任意文件讀取漏洞
所謂文件讀取漏洞,就是攻擊者通過一些手段可以讀取服務器上開發(fā)者不允許讀到的文件。
從整個攻擊過程來看,它常常作為資產信息搜集的一種強力的補充手段,服務器的各種配置文件、文件形式存儲的密鑰、服務器信息(包括正在執(zhí)行的進程信息)、歷史命令、網絡信息、應用源碼及二進制程序都在這個漏洞觸發(fā)點被攻擊者窺探。
文件讀取漏洞常見觸發(fā)點
Web語言
PHP
PHP標準函數中有關文件讀的部分不再詳細介紹,這些函數包括但可能不限于:file_get_contents()、file()、fopen()函數(及其文件指針操作函數fread()、fgets()等),與文件包含相關的函數(include()、require()、include_once()、require_once()等),以及通過PHP讀文件的執(zhí)行系統(tǒng)命令(system()、exec()等)。這些函數在PHP應用中十分常見,所以在整個PHP代碼審計的過程中,這些函數會被審計人員重點關注。
除了上面提到的標準庫函數,很多常見的PHP擴展也提供了一些可以讀取文件的函數。例如,php-curl擴展(文件內容作為HTTP body)涉及文件存取的庫(如數據庫相關擴展、圖片相關擴展)、XML模塊造成的XXE等。
Python
與PHP不同的是,Python的Web應用更多地傾向于通過其自身的模塊啟動服務,同時搭配中間件、代理服務將整個Web應用呈現給用戶。用戶和Web應用交互的過程本身就包含對服務器資源文件的請求,所以容易出現非預期讀取文件的情況。因此,我們看到的層出不窮的Python某框架任意文件讀取漏洞也是因為缺乏統(tǒng)一的資源文件交互的標準。漏洞經常出現在框架請求靜態(tài)資源文件部分,也就是最后讀取文件內容的open函數,但直接導致漏洞的成因往往是框架開發(fā)者忽略了Python函數的feature,如os.path.join()函數。
很多開發(fā)者通過判斷用戶傳入的路徑不包含“.”來保證用戶在讀取資源時不會發(fā)生目錄穿越,隨后將用戶的輸入代入os.path.join的第二個參數,但是如果用戶傳入“/”,則依然可以穿越到根目錄,進而導致任意文件讀取。這是一個值得我們注意并深思的地方。除了python框架容易出這種問題,很多涉及文件操作的應用也很有可能因為濫用open函數、模板的不當渲染導致任意文件讀取。比如,將用戶輸入的某些數據作為文件名的一部分(常見于認證服務或者日志服務)存儲在服務器中,在取文件內容的部分也通過將經過處理的用戶輸入數據作為索引去查找相關文件,這就給了攻擊者一個進行目錄穿越的途徑。與PHP相同,Python的一些模塊可能存在XXE讀文件的情況。此外,Python的模板注入、反序列化等漏洞都可造成一定程度的任意文件讀取,當然,其最大危害仍然是導致任意命令執(zhí)行。
Java
除了Java本身的文件讀取函數FileInputStream、XXE導致的文件讀取,Java的一些模塊也支持“file://”協議,這是Java應用中出現任意文件讀取最多的地方,如Spring Cloud Config Server路徑穿越與任意文件讀取漏洞(CVE-2019-3799)、Jenkins任意文件讀取漏洞(CVE-2018-1999002)等。
Ruby
在CTF線上比賽中,Ruby的任意文件讀取漏洞通常與Rails框架相關。到目前為止,我們已知的通用漏洞為Ruby On Rails遠程代碼執(zhí)行漏洞(CVE-2016-0752)、Ruby On Rails路徑穿越與任意文件讀取漏洞(CVE-2018-3760)、Ruby On Rails路徑穿越與任意文件讀取漏洞(CVE-2019-5418)。
Node
目前,已知Node.js的express模塊曾存在任意文件讀取漏洞(CVE-2017-14849)。CTF中Node的文件讀取漏洞通常為模板注入、代碼注入等情況。
中間件/服務器相關
Nginx錯誤配置
Nginx錯誤配置導致的文件讀取漏洞在CTF線上比賽中經常出現,尤其是經常搭配Python-Web應用一起出現。這是因為Nginx一般被視為Python-Web反向代理的最佳實現。然而它的配置文件如果配置錯誤,就容易造成嚴重問題。
例如:
location /static {
alias /home/myapp/static/;
}
如果配置文件中包含上面這段內容,很可能是運維或者開發(fā)人員想讓用戶可以訪問static目錄(一般是靜態(tài)資源目錄)。但是,如果用戶請求的Web路徑是/static../,拼接到alias上就變成了/home/myapp/static/../,此時便會產生目錄穿越漏洞,并且穿越到了myapp目錄。這時,攻擊者可以任意下載Python源代碼和字節(jié)碼文件。
注意:漏洞的成因是location最后沒有加“/”限制,Nginx匹配到路徑static后,把其后面的內容拼接到alias,如果傳入的是/static../,Nginx并不認為這是跨目錄,而是把它當作整個目錄名,所以不會對它進行跨目錄相關處理。
數據庫
MySQL的load_file()函數可以進行文件讀取,但是load_file()函數讀取文件首先需要數據庫配置FILE權限(數據庫root用戶一般都有),其次需要執(zhí)行l(wèi)oad_file()函數的MySQL用戶/用戶組對于目標文件具有可讀權限(很多配置文件都是所有組/用戶可讀),主流Linux系統(tǒng)還需要Apparmor配置目錄白名單(默認白名單限制在MySQL相關的目錄下),可謂“一波三折”。即使這么嚴格的利用條件,我們還是經??梢栽贑TF線上比賽中遇到相關的文件讀取題。還有一種方式讀取文件,但是與load_file()文件讀取函數不同,這種方式需要執(zhí)行完整的SQL語句,即load data infile。同樣,這種方式需要FILE權限,不過比較少見,因為除了SSRF攻擊MySQL這種特殊情形,很少有可以直接執(zhí)行整條非基本SQL語句(除了SELECT/UPDATE/INSERT)的機會。
軟鏈接
bash命令ln -s可以創(chuàng)建一個指向指定文件的軟鏈接文件,然后將這個軟鏈接文件上傳至服務器,當我們再次請求訪問這個鏈接文件時,實際上是請求在服務端它指向的文件。
FFmpeg
2017年6月,FFmpeg被爆出存在任意文件讀取漏洞。利用工具:https://github.com/neex/ffmpeg-avi-m3u-xbin
Docker-API
Docker-API可以控制Docker的行為,一般來說,Docker-API通過UNIX Socket通信,也可以通過HTTP直接通信。當我們遇見SSRF漏洞時,尤其是可以通過SSRF漏洞進行UNIX Socket通信的時候,就可以通過操縱Docker-API把本地文件載入Docker新容器進行讀?。ɡ肈ocker的ADD、COPY操作),從而形成一種另類的任意文件讀取。
客戶端相關
客戶端也存在文件讀取漏洞,大多是基于XSS漏洞讀取本地文件。
1.瀏覽器/Flash XSS一般來說,很多瀏覽器會禁止JavaScript代碼讀取本地文件的相關操作,如請求一個遠程網站,如果它的JavaScript代碼中使用了File協議讀取客戶的本地文件,那么此時會由于同源策略導致讀取失敗。但在瀏覽器的發(fā)展過程中存在著一些操作可以繞過這些措施,如Safari瀏覽器在2017年8月被爆出存在一個客戶端的本地文件讀取漏洞。
2.MarkDown語法解析器XSS與XSS相似,Markdown解析器也具有一定的解析JavaScript的能力。但是這些解析器大多沒有像瀏覽器一樣對本地文件讀取的操作進行限制,很少有與同源策略類似的防護措施。
文件讀取漏洞常見讀取路徑
Linux
flag名稱(相對路徑)
比賽過程中,有時fuzz一下flag名稱便可以得到答案。注意以下文件名和后綴名,請讀者根據題目及環(huán)境自行發(fā)揮。
../../../../../../../../../flag(.txt|.php|.pyc|.py)
flag(.txt|.php|.pyc|.py)
../flag(.txt|.php|.pyc|.py)
[dir_you_know]/flag(.txt|.php|.pyc|.py)
../../../../../../../../../etc/flag(.txt|.php|.pyc|.py)
../../../../../../../../../tmp/flag(.txt|.php|.pyc|.py)
../../../../../../../../../root/flag(.txt|.php|.pyc|.py)
../../../../../../../../../home/flag(.txt|.php|.pyc|.py)
../../../../../../../../../home/[user_you_know]/flag(.txt|.php|.pyc|.py)
服務器信息(絕對路徑)
下面列出CTF線上比賽常見的部分需知目錄和文件。
(1)/etc目錄
/etc目錄下多是各種應用或系統(tǒng)配置文件,所以其下的文件是進行文件讀取的首要目標。
(2)/etc/passwd
/etc/passwd文件是Linux系統(tǒng)保存用戶信息及其工作目錄的文件,權限是所有用戶/組可讀,一般被用作Linux系統(tǒng)下文件讀取漏洞存在性判斷的基準。讀到這個文件我們就可以知道系統(tǒng)存在哪些用戶、他們所屬的組是什么、工作目錄是什么。
(3)/etc/shadow
/etc/shadow是Linux系統(tǒng)保存用戶信息及(可能存在)密碼(hash)的文件,權限是root用戶可讀寫、shadow組可讀。所以一般情況下,這個文件是不可讀的。
(4)/etc/apache2/*
/etc/apache2/是Apache配置文件,可以獲知Web目錄、服務端口等信息。CTF有些題目需要參賽者確認Web路徑。
(5)/etc/nginx/
/etc/nginx/是Nginx配置文件(Ubuntu等系統(tǒng)),可以獲知Web目錄、服務端口等信息。
(6)/etc/apparmor(.d)/
/etc/apparmor(.d)/是Apparmor配置文件,可以獲知各應用系統(tǒng)調用的白名單、黑名單。例如,通過讀配置文件查看MySQL是否禁止了系統(tǒng)調用,從而確定是否可以使用UDF(User Defined Functions)執(zhí)行系統(tǒng)命令。
(7)/etc/(cron.d/*|crontab)
/etc/(cron.d/|crontab)是定時任務文件。有些CTF題目會設置一些定時任務,讀取這些配置文件就可以發(fā)現隱藏的目錄或其他文件。
(8)/etc/environment
/etc/environment是環(huán)境變量配置文件之一。環(huán)境變量可能存在大量目錄信息的泄露,甚至可能出現secret key泄露的情況。
(9)/etc/hostname/etc/hostname表示主機名。
(10)/etc/hosts/etc/hosts是主機名查詢靜態(tài)表,包含指定域名解析IP的成對信息。通過這個文件,參賽者可以探測網卡信息和內網IP/域名。
(11)/etc/issue
/etc/issue指明系統(tǒng)版本。
(12)/etc/mysql/*
/etc/mysql/是MySQL配置文件。
(13)/etc/php/
/etc/php/*是PHP配置文件。
(14)/proc目錄
/proc目錄通常存儲著進程動態(tài)運行的各種信息,本質上是一種虛擬目錄。注意:如果查看非當前進程的信息,pid是可以進行暴力破解的,如果要查看當前進程,只需/proc/self/代替/proc/[pid]/即可。
對應目錄下的cmdline可讀出比較敏感的信息,如使用mysql-uxxx-pxxxx登錄MySQL,會在cmdline中顯示明文密碼:
/proc/[pid]/cmdline ([pid]指向進程所對應的終端命令)
有時我們無法獲取當前應用所在的目錄,通過cwd命令可以直接跳轉到當前目錄:
/proc/[pid]/cmd/ ([pid]指向進程的運行目錄)
環(huán)境變量中可能存在secret_key,這時也可以通過environ進行讀?。?br>
/proc/[pid]/environ ([pid]指向進程運行時的環(huán)境變量)
其他目錄
Nginx配置文件可能存在其他路徑:
/usr/local/nginx/conf/* (源代碼安裝或其他一些系統(tǒng))
日志文件:
/var/log/* (經常出現Apache2的Web應用可讀/var/log/apache2/access/log從而分析日志,盜取其他選手的解題步驟)
Apache默認Web根目錄:
/var/www/html/
PHP session目錄:
/var/lib/php(5)/sessions/ (泄露用戶session)
用戶目錄:
[user_dir_you_know]/.bash_history (泄露歷史執(zhí)行命令)
[user_dir_you_know]/.bashrc (部分環(huán)境變量)
[user_dir_you_know]/.ssh/id_rsa(.pub) (ssh登錄私鑰/公鑰)
[user_dir_you_know]/.viminfo (vim使用記錄)
[pid]指向進程所對應的可執(zhí)行文件。有時我們想讀取當前應用的可執(zhí)行文件再進行分析,但在實際利用時可能存在一些安全措施阻止我們去讀可執(zhí)行文件,這時可以嘗試讀取/proc/self/exe。例如:
/proc/[pid]/fd/(1|2) (讀取[pid]指向進程的stdout或stderror或其他)
/proc/[pid]/maps ([pid]指向進程的內存映射)
/proc/[pid]/(mounts|mountinfo) ([pid]指向進程所在的文件系統(tǒng)掛載情況,CTF常見的是docker環(huán)境這時mount會泄露一些敏感路徑)
/proc/[pid]/net/* ([pid]指向進程的網絡信息,如讀取TCP將獲取進程所綁定的TCP端口ARP將泄露網段內網IP信息)