PHP 繞過 disable_functions 踩坑記

2019-01-05 security PHP Linux

最近看到很多文章講到 bypass PHP disable functions 的文章,但其實這也不是什麼新的東西了

很久以前就蒐集到過不少相關的文章,印象中最早從現在已經萬年維修的 wooyun drops 看到相關文章

當然也已經有整理很齊全的github,於似乎就順手整理相關資料順便重現一波

Lab.

文章提到想要繞過 PHP 的 disable funtioncs 大概有四種方法

  1. 可能有一些沒 disable 到的漏網之魚
  2. 透過第三方程式弱點像是 ImageMagick 或 Shellshock 等等
  3. apache 啟用了 mod_cgi 並且允許覆蓋 .htaccess
  4. 透過設定環境變數 LD_PRELOAD 來 hijack 系統層級函式

這篇踩坑記主要在第四點上

根據 wooyun drops 的文章來看,中心思想就是使用 putenv 設定 LD_PRELOAD

然後使用 mail 函數會用到系統 sendmail binary 的特性導致 function hijack,進而

繞過 PHP 的 disable functions,但缺點是你必須要覆蓋到會使用到的 function

否則就無法觸發,而 freebuf 的這篇 无需sendmail:巧用LD_PRELOAD突破disable_functions

提到使用編譯器提供的 attribute 屬性來優先執行,這樣就可以無需覆蓋到任何函數一樣可以達到效果

甚至系統最後沒有 sendmail 也無妨,在這一次重現中,主要測試了兩個運行方法,PHP CLI 與

apache 的 php_mod,CLI 方面穩定觸發沒問題,但 apache 的測試一直不見效果,PoC 如下

<?php 
    putenv('LD_PRELOAD=PATH_TO_SO');
    mail('', '', '', '-bv');
?>

其中 so 中覆蓋的函數會執行 system("touch /tmp/HACKED")

有鑑於此想要搞清楚原因為和,打算用 strace 來看看到底怎麼回事,PHP CLI 方面可以很清楚

看到讀取 PHP 文件,覆蓋 LD_PRELOAD 與呼叫 sendmail,但 apache 有 prefork 不容易 strace

所以使用 ps auxw | grep sbin/apache | awk '{print"-p " $2}' | xargs strace

對所有的 apache process 使用 strace。

後來發現的確有觸發到 sendmail 也確實執行了 execve("touch /tmp/HACKED"),但看了看我的

tmp 目錄就是沒看見 HACKED 檔案,難道我的 PHP 壞掉了 ?!

後來注意到 tmp 目錄下有類似這樣的路徑 /tmp/systemd-prive-HASH-apche.service 這樣的資料夾

進去一看,果然 HACKED 檔案好好地躺在那,迅速查了一下發現這是 systemd 的 feature

當透過 systemd 啟動的 service 用了 privateTmp 參數,該 service 的 tmp 資料夾就會用這種方式存在

隔離每個 service 的 tmp 避免互相干擾

Conclusion

結論是,自己對 Linux 不熟才繞了這麼大一圈

慚愧…慚愧…

References