咱常在會拄著一寡會當隨咱寫檔案抑是讀檔案的漏縫,像昨昏講著的 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。毋過,逐家敢閣知影/會記得講伊的標準解是生啥款?簡單來講就三步爾爾:
readfile
的功能來讀一个大組閣慢的 HTTP 資源 (閣愛維持連線開咧)fastcgi_buffering
來生一个 tempfile尾仔,閣有人發現講免有 readfile
就會當生 tempfile 的招 予咱來 include 矣。彼是欲按怎創咧?咱干焦需要用 Nginx 內底 client body buffer 的特性就好矣!
include!!!
|
傷大矣 |
生tempfile囥 | 共tempfile刣掉
| | |
v v v
---------------------------------->
[---------------]
上傳大檔案
咱若是上傳一个足大的檔案起去,nginx 就會想講按呢阮 memory 食袂落去,愛先共規个 request body 暫時囥去一个檔案來較穩——彼就是咱彼个 tempfile 生出來的時機。畢竟是 request body,自然彼个檔案內容是咱完全有法度控制的,佇當咧傳檔案的時,咱就會當共彼个 tempfile 去 include 入來,按呢就隨有 RCE 用矣!
讀到遮,你凡勢會想講這干焦是一个佇 Nginx 通好用的步數爾爾——毋過毋是喔,佇誠濟 server 佮 framework 攏有這款的特性!
譬論講,佇 CTF,UIUCTF 2022 - spoink(Apache Tomcat)佮 MaltaCTF 2025 Quals - Enterprise Template as a Service(.NET)攏有用著這款「傳大檔案起去會生 tempfile」的特性去耍 LFI。
閣有一寡情境是你有 AFW(arbitrary file write)矣,毋過規个環境鎖牢牢,無啥所在通予咱寫,按呢欲按怎創咧?
這款情形的重點就佇咧一寡崁名管道(anonymous pipes)矣,通常彼是用來做 IPC 的,毋過咱若是有 AFW 嘛是會當寫入去遐的管道來做一寡代誌!
佇舊年的 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) 這款的關係啦。
簡單來講,駭客會當生一个檔案,內容就是彼規个惡意的結構:
uv_signal_s
結構。signal_cb
function pointer,設定做伊想欲執行的任意記憶體位置。uv__signal_msg_t
結構出來,共伊內底的 handle 指標,指去頭前彼个假 uv_signal_s
的所在。共這規包物件,透過 file write 漏縫,寫入去 Node.js 的 pipe descriptor 了後,只要條件攏有合,libuv 的 event handler 就會戇戇仔去走 signal_cb 所指的 address,駭客就成功共程式的執行控制牢矣,造成 RCE!
這部份就較「pwn」一寡矣,詳細會當去看in的完整研究。毋過仝款,這嘛毋但會當用佇 Node.js,佇 Julia 抑是別个有用著 libuv 的攏會當按呢舞喔!
佇 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