第一个没有作业的寒假终于来了,但是在家感觉瞬间失去了在学校里平日的那种积极性,感觉变得越来越咸鱼。于是就打算在寒假的时候认真学习一下CTF,好歹不要虚度光阴。
打卡不一定每天都会坚持,但是感觉只要在博客上更新了笔记就可以在一定程度上督促自己的学习。这里会写下每天写题的时候遇到的新的知识以及部分做题笔记,还会有一些有意思的地方。
Bugku:备份是个好习惯
http://123.206.87.240:8002/web16/
点进去是一堆奇怪的东西:
d41d8cd98f00b204e9800998ecf8427ed41d8cd98f00b204e9800998ecf8427e
看起来有md5的特征,但是md5往往只有16或者32位,这里却有64位。
根据题目提示的“备份是个好习惯”猜测可能会有源码泄露:
http://123.206.87.240:8002/web16/index.php.bak
发现返回HTTP 200请求,于是乎下载,得到泄露的源码:
<?php
include_once "flag.php";
ini_set("display_errors", 0);
$str = strstr($_SERVER['REQUEST_URI'], '?');
$str = substr($str,1);
$str = str_replace('key','',$str);
parse_str($str);
echo md5($key1);
echo md5($key2);
if(md5($key1) == md5($key2) && $key1 !== $key2){
echo $flag."取得flag";
}
?>
有几个不懂的地方,现场补缺补漏:
- $_SERVER 中的 REQUEST_URI : 返回的是包含参数的URI,例如请求的是 http://123.206.87.240:8002/web16/index.php?key1=123 返回的则是/web16/index/php?key1=123
- strstr :查找并返回母串中子串开始处到母串结尾处的部分,例如这里返回的是 ?key1=123
- substr :返回母串指定处开始的字串。这里返回的是key1=123
- parse_str : 处理字符串
通过阅读代码发现这题上面的64位字符就是key1和key2连在一起(好像并没有什么ruan用。。。otz
在中间还有一个对传入参数的一个replace过滤,这里可以用kekeyy重写来绕过这个检测
最后要求传入的key1和key2值不一样但是$md5()之后的数值要一样,但是两者的值不一样。
这里可以利用$md5()函数的无法处理数组的特性,传入key1和key2为数组,$md5()函数就会返回NULL来绕过判断。
Payload: ?kekeyy1[]=123&kekeyy2[]=1234
这边也看到CSDN上有一个用==比较漏洞的方法也蛮有意思的,这里Mark一下:
https://blog.csdn.net/zpy1998zpy/article/details/80582974
如果两个字符经MD5加密后的值为 0exxxxx形式,就会被认为是科学计数法,且表示的是0*10的xxxx次方,还是零,都是相等的。
下列的字符串的MD5值都是0e开头的:
QNKCDZO
240610708
s878926199a
s155964671a
s214587387a
s214587387a
Bugku: strcmp比较字符串
<?php
$flag = "flag{xxxxx}";
if (isset($_GET['a'])) {
if (strcmp($_GET['a'], $flag) == 0) //如果 str1 小于 str2 返回 < 0; 如果 str1大于 str2返回 > 0;如果两者相等,返回 0。
//比较两个字符串(区分大小写)
die('Flag: '.$flag);
else
print 'No';
}
?>
这题要求比较传入的a和flag的值,如果一致就返回flag,显然这题要利用漏洞。
这里要利用的漏(特)洞(性)就是strcmp函数无法处理数组的漏洞,根据PHP的官方文档,在php5.2版本之前将数组丢入strcmp中比较会返回-1,而在5.3之后的版本中则返回0(和比较一致返回值一样)(这里想吐槽一下这样更新不明摆着坑人么)
于是传入payload: ?a[]=1 就可以拿到flag了
Comments | NOTHING