Unrestricted File Upload Vulnerability

1 minute read

這篇會介紹一下經典的 file upload 漏洞。

介紹

Unrestricted File Upload Vulnerability,顧名思義,就是沒有限制使用者上傳的檔案,導致伺服器執行惡意代碼,或是利用 XSS攻擊 騙取其他此使用者等等。

許多網站會提供使用者上傳資料的功能,例如上傳大頭貼,如果伺服器沒有詳加檢查上傳檔案的格式,那麼非法的使用者就可以上傳惡意的檔案讓 server 執行。 例如上傳一個 index.php 檔案,接著開啟,那麼 server 端便會幫我們跑這個 php 檔案。

或者,使用者上傳 index.html 檔案,裡面嵌有惡意的 javascript 代碼或是 iframe,當其他使用者及管理員因為相信該網站,而點擊此頁面,便會執行惡意的代碼。

真實範例

其實會寫這篇文章的原因,是因為發現某學校的教學平台有這個漏洞。該平台提供自訂頁面的服務,可以上傳任意格式的檔案,因此我就先試了一下 html,結果成功!

html-upload-success

html 可以上傳的話,基本上足夠用來做 XSS 攻擊,只要吸引使用者點擊這個頁面即可,但這還不夠,來試試看更暴力的。

試著上傳 a.php 以及 a.asp 檔案看看,不過失敗了,在檔案列表下並沒有這兩個檔案。

至此,合理判斷網站雖然沒有擋住 html,但對於上傳可執行的 php 以及 asp 檔案還是有限制的,因此我猜測他是藉由判斷副檔名來擋住非法格式的。

所以,要怎麼繞過這個檔名格式限制呢?首先我發現這是一個 windows server,所以要用 windows 的思維去想,windows 對於檔名有一些古怪的限制以及 bug,而我們的目標是讓檔案結尾不是 .php,但寫入硬碟的時候又要是 .php

這裡利用了 windows 的一個 bug (也可能是 feature),在檔案名稱後面加上一個點 .,但這在寫入的時候會被拿掉,這一個漏洞在 OWASP 裡也有提到:

Using trailing spaces and/or dots at the end of the filename can sometimes cause bypassing the protection. These spaces and/or dots at the end of the filename will be removed when the file wants to be saved on the hard disk automatically. The filename can be sent to the server by using a local proxy or using a simple script (example: “file.asp … … . . .. ..”, “file.asp ”, or “file.asp.”).

因此試著上傳 a.php.,結果成功! 並且能夠透過瀏覽器存取,請 server 端執行 php

接下來就簡單了,透過 php 加上 server 端的幫忙,我們等同於拿到 shell:

<?php
passthru("pwd");
passthru("ls -all");
?>

我們現在想做什麼都可以了!

如何防護

這個保護的方法詳細可以參考 OWASP,我建議是設定白名單,只讓某些格式的檔案通過,例如無害的 png, txt 檔案,另外對於使用者上傳的檔案 hash 過後再存放至硬碟(防止惡意檔名);還有不要讓 server 直接去執行使用者上傳的任何檔案,有一句經典名言 : Don’t trust user input,惡意的使用者會上傳其他格式的檔案,善意的使用者會誤傳大檔,總之 upload 的動作一定要小心做好資安防護。

補充一點,單純判斷檔案格式是否為圖片,是沒有用的,有心人士可以竄改執行擋 header,讓你以為他是圖片,但其實是有惡意程式在裡面的 script。

後記

剛發現這個漏洞的時候,當然是回報給平台的負責人,他們也非常盡職的在兩天內修復完成,值得讚賞!

有一個小插曲是,我在測試這個漏洞的嚴重性時,想要看一些 php 的 source code,然後我就看到了他連接資料庫的帳號密碼,看了當下馬上告訴自己眼睛業障重,假的,我都沒看到。

仔細想想,若我是有心人士,只要連上資料庫,把它 dump 下來,就可以獲得該學校所有的學生個資,這如果外洩,後果恐怕不堪設想。

這件事情的啟發是,就算我們重視自己的資料安全,那些擁有你個資的人,未必會重視它們,但你只要外洩一次,你的個資就在網路世界的天上飛了。所以我們也一樣,當我們廣開 Google 表單,收集別人個資的同時,必須要把他們當作自己的個資一樣看待才對!