標籤:http io os ar for sp 檔案 on 2014
$pkav->publish{當php懈垢windows}
劍心@xsser拋棄了我,但我卻不能拋棄烏雲..
php懈垢windows,就像男人邂逅女人,早晚都會出問題的..
感謝二哥@gainover
Tips:本文講述一種新型的檔案上傳方式(幾個特性導致的漏洞),並給出相應的執行個體..
詳細說明:
#1 執行個體介紹
本案例採用的執行個體是:U-Mail郵件系統。
U-Mail郵件系統檔案上傳的地方代碼是這樣的:
code 地區
<?php
if(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( "無法找到需要上傳的檔案!", "" ) ) );
}
}
我們注意到如下的代碼
code 地區
$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實現
為了在本地測試方便,我們對上述代碼進行簡化,如下
code 地區
<?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,
點擊forward後,可以看見成功產生空白的bypass.php檔案
2)利用上面的系統特性覆蓋該檔案
從上面已經知道"<" 就等於 "*",而"*"代碼任一字元,於是乎..
我們可以這樣修改上傳的檔案名稱,如下:
code 地區
------WebKitFormBoundaryaaRARrn2LBvpvcwK
Content-Disposition: form-data; name="file"; filename="bypass.<<<"
Content-Type: image/jpeg
//注意!檔案名稱為:bypass.<<<
點擊go..,即可成功覆蓋bypass.php檔案,
對比上面的兩個圖,bypass.php被我們成功的寫入了內容..
#5 特性二
首先來看看微軟MSDN上面的一段話,
注意紅色圈起來的英文
code 地區
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.
看不去不錯喲,試試吧..
同樣,我們可以這樣修改上傳的檔案名稱,如下:
code 地區
------WebKitFormBoundaryaaRARrn2LBvpvcwK
Content-Disposition: form-data; name="file"; filename=‘DataStreamTest.php::$DATA‘
Content-Type: image/jpeg
//注意!檔案名稱為:DataStreamTest.php::$DATA
點擊GO,奇蹟出現了..
訪問之...
漏洞證明:
#6 漏洞證明
U-Mail,具體利用方法,同上述的方法一樣,為了簡單快捷的話,可直接抓包修改檔案名稱為:
shell.php::$DATA 即可成功上傳,這裡不再示範,附shell
pkav之當php懈垢windows通用上傳缺陷