您好,登錄后才能下訂單哦!
PHP反序列化中如何尋找POP鏈,相信很多沒有經(jīng)驗(yàn)的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
運(yùn)行環(huán)境要求
PHP >= 7.1.3
OpenSSL PHP Extension
PDO PHP Extension
Mbstring PHP Extension
安裝題目環(huán)境
運(yùn)行題目代碼
更多請參考:https://laravel-china.org/docs/lumen/5.7/installation/2402
PS:更新P牛制作的docker環(huán)境 https://github.com/phith0n/code-breaking
在 routes/web.php 文件中,定義了 web 程序的路由,當(dāng)我們以 GET 或 POST 方法訪問 http://website/server/editor 的時(shí)候,程序就會調(diào)用 app/Http/Controllers/EditorController.php 類中的 main 方法。
我們進(jìn)而看 app/Http/Controllers/EditorController.php 文件,很快便會發(fā)現(xiàn)有一個(gè) download 方法中的 $url 變量沒有經(jīng)過任何處理用在了 file_get_contents 函數(shù)中, download 方法代碼如下:
這時(shí)我們便考慮 $url 變量是否可控,如果可控,便可以利用 phar反序列化 。我們回溯尋找 $url 變量來源,會發(fā)現(xiàn)在 doCatchimage 方法中,該變量值是從 $sources 變量來。而 $sources 變量由用戶傳來的 source 參數(shù)決定(通過 http://website/server/editor/?action=Catchimage&source[]=phar://xxx.gif 即可控制 $url 變量),相關(guān)代碼如下:
那么接下來,我們就要尋找可利用的類方法,然后通過 phar反序列化 觸發(fā)漏洞。
在尋找 pop鏈 之前,我們不妨先看看 phpggc 中已有的 4種 關(guān)于 Laravel 框架 RCE 的 payload 生成方法,以便我們更快速的找出本題的 pop鏈 ,其 4種 Laravel 框架 RCE 的 payload 生成方法分別如下:
第1種
其反序列化時(shí),類方法調(diào)用過程如下:
第2種
其反序列化時(shí),類方法調(diào)用過程如下:
第3種
其反序列化時(shí),類方法調(diào)用過程如下:
第4種
其反序列化時(shí),類方法調(diào)用過程如下:
這里我選取 第1種 的 phar反序列化 執(zhí)行結(jié)果圖(題目環(huán)境為 PHP7.1.16 ):
然而本題目的環(huán)境還有一些額外的限制,例如 PHP 版本為 7.2.14 ,且設(shè)置了禁用了如下函數(shù)和類(這個(gè)通過 phpggc 的第一個(gè) Laravel 框架 RCE 生成 phpinfo 函數(shù)的利用 phar 即可看到):
disable_functions: system,shell_exec,passthru,exec,popen,proc_open,pcntl_exec,mail,apache_setenv,mb_send_mail,dl,set_time_limit,ignore_user_abort,symlink,link,error_log disable_classes: GlobIterator,DirectoryIterator,FilesystemIterator,RecursiveDirectoryIterator
由于在 PHP7.x 版本中,很多函數(shù)禁止動態(tài)調(diào)用了,加上上面的這些限制,所以我們還需要尋找其他利用點(diǎn),結(jié)合上述 POP 鏈,完成寫 shell 。
我們可以發(fā)現(xiàn)上面的4種 RCE 入口點(diǎn)都是從 PendingBroadcast 類的 __destruct 方法開始的,那么我們著重搜索 dispatch 方法和 __call 方法。經(jīng)過一番搜索,發(fā)現(xiàn) ValidGenerator 類中的 __call 比較好利用。
我們可以看到其代碼中先調(diào)用了 call_user_func_array 函數(shù),然后將 call_user_func_array 函數(shù)的執(zhí)行結(jié)果又傳入 call_user_func 函數(shù),只要我們能控制住 call_user_func_array 函數(shù)的執(zhí)行結(jié)果,相當(dāng)于 call_user_func 函數(shù)的兩個(gè)參數(shù)都可控,這樣我們便可以調(diào)用任意類方法。
我們接著搜索可以用于控制 call_user_func_array 函數(shù)執(zhí)行結(jié)果的類,這里我找到了 DefaultGenerator 類的 __call 方法,我們可以看到返回值 $this->default 完全可控。
現(xiàn)在 call_user_func(res) 中的兩個(gè)參數(shù)都可控了。那么如果我們想寫shell,就要調(diào)用 file_put_contents 函數(shù),而這個(gè)函數(shù)需要兩個(gè)參數(shù),所以直接通過 call_user_func 函數(shù)是無法使用該函數(shù)的,我們需要通過 call_user_func_array 函數(shù)來使用 file_put_contents 函數(shù),用法形如: call_user_func_array('file_put_contents',array('shell.php','test')) 。
通過直接搜索 call_user_func_array 函數(shù),我們會發(fā)現(xiàn)兩個(gè)比較好利用的類函數(shù)。但是這里的第一個(gè) ClosureWrapper 類我們無法利用,所以得利用 ReturnCallback 類的 invoke 方法,具體代碼如下:
很明顯 invoke 方法兩個(gè)參數(shù)都可控,現(xiàn)在我們只要構(gòu)造好一個(gè) Invocation 類對象即可。通過搜索,我們會發(fā)現(xiàn) Invocation 是一個(gè)接口,那么我們找到他的實(shí)現(xiàn)類即可。這里我找到了 StaticInvocation 類來實(shí)現(xiàn)上訴功能,其代碼具體如下:
這樣子,我們的整個(gè) POP鏈 就構(gòu)造好了。下面是 exp :
{ { ; ; (, ){ ; ; } } }; { { ; ( ){ ; } } { ; ; ; (, , ) { ; ; ; } } }; { { ; () { ; } } }; { { ; (){ ; } } }; { ; (,); (); (); (); (,(,),); (,); ; ; () () : ; (); (); (); (); (,); (); };
我們再通過下面這張圖片,來理清整個(gè) POP鏈 的調(diào)用過程。
看完上述內(nèi)容,你們掌握PHP反序列化中如何尋找POP鏈的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。