當php邂逅windows通用上傳缺陷

來源:互聯網
上載者:User

標籤:驀然回首   目錄   程式   style   無法   證明   test   郵件系統   tac   

早上逛烏雲發現了PKAV大牛的一篇文章,針對php和windows檔案上傳的分析,思路很YD,果斷轉之與大家分享。

雖然此文可能有許多的限制條件,但是如果你認真閱讀會發現,其實還是比較實用的。

另外一篇團長發的pdf中也涉及到了相關的文章,是國外的nosec發布的,英文的,感興趣的同學在這裡下載http://pan.baidu.com/s/1hqiQRbA

 

本案例採用的執行個體是:U-Mail郵件系統。

U-Mail郵件系統檔案上傳的地方代碼是這樣的:

<?phpif(ACTION =="attach-upload"){    if($_FILES){        $file_name = $_FILES[‘Filedata‘][‘name‘];        $file_type = $_FILES[‘Filedata‘][‘type‘];        $file_size = $_FILES[‘Filedata‘][‘size‘];        $file_source = $_FILES[‘Filedata‘][‘tmp_name‘];        $file_suffix = getfilenamesuffix( $file_name );        $not_allow_ext = array( "php", "phps", "php3", "exe", "bat" );        if (in_array($file_suffix, $not_allow_ext )){            dump_json( array( "status" => 0, "message" => el( "不支援該副檔名檔案上傳", "" ) ) );        }        $path_target = getusercachepath( );        do{            $file_id = makerandomname( );            $file_target = $path_target.$file_id.".".$file_suffix;        } while ( file_exists( $file_target ) );        if ( move_uploaded_file( $file_source, $file_target )){            dump_json( array( "status" => 0, "message" => el( "寫入檔案出錯,請與管理員聯絡!", "" ) ) );        }        $_SESSION[SESSION_ID][‘attach_cache‘][] = array( "id" => $file_id, "name" => $file_name, "type" => "1", "path" => $file_target, "size" => $file_size );        dump_json( array( "status" => "1", "filename" => $file_name, "filesize" => $file_size, "file_id" => $file_id ) );    }else{        dump_json( array( "status" => "0", "message" => el( "無法找到需要上傳的檔案!", "" ) ) );    }}

我們注意到如下的代碼

$not_allow_ext = array( "php", "phps", "php3", "exe", "bat" );if (in_array($file_suffix, $not_allow_ext )){    dump_json( array( "status" => 0, "message" => el( "不支援該副檔名檔案上傳", "" ) ) );}

非常明顯,採用的是黑名單驗證,雖然我們可以採用類似這樣的檔案尾碼繞過程式的檢測,如:bypass.phpX(這裡的X代表空格%20或其他特殊字元{%80-%99}),但這完全不是今天我想要講的內容。

今天,通過這個執行個體給大家講解一種新型的檔案上傳方式,且聽我細細道來..

#2 代碼poc實現

為了在本地測試方便,我們對上述代碼進行簡化,如下

<?php//U-Mail demo ...if(isset($_POST[‘submit‘])){    $filename = $_POST[‘filename‘];    $filename = preg_replace("/[^\w]/i", "", $filename);    $upfile = $_FILES[‘file‘][‘name‘];  $upfile = str_replace(‘;‘,"",$upfile);    $upfile = preg_replace("/[^(\w|\:|\$|\.|\<|\>)]/i", "", $upfile);    $tempfile = $_FILES[‘file‘][‘tmp_name‘];    $ext = trim(get_extension($upfile)); // null    if(in_array($ext,array(‘php‘,‘php3‘,‘php5‘))){        die(‘Warning ! File type error..‘);    }    if($ext == ‘asp‘ or $ext == ‘asa‘ or $ext == ‘cer‘ or $ext == ‘cdx‘ or $ext == ‘aspx‘ or $ext == ‘htaccess‘) $ext = ‘file‘;  //$savefile = ‘upload/‘.$upfile;    $savefile = ‘upload/‘.$filename.".".$ext;    if(move_uploaded_file($tempfile,$savefile)){        die(‘Success upload..path :‘.$savefile);    }else{        die(‘Upload failed..‘);    }}function get_extension($file){    return strtolower(substr($file, strrpos($file, ‘.‘)+1));}?><html> <body>  <form method="post" action="upfile.php" enctype="multipart/form-data">   <input type="file" name="file" value=""/>   <input type="hidden" name="filename" value="file"/>   <input type="submit" name="submit" value="upload"/>  </form> </body></html>

對於上述代碼,雖然是通過黑名單進行檔案名稱檢測,但通過目前已知的上傳方法,是沒有辦法成功上傳php檔案的(不考慮程式的Bug),因此可以說這段檔案上傳的代碼是"安全"的,

可是,我驀然回首,在那個燈火闌珊的地方,php邂逅了Windows,美麗的愛情故事便由此產生了..

#3 細說故事

某天,二哥在群裡丟了一個url串連,我簡單看了下,關於利用系統特性進行檔案上傳的,興趣馬上就來了,就細細研究了下,於是有了這篇文章..

這幾行英文的意思大致是,在php+window+iis環境下:

雙引號(">") <==> 點號(".")‘;大於符號(">") <==> 問號("?")‘;小於符號("<") <==> 星號("*")‘;

有這麼好玩的東西,那不就可以做太多的事了?但事實並不是這樣,通過一系列的測試發現,該特性只能用於檔案上傳時覆蓋已知的檔案,於是這個特性便略顯雞肋..

原因有二:

1)上傳檔案的目錄一般我們都不可控;

2)同時,一般檔案上傳的目錄不可能存在我們想要的任何php檔案,因此沒辦法覆蓋;

後來,經過反反覆複的思考,終於找到了可以完美利用的辦法..

思路如下:

首先我們先利用特殊辦法產生一個php檔案,然後再利用這個特性將檔案覆蓋..

可問題又來了,怎樣產生php檔案呢?如果可以直接產生php檔案的話,幹嘛還要利用那什麼特性?

別急,辦法總是有的..

我們都知道在檔案上傳時,我們往往會考慮到檔案名稱截斷,如%00 等..

對!有的人可能還會用冒號(":")去截斷,如:bypass.php:jpg

但是你知道嗎?冒號截斷產生的檔案是空白的,裡面並不會有任何的內容,呵呵 說到這裡 明白了沒有? 雖然產生的php檔案裡面沒有內容,但是php檔案總產生了吧,所以 我們可以結合上面所說的特性完美成功利用..

 

#4 冒號+特性成功利用

按照#3提供的思路,實現..

本地測試地址:http://www.secmap.cn/upfile.php 環境:Windows+IIS7.5

1)首先利用冒號產生我們將要覆蓋的php檔案,這裡為:bypass.php,

2)利用上面的系統特性覆蓋該檔案

從上面已經知道"<" 就等於 "*",而"*"代碼任一字元,於是乎.. 我們可以這樣修改上傳的檔案名稱,如下:

------WebKitFormBoundaryaaRARrn2LBvpvcwKContent-Disposition: form-data; name="file"; filename="bypass.<<<"Content-Type: image/jpeg//注意!檔案名稱為:bypass.<<<

點擊go..,即可成功覆蓋bypass.php檔案,

對比上面的兩個圖,bypass.php被我們成功的寫入了內容..

#5 特性二

首先來看看微軟MSDN上面的一段話,

 

 

 

注意紅色圈起來的英文

The default data stream has no name. That is, the fully qualified name for the default stream for a file called "sample.txt" is "sample.txt::$DATA" since "sample.txt" is the name of the file and "$DATA" is the stream type.

看不去不錯喲,試試吧..

同樣,我們可以這樣修改上傳的檔案名稱,如下:

------WebKitFormBoundaryaaRARrn2LBvpvcwKContent-Disposition: form-data; name="file"; filename=‘DataStreamTest.php::$DATA‘Content-Type: image/jpeg//注意!檔案名稱為:DataStreamTest.php::$DATA

點擊GO,奇蹟出現了..

訪問之...

#6 漏洞證明

 

 

U-Mail,具體利用方法,同上述的方法一樣,為了簡單快捷的話,可直接抓包修改檔案名稱為:

shell.php::$DATA 即可成功上傳,這裡不再示範,附shell

 

當php邂逅windows通用上傳缺陷

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.