文件上傳bypass安全狗


0x00 前言

 

本文首發於先知社區:https://xz.aliyun.com/t/9507

 

我們知道WAF分為軟WAF,如某狗,某盾等等;雲WAF,如阿里雲CDN,百度雲CDN等等;硬WAF,如天融信,安恆等等,無論是軟WAF、雲WAF還是硬WAF,總體上繞過的思路都是讓WAF無法獲取到文件名或者其他方式無法判斷我們上傳的木馬(PHP、JSP、ASP、ASPX等等)。

 

這里總結下關於軟waf中那些繞過文件上傳的姿勢和嘗試思路,這里選擇繞過的軟waf為某狗4.0,可能其他軟waf在攔截關鍵字方面可能會有差異,但繞過軟waf的大體思想都是相同的,如果文章中有錯誤,歡迎師傅們斧正。

 

0x01 初探原理

 

寫這篇文章時想過一個問題,如何總結哪些屬於文件上傳Bypass的范疇?打個比方:

 

上傳正常.jpg的圖片 #成功
上傳正常.php #攔截
繞過.php文件的filename后進行上傳 #成功
使用繞過了filename的姿勢上傳惡意.php #攔截
 
        

以上這么個邏輯通常來講是waf檢測到了正文的惡意內容。再繼續寫的話就屬於免殺的范疇了,過於模糊並且跑題了,並不是真正意義上的文件上傳Bypass,那是寫不完的。

 

上傳文件時waf會檢查哪里?

 

請求的url
Boundary邊界
MIME類型
文件擴展名
文件內容

 

常見擴展名黑名單:

 

asp|asa|cer|cdx|aspx|ashx|ascx|asax
php|php2|php3|php4|php5|asis|htaccess
htm|html|shtml|pwml|phtml|phtm|js|jsp
vbs|asis|sh|reg|cgi|exe|dll|com|bat|pl|cfc|cfm|ini
 
        

個人寫的“稍微”全一點,實際上waf的黑名單就不一定這么全了。

 

測試時的准備工作:

 

  • 什么語言?什么容器?什么系統?都什么版本?
  • 上傳文件都可以上傳什么格式的文件?還是允許上傳任意類型?
  • 上傳的文件會不會被重命名或者二次渲染?

 

0x02 環境介紹

 

實驗環境:mysql + apache +php

 

waf:某狗4.0

 

這里用了一個簡單的上傳頁面判斷,觀察代碼可以發現只允許上傳Content-Type為image/gif、image/jpeg、image/pjpeg三種形式的文件

 

<html>
<body>

<form action="upload.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" /> 
<br />
<input type="submit" name="submit" value="Submit" />
</form>

</body>
</html>
<?php
error_reporting(0);
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg")))
//&& ($_FILES["file"]["size"] < 20000))
  {
  if ($_FILES["file"]["error"] > 0)
    {
    echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
    }
  else
    {
    echo "Upload: " . $_FILES["file"]["name"] . "<br />";
    echo "Type: " . $_FILES["file"]["type"] . "<br />";
    echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
    echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

    if (file_exists("upload/" . $_FILES["file"]["name"]))
      {
      echo $_FILES["file"]["name"] . " already exists. ";
      }
    else
      {
      move_uploaded_file($_FILES["file"]["tmp_name"],
      "upload/" . $_FILES["file"]["name"]);
      echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
      }
    }
  }
else
  {
  echo "Invalid file";
  }
?>

 

0x03 實驗bypass

 

先上傳一個asp,看一下返回值

 

 

這里看到了404xxxdog的頁面,那應該是攔截了,我這里先放過去看看,果然是某狗攔截了

 

 

開始嘗試繞waf

 

這里我先把Content-Type改成image/gif通用圖片類型

 

 

0x03.1 增大文件大小

 

測試發現 waf對於Content-Disposition字段的 長度驗證不是很准確,因為我們可以想到它進行攔截的規則肯定是基於正則,那么我們想辦法讓安全狗攔截的正則匹配不到即可

 

這里附一個對Content-Disposition字段的解釋

 

在常規的 HTTP 應答中,Content-Disposition 響應頭指示回復的內容該以何種形式展示,是以內聯的形式(即網頁或者頁面的一部分),還是以附件的形式下載並保存到本地。
在 multipart
/form-data 類型的應答消息體中,Content-Disposition 消息頭可以被用在 multipart 消息體的子部分中,用來給出其對應字段的相關信息。各個子部分由在Content-Type 中定義的分隔符分隔。用在消息體自身則無實際意義。 Content-Disposition 消息頭最初是在 MIME 標准中定義的,HTTP 表單及 POST 請求只用到了其所有參數的一個子集。只有 form-data 以及可選的 name 和 filename 三個參數可以應用在HTTP場景中。

 

這里對這個字段的長度進行篡改,繞過成功

 

 

0x03.2 對文件名修改(卒)

 

我們在上傳時候通常會把文件名后綴和解析漏洞,那么waf對於filename參數后的值的文件名后綴肯定是要正則去匹配的 這樣正常上傳肯定不行

 

 那么繞過之前我們猜想,第一個它可能是對filename這樣的鍵值對進行匹配,例如"ket = val"這樣的鍵值對 那么這里我們就是filename=“shell.php” 

 

那這里把雙引號去除,擾亂匹配,發現不行

 

 

那么我們可不可以多一個filename,因為文件在接收上傳文件名時取的是最后一個filename,那么我們在最后一個filename參數前加一些干擾的filename參數試試

 

 

發現還是不行  那么這里就知道他是對所有filename參數進行檢測  那么我們能不能把前面的filename參數去掉值呢

 

Content-Disposition: form-data; name="file"; filename= ;  filename="shell.php"

 

 

結果對文件名進行修改全卒,在之前版本的某狗在filename= ;是可以進行繞過的,4.0版本文件名修改全卒 

 

0x03.3 修改文件名后綴

 

經典的apache解析漏洞嘗試,攔截

 

 

可以在文件名中間加符號擾亂某狗匹配,經測試 ";" " " " ' " 均可

 

 

 

 

0x03.4 對filename動手腳

 

這里可以讓waf對filename這個字符串匹配不到,但是服務器又可以接收,加入換行這類的干擾

 

先測試單個字符進行換行,都失敗

 

 

 

切斷filename= 和 之后的值,則可以繞過

 

 

文件名換行,即hex加入0a,也可以繞過

 

 

 

0x03.5 修改匹配字段(卒)

 

我們的filename參數是在post包中的 Content-Disposition 字段,那么waf也是先匹配到這個http頭在對內容進行檢測,我們可以嘗試對這個頭的特征進行修改

 

我們嘗試去掉這個form-data    (form-data;的意思是內容描述,form-data的意思是來自表單的數據,但是即使不寫form-data,apache也接受。)

 

  Content-Disposition: name="file"; filename="shell.php"

 

發現失敗,之前3.0版本可以繞,4.0卒

 

 

對Content-Disposition進行參數污染,攔截

 

 

對Content-Disposition進行大小寫混淆,攔截

 

 

加上額外的Content-Type進行干擾,攔截

 

 

加上filename進行參數污染,攔截

 

 

加一個額外的Content-Length頭,攔截

 

 

0x03.6 多個等號

 

經測試兩個=或者三個=都可以達到繞過的效果

 

 

 

 

 

0x03.7 %00截斷

 

%00截斷產生的原因是0x00為十六進制的表示方法,ASCII碼里就為0,而有些函數在進行處理的時候會把這個當作結束符

 

這里直接嘗試在文件名后面加上%00形成00截斷,成功繞過

 

 

 

 

0x04 后記

 

某狗4.0版本對於3.0版本又有了一定的改進,對於之前的文件名修改和修改匹配字段已經不能夠繞過waf,但是對於繞軟waf的思想總結起來可以有如下幾點:

 

大小寫轉換、干擾字符污染、字符編碼、拼湊法、各種換行符

 

總體來說,這些思想不僅在文件上傳bypass中有用,對於sql注入繞waf等一系列地方思想都大體相同,師傅們可自行拓展,文章中若有錯或不足的地方歡迎師傅們交流。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM