淺談php序列化字符串逃逸問題


0x00 前言

這幾天做了兩道有關php反序列化字符逃逸的題目,故來自己本地實驗總結一下,以后可以時不時拿起來看.

這種題目有個共同點:

  1. php序列化后的字符串經過了替換或者修改,導致字符串長度發生變化.
  2. 總是先進行序列化,再進行替換修改操作.

經典題目:

  1. [0CTF 2016]piapiapia (替換變長)
  2. [安洵杯 2019]easy_serialize_php (替換變短)

0x01 漏洞淺析

第一種情況:替換修改之后導致序列化字符串長度變長

  1. 先看一段php序列化的代碼(本代碼基於7.0.9版本的php,經過測試較低版本的php會使"被轉義導致實驗失敗:
  2. 代碼功能很簡單,輸入name,並和sign一同傳入到user數組中,user數組序列化后的字符串經過test函數檢測之后,輸出反序列化之后的結果.
  3. 關於php反序列化引擎在進行反序列化的時候是以字符長度來進行判斷的,關於這一點,前言中的參考文章已經解釋的很詳細了,這里不再贅述.
  4. 下面進行漏洞測試,通過修改name的值從而改變sign的值.
    1. 關鍵點在於test函數,這個函數檢測並替換了非法字符串,看似增加了代碼的安全系數,實則讓整段代碼更加危險.test函數中檢測序列化后的字符串,如果檢測到了非法字符'x',就把它替換為'ha'.
    2. 如果輸入name=evALx
    3. 可以看到被替換成了'evALha',這個字符串長度為6,從而導致反序列化失敗,無法輸出結果.利用這個漏洞,就可以對sign的值進行修改.輸入name=evALxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";i:1;s:14:"hello hackerrr";}
    4. 可以就看到sign的值被成功修改.
  5. 原因分析
    1. test函數把'x'替換成'ha',換句話來說,就是把一個字符替換成了兩個字符,造成了序列化字符串的"膨脹".
    2. 首先來考慮要注入的數據,在這個例子中把sign替換為"hello hackerrr",這個字符串在本實驗的序列化結果是i:1;s:14:"hello hackerrr,由於要閉合name的雙引號以及結束的花括號,所以payload應該是";i:1;s:14:"hello hackerrr";}
    3. 下面來考慮長度溢出,payload的字符串的長度是29,所以要在name中輸入29個x,再加上evAL,整體長度就是62,在經過test函數替換之后,x被替換成了ha,如下圖所示:
    4. 溢出的部分成功逃逸,經過雙引號閉合name,以及閉合結束時的花括號,導致sign被成功修改.

第二種情況:替換之后導致序列化字符串長度變短

  1. 本地實驗代碼如下:

  2. 輸入name和sign,number值是固定的'2020',經過[序列化->敏感字替換為空(長度變短)->反序列化]的過程之后再輸出結果.

  3. 通過輸入name和sign修改number:
    payload:name=testtesttesttesttesttest&sign=hello";s:4:"sign";s:4:"eval";s:6:"number";s:4:"2000";}

  4. 原因分析:
    在str_rep函數中如果檢測到'php','test'關鍵字就把其替換為空,那么就利用這一點,我們故意輸入敏感字符,替換為空之后來實現字符逃逸.(注意考慮閉合問題)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM