漏洞原理分析
先看源码
<?php
$SELF_PAGE = substr($_SERVER['PHP_SELF'],strrpos($_SERVER['PHP_SELF'],'/') 1);
if ($SELF_PAGE = "unser.php"){
$ACTIVE = array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','active open','','active','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','');
}
$PIKA_ROOT_DIR = "../../";
include_once $PIKA_ROOT_DIR.'header.php';
class S{
var $test = "pikachu";
function __construct(){
echo $this->test;
}
}
$html='';
if(isset($_POST['o'])){
$s = $_POST['o'];
if(!@$unser = unserialize($s)){
$html.="<p>大兄弟,来点劲爆点儿的!</p>";
}else{
$html.="<p>{$unser->test}</p>";
}
}
?>
漏洞成因:
一.参数可控
从源码可以看到反序列化的变量是post请求的,post请求变量名为o,通过抓包发现我们输入框输入的值,正好赋值给Post变量o

二.实现了unserialize()函数
这一点是肯定的,没有这个函数这里肯定就无法反序列化
三.调用了魔法函数
__construct函数可利用
四.没有过滤
没有对传参进行过滤,否则无法构成目的Payload。
实战中要更具情况来构造payload,能利用的漏洞也远不止xss
phar://伪协议
除了unserialize反序列化之外 ,另一种能够反序列化方式是利用 phar:// 协议触发反序列化,前提是完全可控的文件名。
这个方法是在BlackHat 大会上的 Sam Thomas 分享了 file Operation Induced Unserialization via the “phar://” Stream Wrapper ,该研究员指出该方法在文件系统函数 ( file_get_contents 、 unlink 等)参数可控的情况下,配合 phar://伪协议 ,可以不依赖反序列化函数 unserialize() 直接进行反序列化的操作。
什么是phar
官方文档:
https://www.php.net/manual/zh/book.phar.php
简单来说,phar是PHP提供的一种压缩和归档的方案,并且还提供了各种处理它的方法。
phar结构
由四部分组成:
一:stub
即用来标识phar 文件的部分,类似MZ头。格式为
<?php
Phar::mapPhar();
include 'phar://phar.phar/index.php';
__HALT_COMPILER();
?>
二:manifest describing the contents
phar文件本质上是一种压缩文件,其中每个被压缩文件的权限、属性等信息都放在这部分,也存储用户自定义的meta-data,这是用来攻击的入口,最核心的地方

三:the file contents
被压缩文件的内容
四:signature for verifying Phar integrity
可选项,即签名。
demo
根据phar文件结构我们来自己构建一个phar文件,php内置了一个Phar类来处理相关操作。
注意:要将php.ini中的phar.readonly选项设置为Off,否则无法生成phar文件。不要只读

如果修改了之后在phpinfo上还是On的话记得把这行最前面的分号删掉,这样就行了
