文件上傳漏洞是web安全中常常利用到的一種漏洞形式。一些web應用程序中容許上傳圖片,文本或者其餘資源到指定的位置,文件上傳漏洞就是利用這些能夠上傳的地方將惡意代碼植入到服務器中,再經過url去訪問以執行代碼。但在一些安全性較高的web應用中,每每會有各類上傳限制和過濾,致使咱們沒法上傳特定的文件。本文將就此展開討論,經過本文的學習你將瞭解到Web應用中文件上傳的處理和驗證發送流程,以及咱們該如何繞過這些驗證。javascript
客戶端驗證是一種發生在輸入被實際發送至服務器以前進行的驗證。這類驗證大都都是經過JavaScript,VBScript或HTML5來完成的。雖然,這對於用戶來講響應速度更快體驗也更好。但對於惡意×××者來講,這些驗證彷佛就顯得略爲低級。php
這種類型的繞過也很是簡單,咱們能夠關閉瀏覽器上的JavaScript或是在瀏覽器發出請求以後,在被髮送至服務器以前來篡改該HTTP請求便可。html
示例:java
1. <script type="text/javascript">web
2. var _validFileExtensions = [".jpg", ".jpeg", ".bmp", ".gif", ".png"];shell
3. function Validate(oForm) {瀏覽器
4. var arrInputs = oForm.getElementsByTagName("input");安全
5. for (var i = 0; i < arrInputs.length; i++) {服務器
6. var oInput = arrInputs[i];網絡
7. if (oInput.type == "file") {
8. var sFileName = oInput.value;
9. if (sFileName.length > 0) {
10. var blnValid = false;
11. for (var j = 0; j < _validFileExtensions.length; j++) {
12. var sCurExtension = _validFileExtensions[j];
13. if (sFileName.substr(sFileName.length - sCurExtension.length, sCurExtension.length).to LowerCase() == sCurExtension.toLowerCase()) {
14. blnValid = true;
15. break;
16. }
17. }
18.
19. if (!blnValid) {
20. alert("Sorry, " + sFileName + " is invalid, allowed extensions are: " + _validFileExtension s.join(", "));
21. return false;
22. }
23. }
24. }
25. }
26.
27. return true;
28. }
29. </script>
正如你所看到的,此JavaScript僅在請求被實際發送至服務器以前處理你的請求,以及檢查你上傳的文件擴展名是否爲(jpg,jpeg,bmp,gif,png)。這樣的話,咱們就能夠攔截該請求並篡改文件內容(惡意代碼),而後將圖片擴展名更改成可執行文件的擴展名(如php,asp)。
如上圖所示,咱們試圖上傳一個直接的PHP文件,JavaScript阻止了咱們的文件上傳請求。
咱們能夠經過瀏覽器來上傳一個正常的圖片格式來繞過該驗證,而後攔截該請求再將其改回爲php格式並將文件內容替換爲咱們的惡意代碼,這樣咱們就可以成功上傳咱們的惡意php腳本了。
顧名思義,就是在文件被上傳到服務端的時候,對於文件名的擴展名進行檢查,若是不合法,則拒絕此次上傳。檢查擴展名是否合法有兩種經常使用策略,即黑名單和白名單策略。
黑名單策略,即文件擴展名在黑名單中的爲不合法。白名單策略,即文件擴展名不在白名單中的均爲不合法。相對於黑名單,白名單策略更加安全的。經過限制上傳類型爲只有咱們接受的類型,能夠較好的保證安全,由於黑名單咱們可使用各類方法來進行注入和突破。
咱們能夠經過上傳一些平時不怎麼用的容易被人忽視的文件擴展名,來繞過這種類型的驗證。
黑名單繞過
經過上傳不受歡迎的php擴展來繞過黑名單。例如:pht,phpt,phtml,php3,php4,php5,php6
白名單繞過
經過某種類型的技巧來繞過白名單,例如添加空字節注入(shell.php%00.gif),或使用雙重擴展來上傳文件(shell.jpg.php)。
此外,咱們還能夠嘗試擴展名大小寫來繞過,例如:pHp,Php,phP。
示例:
1. if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"2. && $imageFileType != "gif" ) { 3. echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed.";
以上代碼將會阻止除jpg,jpeg,gif,png擴展名之外的,全部其它文件類型上傳。在本例中咱們將嘗試繞過該檢查,並在Web服務器上傳一個php文件。
黑名單繞過
正如你所看到的,將php文件的後綴更改成.php5(Apache服務器會將其視爲php文件執行)後,就能夠成功繞過該上傳驗證。
白名單繞過
如上圖所示,咱們使用了雙重擴展名(shell.jpg.php)來繞過驗證。
Content-Type(內容類型),通常是指網頁中存在的Content-Type,用於定義網絡文件的類型和網頁的編碼,決定文件接收方將以什麼形式、什麼編碼讀取這個文件。例如,一些圖像文件上傳經過檢查文件的內容類型是否爲圖像類型來驗證上傳的圖像。
該類型的繞過也很是簡單,只需將「Content-Type」的參數類型更改成「image/ *」便可,例如「image/png」, 「image/jpeg」, 「image/gif」。
示例:
1. <?php 2. 3. $mimetype = mime_content_type($_FILES['file']['tmp_name']); 4. if(in_array($mimetype, array('image/jpeg', 'image/gif', 'image/png'))) { 5. move_uploaded_file($_FILES['file']['tmp_name'], '/uploads/' . $_FILES['file']['name']); 6. echo 'OK'; 7. 8. } else { 9. echo 'Upload a real image'; 10. }
以上代碼會檢查Content-Type header中的MIME類型,僅接受類型爲image/jpeg, image/gif, image/png的文件上傳。咱們只需只需將「Content-Type」的參數類型更改成其可接受的類型便可繞過。
Content-Length驗證是指服務器會對上傳的文件內容長度進行檢查,超出限制大小的文件將不容許被上傳。雖然這種類型的驗證不是很受歡迎,但在一些應用的文件上傳中也時常能碰到。
針對這種類型的驗證,咱們能夠經過上傳一些很是短的惡意代碼來繞過。上傳文件的大小取決於,Web服務器上的最大長度限制。咱們可使用不一樣大小的文件來fuzzing上傳程序,從而計算出它的限制範圍。
示例:
1. if ($_FILES["fileToUpload"]["size"] > 30) {
2. echo "Sorry, your file is too large.";
3. }
以上代碼將限制大小超過30字節的文件上傳。咱們能夠經過上傳一個30字節之內大小的惡意payload文件來繞過它。