利用 procfs 共 AFR/AFW 的影響升級

咱常在會拄著一寡會當隨咱寫檔案抑是讀檔案的漏縫,像咱捷講著的 LFI 嘛算是一款任意讀檔的利用——毋過,讀罔讀,寫罔寫,咱嘛毋是逐改攏好運,會當拄著彼款共內容寫(讀)落去就有 RCE 的情境。

咱若是拄著較有限制的環境,閣有啥物招通用咧?

一切攏是檔案!

著,佇 UNIX 系統頂懸,咱一切的資源攏會用「檔案描述子(file descriptor)」的模樣來共展出來。

所謂的「Everything is a file」是 UNIX 系統內底一个誠重要的理念,甚至凡勢會使講這是伊成功的一个關鍵,予咱會當輕鬆共資源掛起去。這款特性講趣味是趣味,毋過煞會當予咱佇檔案這層的攻擊面湠了閣較闊——這自然就是咱這擺的重點矣。

今仔日咱就來看一寡利用各種 procfs 下跤的「檔案」來達成一寡利用的步數!

欲讀啥?

若是有一个 LFI-ish 的漏縫佇咧,毋過佇 server 頂無啥隨咱上傳、控制檔案內容的功能,咱會當按怎予這个漏縫的影響加較大咧?

咱基本的物件,像啥物 /proc/self/cmdline/proc/self/environ 遐橐個束個的,佇遮就先閬過,逐家家己去看 hacking cheatsheet 就好矣,佇遮咱來講寡較特別的物件!

佇 hxp CTF 2021: includer's revenge 彼題,有一个蓋出名的非預期解,就是彼个靠一大捾 PHP filter 來鬥出任意的檔案內容的招,予咱現代的 PHP LFI 百面會變做 RCE。毋過,逐家敢閣知影/會記得講伊的標準解是生啥款?簡單來講就三步爾爾:

  1. 利用題目內底 readfile 的功能來讀一个大組閣慢的 HTTP 資源 (閣愛維持連線開咧)
  2. 利用 Nginx 的 fastcgi_buffering 來生一个 tempfile
  3. 共 ta̋nn 生出來的 tempfile 引入來 --> Pwned!

尾仔,閣有人發現講免有 readfile 就會當生 tempfile 的招 予咱來 include 矣。彼是欲按怎創咧?咱干焦需要用 Nginx 內底 client body buffer 的特性就好矣!

        include!!!
            |
   傷大矣    |
生tempfile囥 |  共tempfile刣掉
     |      |        |
     v      v        v
---------------------------------->
    [---------------]
        上傳大檔案

咱若是上傳一个足大的檔案起去,nginx 就會想講按呢阮 memory 食袂落去,愛先共規个 request body 暫時囥去一个檔案,按呢才較穩——彼就是咱彼个 tempfile 生出來的時機。畢竟是 request body,自然彼个檔案內容是咱完全有法度控制的,佇當咧傳檔案的時,咱就會當共彼个 tempfile 去 include 入來,按呢就隨有 RCE 用矣。

毋過,咱會拄著幾若个問題,第一是,彼个檔案名是隨機生的,咱誠僫臆;第二是,檔案傳煞會隨 hőng 刣掉,照按呢看,咱差不多是倚欲無機會直接共 tempfile 讀入來乎。

當然,咱原仔閣有一招!檔案本身揣無是揣無,毋過無要緊,server 欲生 tempfile 時就是去開一个檔案,啊若是開檔案,自然就會有一个 /proc/<nginx pid>/fd/<fd> 生出來矣,咱去 include 彼个 fd 就好,毋免閣管彼个檔案是啥物名矣!

讀到遮,你凡勢會想講這干焦是一个佇 Nginx 通好用的步數爾爾——毋過毋是喔,佇誠濟 server 佮 framework 攏有這款的特性!

譬論講,佇 CTF,UIUCTF 2022 - spoinkApache Tomcat)佮 MaltaCTF 2025 Quals - Enterprise Template as a Service (.NET, write-up by maple3142)、攏有用著這款「傳大檔案起去會生 tempfile」的特性去耍 LFI。另外,遮嘛有一篇佇 Rails 捷會用著的 Rack 頂利用著仝款耍法的文:New Method to Leverage Unsafe Reflection and Deserialisation to RCE on Rails

欲寫啥?

閣有一寡情境是你有 AFW(arbitrary file write)矣,毋過規个環境鎖牢牢,無啥所在通予咱寫,按呢欲按怎創咧?

這款情形的重點就佇咧一寡崁名管道(anonymous pipes)矣,通常彼是用來做 IPC 的,毋過咱若是有 AFW 嘛是會當寫入去遐的管道來做一寡代誌!

Node.js

佇舊年的 Hexcon24 有一篇研究講著一个佇 Node.js 頂揣著 AFW (arbitrary file write) 漏縫了後欲利用的新招!

Node.js 本身是 single-thread,毋過伊有才調去處理 asynchronous 的操作,就是倚靠一个號做 libuv 的 library。libuv 會用著一種崁名管道來處理內部事件的通知。重點來矣,這寡 pipes 也會出現佇 /proc/<pid>/fd/ 內底。

上好耍的一點是:就算講規个系統是 read-only,你原仔嘛會當共這寡 pipe file descriptors 囥資料入去!因為 pipe 其實是 kernel 內部的 pipefs 咧處理的。

這就為咱駭客開一扇門矣。伊若有 AFW 漏縫,毋免用伊去寫一个實體的檔案,煞是會當直接對 Node.js process 的 pipe descriptor (譬論講 /proc/12345/fd/5) 寫資料入去。

佇咧駭客去對 libuv 的 pipe 寫資料的時陣,libuv 的 event handler 會去搝遐的資料,而且閣會共遐的資料當做是特別的 C 語言結構 (uv__signal_msg_t) 來解析。

這个 uv__signal_msg_t 結構內底,有一个指標 (handle),會指去另外一个號做 uv_signal_s 的結構。閣 uv_signal_s 這个結構內底,有一个誠重要的成員,號做 signal_cb,這是一个 function pointer (函式指標)。

講甲按呢敢若有淡薄仔複雜 XD 簡單講就是 uv__signal_msg_t -> uv_signal_s -> signal_cb (function ptr) 這款的關係啦。

簡單來講,駭客會當生一个檔案,內容就是彼規个惡意的結構:

  1. 佇伊欲寫入的資料內底,先假造一个 uv_signal_s 結構。
  2. 共這个假結構內的 signal_cb function pointer,設定做伊想欲執行的任意記憶體位置。
  3. 閣再舞一个假的 uv__signal_msg_t 結構出來,共伊內底的 handle 指標,指去頭前彼个假 uv_signal_s 的所在。

共這規包物件,透過 file write 漏縫,寫入去 Node.js 的 pipe descriptor 了後,只要條件攏有合,libuv 的 event handler 就會戇戇仔去走 signal_cb 所指的 address,駭客就成功共程式的執行控制牢矣,造成 RCE!

這部份就較「pwn」一寡矣,詳細會當去看𪜶的完整研究。毋過仝款,這嘛毋但會當用佇 Node.js,佇 Julia 抑是別个有用著 libuv 的攏會當按呢舞喔!

Python + multiprocessing

佇 Python 的 multiprocessing,爸母 process 欲佮細漢 process 互相溝通是透過 pipe fd + pickle,啊咱攏知影若是會當烏白去做 pickle 反序列化是誠危險的代誌。所以,咱若是會當寫資料去彼个 fd 內底,就會當透過 pickle 反序列化造成 RCE 矣。

我有共這个步數出佇今年的 HITCON CTF,會當來遮看我寫的 write-up https://blog.splitline.tw/hitcon-ctf-2025-taigi/#web-imgc0nv