日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

浅析php反序列化字符串逃逸

發布時間:2024/9/30 php 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅析php反序列化字符串逃逸 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:

php反序列化字符串逃逸之前沒有詳細的學習過,所以遇到題目看的有點懵,這次好好學習一下。

反序列化的特點

首先要了解一下反序列化的一些特點:

  • php在反序列化時,底層代碼是以 ; 作為字段的分隔,以 } 作為結尾,并且是根據長度判斷內容的 ,同時反序列化的過程中必須嚴格按照序列化規則才能成功實現反序列化 。
  • class A{public $name='shy';public $pass='123456'; }$lemon = new A(); echo serialize($lemon); #反序列化后的結果為: O:1:"A":2:{s:4:"name";s:3:"shy";s:4:"pass";s:6:"123456";}

    超出的部分并不會被反序列化成功,如下圖:

    這說明反序列化的過程是有一定識別范圍的,在這個范圍之外的字符都會被忽略,不影響反序列化的正常進行。而且可以看到反序列化字符串都是以";}結束的,那如果把";}添入到需要反序列化的字符串中(除了結尾處),就能讓反序列化提前閉合結束,后面的內容就相應的丟棄了。

    2. 長度不對應的時候會報錯

    在反序列化的時候php會根據s所指定的字符長度去讀取后邊的字符。如果指定的長度錯誤則反序列化就會失敗

    3. 可以反序列化類中不存在的元素

    <?php $str='O:1:"A":3:{s:4:"name";s:3:"shy";s:4:"pass";s:6:"123456";s:5:"pass2";s:6:"123456";}'; var_dump(unserialize($str));


    這些特點一定要清楚,否則在做題時可能就因為這些基礎知識而做出不來。

    字符串逃逸

    0x0:特點

    這類CTF題目的本質是因為改變序列化字符串的長度,從而導致反序列化漏洞。

    具體的話大致都是因為php序列化后的字符串經過了替換或者修改,導致字符串長度發生變化。而且總是先進行序列化,再進行替換修改操作。

    0x01:過濾后字符變多

    實驗代碼:

    #參考字節脈搏實驗室 <?php function lemon($string){$lemon = '/p/i';return preg_replace($lemon,'ww',$string); } $username = $_GET['a']; $age = '20'; $user = array($username,$age); var_dump(serialize($user)); echo "<br>";$r = lemon(serialize($user)); var_dump($r); var_dump(unserialize($r)); ?>

    正常輸入的話

    因為我們輸入的是apple,含有兩個p,所以會被替換成四個w,但是發現長度并沒有變化,因此根據反序列化的特點,指定的長度錯誤則反序列化就會失敗。

    但是正是因為存在這個過濾,我們便可以去修改age的值,首先來看一下,原來序列化后";i:1;s:2:"20";}長度為16,我們已經知道了當輸入一個p會替換成ww,所以如果輸入16個p,那么會生成32個的w,所以如果我們輸入16個p再加上構造的相同位數的";i:1;s:2:"30";},恰好是32位,即

    32 pppppppppppppppp";i:1;s:2:"30";} 經過替換后 32 wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

    所以非常明顯了,在過濾后的序列化時會被32個w全部填充,從而使構造的代碼 ";i:1;s:2:"30";} 成功逃逸,修改了age的值,而原來的那";i:1;s:2:"20";}則被忽略了因為反序列化字符串都是以";}結束的,我們傳入的";i:1;s:2:"30";}已經在前面成功閉合了

    0x02:過濾后字符變少

    搭建一個簡單的實驗環境代碼如下:

    #參考Mr. Anonymous師傅的代碼學習 <?php function str_rep($string){return preg_replace( '/lemon|shy/','', $string); }$test['name'] = $_GET['name']; $test['sign'] = $_GET['sign']; $test['number'] = '2020'; $temp = str_rep(serialize($test)); printf($temp); $fake = unserialize($temp); echo '<br>'; print("name:".$fake['name'].'<br>'); print("sign:".$fake['sign'].'<br>'); print("number:".$fake['number'].'<br>'); ?>

    如果正常輸入的話,回顯出的結果如下:

    已經知道number的值是固定的2020

    如果想要修改這個值,就要在sign中加入";s:6:"number";s:4:"2000";},其長度為27,仔細觀察便可以發現是利用反序列化的第一個特點底層代碼是以;作為字段的分隔,以}作為結尾,想要將之前的number擋在序列化之外,從而可以反序列化自己構造的,但直接輸入發現是不行的,并沒有將我們輸入的給反序列化了


    在實驗代碼中有替換功能,當遇到lemon 或 shy會自動替換為空,也這里用shy做為name的輸入,故意輸入敏感字符,替換為空之后來實現字符逃逸,三個字符變成零個字符,吃掉了三個字符,輸入8個shy,也就是騰出了24個字符的空間,利用這個空間來進行構造,由于";s:4:"sign";s:54:"hello成了name的內容,所以還要在后面加個";s:4:"sign";s:4:"eval作為sign序列化的內容。


    這個構造其實也很簡單,因為經過測試發現,";s:4:"sign";s:這個長度其實是不變的,變的是我們在參數sign輸入的參數,這里假設輸入9個shy,那么吃掉了27個字符,對應的就需要添加27個字符,目前";s:4:"sign";s:這個長度為15,所以還差12個,因為整個payload肯定是不超過100個字符的,所以加上后面的長度,也就是";s:4:"sign";s:xx:",這個長度為19,因此我們要輸入的字符只需8個即可

    payload:

    http://127.0.0.1/1.php ?name=shyshyshyshyshyshyshyshyshy &sign=hello123";s:4:"sign";s:4:"eval";s:6:"number";s:4:"2000";}


    這樣便可以將number的值給更改了,原理的話就是這樣,做題時還要多動手進行測試。

    總結

    以上是生活随笔為你收集整理的浅析php反序列化字符串逃逸的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。