upload-labs pass-5-利用系統特性繞過
Windows利用系統本身的命名規則繞過:
先看一下利用Windows特性繞過
大小寫繞過:針對對大小寫不敏感的系統如 windows 例如test.PhP
以下為不符合規則的Windows檔案
shell.php. | 檔名後加 '.' | 適用於上傳的檔名沒有被修改 |
---|---|---|
shell.php空格 | 檔名後加空格 | |
shell.php.空格. | 檔名+'.'+空格+'.' | 適用於上傳的檔名沒有被修改 |
shell.php:1.jpg | 檔名後加冒號 | 適用於上傳的檔名沒有被修改 |
shell.php::$DATA | 檔名加NTFS ADS特性::$DATA | |
shell.php::$DATA...... | 檔名::$DATA..... |
均會被windows系統自動去掉不符合規則符號後面的內容
ADS是nfts磁碟格式的一個特性,由於NTFS交換資料流,在上傳檔案時,如果系統對請求正文的filename匹配不當的話可能會導致繞過
上傳的檔名 | 伺服器表面現象 | 生成的檔案內容 |
---|---|---|
test.php:a.jpg | 生成test.php | 空 |
test.php::$DATA | 生成test.php | |
test.php::$INDEX_ALLOCATION | 生成test.php資料夾 | |
test.php::$DATA.jpg | 生成0.jpg | |
test.php::$DATA\aaa.jpg | 生成aaa.jpg |
在php環境下可以上傳test.php::$DATA
Linux也可利用系統本身的命名規則繞過
linux命名規則
1、檔名最大長度為255
2、全路徑長度最大為4096(16級最大檔案長度)
3、區分大小寫
4、除“/”之外所有字元都可以使用
5、linux不以副檔名區分檔案型別,對linux來說一切皆檔案。
原始碼分析
$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 = 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 = '此檔案型別不允許上傳!'; } } else { $msg = UPLOAD_PATH . '資料夾不存在,請手工建立!'; } }
首先 trim( )函式 移除字串兩側的空白字元
- 假設上傳
test.php+空格
,這時伺服器獲取到的字尾是.php+空格,該檔案不再黑名單中,因此上傳功。 - 由於windows檔案系統的特性,會去除後面的空格,導致test.php+空格=test.php
- 假設上傳
deldot( ) 刪除檔名末尾的點
- 假設上傳
test.php.
這時伺服器獲取到的字尾是空,不在黑名單中,因此檔案上傳成功 - 但是由於windows檔案系統的特性導致test.php.=test.php
- 假設上傳
strchr( $file_name,' . ')函式 是搜尋
.
在檔名中的位置,並返回從該位置(包括此位置)到字串結尾的所有字元從頭開始,找到第一個滿足的就開始擷取
strrchr( $file_name,' . ')函式 函式和3中的strchr不同,看看下面的圖體會一下,原始碼用的此函式
str_ireplace('::$DATA', '', $file_ext)
將::$DATA去掉使用 trim($file_ext) 移除字串兩側的空白字元
禁止上傳如下字尾檔案
- 檔案重新命名文年月日星期+1000~9000+字尾名
- 上傳成功
上傳
分析上面的原始碼後,思路逐漸清晰,前兩步尾部去點,去空格,第五步去::$DATA,對於windows來說算致命打擊,但是轉換沒轉換大小寫,可以用test.PHp
繞過windows系統
利用linux的特性,建立一個類似檔案如test.\php
可以繞過linux系統
上傳一個test.\php
,看到上傳的字尾名沒了,所以上傳的不是linux系統,而是windows系統
因此利用windows不區分大小寫特性來繞過
上傳1.PHp
連線成功