iT邦幫忙

2021 iThome 鐵人賽

DAY 19
0

Q1. 什麼是 php 反序列化?

  • 為了讓程式中的物件可以在保存到 persistent database,或者能夠傳輸到其他程式,程式可以將物件的屬性與狀態利用特定的規則編碼,轉為資料序列,這便稱為序列化 (Serialize) ,是許多程式語言都具備的功能,而將被序列化的物件還原的過程就稱為反序列化
  • 許多語言都有序列化的函數,例如PHP、Python、Java 等。

Q2. php 反序列化原理

  • PHP 序列化的基本表達式有下列幾種 (序列中分號、冒號前後都不能有空格,此處為了易讀性才加入空格)
    • boolean

      • <boolean(b)型態> : <值(0或1)>
      • e.g. b:0b:1
    • int

      • <interger(i)型態> : <值 -2147483648~2147483647>
      • e.g. i:666
    • string

      • <string(s)型態> : <名稱長度> : <名稱>
      • e.g. s:4:"Baba"
    • array

      • <array(a)型態> : <array 長度> : { key ; value ; key ; value .....}
      • e.g. a:2:{i:1;s:3:"iam",i:2;s:4:"Baba"}
      • e.g. ['A' => 123, 2 => 'aaa'] 會變為 a:2:{s:1:"A";i:123;i:2;s:3:"aaa";}
      • key 可以使用 int、string,value 則不限
    • object

      • Object (o) 型態 : <object 名稱長度> : <properties 數量> : {key; value; key; value; ...},其中:

        • property 若為 public:則 Key 名稱即等同 property 名稱
        • property 若為 protected:則 Key 名稱為%00*%00<property名稱>
        • property 若為 private:則 Key 名稱需在 property 名稱前面加上 %00<class名稱>%00<property名稱>
      • Object 的 method 不會被序列化。

      • e.g.

        class Babaobject{
        	public $iam;
        	public $Baba = 666;
        	protected $not = "QAQ";
          private $you = True;
        }
        
        • 上述程式,序列化後是:
        O:10:"Babaobject":4:{s:3:"iam";N;s:4:"Baba";i:666;s:6:"%00*%00not";s:3:"QAQ";s:15:"%00Babaobject%00you";b:1;}
        
        • protected $not = "QAQ"; 序列化後,直接印出會看到 s:6:"*not";s:3:"QAQ" ;而 private $you = True; 序列化後,直接印出會看到 s:15:"Babaobjectyou";b:1; 。之所以會看不到 %00 ,是因為在 ascii 中 %00 為空字元,因此無法顯示,但在計算長度時仍可看出其確實存在,因而會比顯示的字元多 2 個字。(因此會看到 *not 的長度是 6)
    • NULL

      • <Null (n) 型態>
      • e.g. N
      • 當變數無賦值時,則會放N

Q3. 反序列化類型?

  • 常見型

    • 在 PHP 中,有許多 magic method 會在特定條件下自動執行,例如:

      • __wakeup :反序列化時觸發
      • __sleep :序列化時觸發
      • __destruct :物件刪除時觸發

      參考資料: https://www.php.net/manual/en/language.oop5.magic.php

    • 舉例來說,如下的程式碼收到 網址?data=O:4:"Flag":0:{} 時,會反序列化出 Flag 物件,並印出 flag。

      <?php
        require('secret.php');
        class Flag {
          function __wakeup() {
            global $flag;
            echo $flag;
          }
        }
        unserialize($_GET['data']);
      

      https://ithelp.ithome.com.tw/upload/images/20211003/201405922MymnlIoOg.png

    • 有些時候我們可以利用竄改資料來達成目的,例如下方的例子,可以看出正常情況下 Flag 物件中的屬性 u 會是一個 User 實例,但我們反序列化時可以改成 Admin ,像是這樣 O:4:"Flag":1:{s:1:"u";O:5:"Admin":0:{}} ,如此便能拿到 flag。

      <?php
      require('secret.php');
      class Flag {
          function __construct() {
              $this->u = new User();
          }
          function __destruct() {
              $this->u->flag();
          }
      }
      
      class User {
      	function flag() {
      		echo "No flag for ya~";
      	}
      }
      
      class Admin {
      	function flag() {
      		global $flag;		
      		echo "Here you go: {$flag}";
      	}
      }
      
      unserialize($_GET['data']);
      
  • 原生型

  • phar 型


上一篇
【第十八天 - 命令執行】
下一篇
【第二十天 - PHP反序列化(2)】
系列文
【CTF衝衝衝 - Web篇】30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言