PHP代码审计——Day3-Snow Flake
漏洞解析
// 实现了一个基本的MVC(Model-View-Controller)结构,通过动态加载控制器类和数据,并调用控制器的方法来实现基本的页面渲染。
// 自动加载函数,用于动态加载类文件。当使用尚未定义的类时,PHP会自动调用该函数来加载类文件。此处,__autoload 函数会尝试加载与类名 $className 对应的文件。
function __autoload($className) {
include $className;
}
$controllerName = $_GET['c'];
$data = $_GET['d'];
// 检查指定的类是否已经定义。如果控制器类已经定义,则表示该类存在,可以实例化
if (class_exists($controllerName)) {
$controller = new $controllerName($data['t'], $data['v']);
$controller->render();
} else {
echo 'There is no page with this name';
}
// 控制器类负责处理业务逻辑和渲染视图。在构造函数中,它接收模板名称和变量数组作为参数,并将它们存储在私有属性中。render() 方法根据变量数组中的内容来渲染视图。
class HomeController {
private $template;
private $variables;
public function __construct($template, $variables) {
$this->template = $template;
$this->variables = $variables;
}
public function render() {
if ($this->variables['new']) {
echo 'controller rendering new response';
} else {
echo 'controller rendering old response';
}
}
}
考察点:文件包含漏洞;实例化任意对象漏洞
1、文件包含漏洞
class_exists
:(PHP 4, PHP 5, PHP 7)
- 功能 :检查类是否已定义
- 定义 : bool class_exists ( string $class_name[, bool $autoload = true ] )
$class_name 为类的名字,在匹配的时候不区分大小写。默认情况下 $autoload 为 true ,当 $autoload 为 true 时,会自动加载本程序中的 __autoload 函数;当 $autoload 为 false 时,则不调用 __autoload 函数。
使用class_exists()
函数来判断用户传过来的控制器是否存在,默认情况下,如果程序存在 __autoload
函数,那么在使用 class_exists()
函数就会自动调用本程序中的 __autoload
函数,文件包含漏洞就出现在这个地方。攻击者可以使用路径穿越来包含任意文件,当然使用路径穿越符号的前提是 PHP5~5.3(包含5.3版本)版本 之间才可以。例如类名为: ../../../../etc/passwd
的查找,将查看passwd文件内容
2、实例化任意对象漏洞
实例化类的类名$controllerName
和 传入类的参数$data
都是用户输入可控,于是可以通过这个漏洞,调用php代码库的任意构造函数。即使代码本身不包含易受攻击的构造函数,我们也可以使用PHP的内置类 SimpleXMLElement
来进行 XXE 攻击,进而读取目标文件的内容,甚至命令执行(前提是安装了PHP拓展插件expect)。
SimpleXMLElement
:(PHP 5, PHP 7)
- 功能 :用来表示XML文档中的元素,为PHP的内置类。
demo演示
<?php
$xml = <<< EOF
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "file:///C:/PHP/flag.txt">
]>
<x> &xxe;</x>
EOF;
$xml_class = new SimpleXMLElement($xml, LIBXML_NOENT);
var_dump($xml_class);
?>
构造payload:?c=SimpleXMLElement&d=xml文本
参考这位师傅的: