upload-labs(11-15)
pass-11 黑名單-%00截斷-get
黑盒測試
1.php
上傳失敗,只允許上傳如下格式,看來這次採用白名單了
前端沒有js指令碼
改Content-Type: image/png
,上傳失敗
沒有頭緒,看看提示吧,說上傳路徑可控?
果然url欄寫著路徑,但是不知道有什麼用
原始碼分析
$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型別檔案!"; } }
1.strrpos() 函式查詢字串在另一字串中最後一次出現的位置。
- 原始碼中是查詢
.
在檔名中最後出現的位置
2.substr() 函式 返回其中一部分的字串。
substr(string,start,length)
:start為開始擷取部分
3.將字尾名給$file_ext
4.如果$file_ext
在白名單內,就上傳到規定的路徑,檔案命名為上傳路徑+10-99+年月日時分秒+$file_ext
看著無懈可擊,有沒有突破路徑呢?
百度了一下,這道題要用00截斷
%00截斷
繞過原理
move_uploaded_file函式的底層實現類似於C語言,遇到0x00會截斷,把後面部分刪掉
截斷條件:
1、php版本小於5.3.4
2、php.ini的magic_quotes_gpc為OFF狀態
注意
POST和GET不一樣
%00 截斷在 GET 中被 url 解碼之後是空字元。
但是在 POST 中 %00 不會自動被 url 解碼,用bp先對%00進行解碼
這也是為什麼上傳後沒有截斷,因為是post上傳
白盒測試
因為重新命名是上傳路徑+10-99+年月日時分秒+$file_ext
在上傳路徑處進行修改
上傳1.php
,burpsuite進行修改
表面上重新命名成了:1.php%EF%BF%BD/6120210806180147.gif
儲存的時候由於截斷,變成了1.php
連線成功
pass-12 黑名單-%00截斷-post
黑盒測試
同樣只允許上傳圖片型別
抓包發現檔案路徑變成post上傳了
進行修改,同時將%00先解碼
檔案名錶面上是123.php%EF%BF%BD/3020210806184837.jpg
但是由於截斷作用,實際上是123.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 = $_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型別檔案!";
}
}
除了改成POST上傳,和pass-11沒什麼區別
pass-13白名單-檔案包含漏洞-上傳圖片馬-讀檔案前兩個位元組
黑盒測試
看看要求:
意思是說這個系統有檔案包含漏洞,讓我們上傳三種格式的圖片馬並連線成功
做圖片馬
此外,在檔案頭加GIF89A也能繞過,目前還不清楚原理
/etc/shadow
爆出絕對路徑
上傳,連線shell
php版本要高一點,5.3以上,不然報錯很難受
原始碼分析
function getReailFileType($filename){
$file = fopen($filename, "rb");
$bin = fread($file, 2); //只讀2位元組
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_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上傳出錯!";
}
}
}
1.fopen( )函式以二進位制只讀的方式開啟檔案
2.fread() 函式讀取檔案,只讀兩個位元組,賦值給$bin
3.關閉檔案
4.unpack() 函式是將二進位制解包成其他形式,unpack("C2chars", $bin)
是輸出為兩個無符號字元型
5.intval() 函式將兩個字元轉成10進位制(預設)
6.比較10進位制數來確定檔案字尾$file_type
7.重新命名為10-99+年月日時分秒+$file_type
因為存在檔案包含漏洞,所以做一個圖片馬可以輕鬆繞過
pass-14 白名單-檔案包含漏洞-上傳圖片馬-getimagesize( )
黑盒測試
上傳GIF成功繞過,連線成功
但是jpg和和png檔案包含時報錯
原始碼分析
function isImage($filename){
$types = '.jpeg|.png|.gif';
if(file_exists($filename)){
$info = getimagesize($filename);
$ext = image_type_to_extension($info[2]);
if(stripos($types,$ext)>=0){
return $ext;
}else{
return false;
}
}else{
return false;
}
}
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$temp_file = $_FILES['upload_file']['tmp_name'];
$res = isImage($temp_file);
if(!$res){
$msg = "檔案未知,上傳失敗!";
}else{
$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").$res;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上傳出錯!";
}
}
}
1.getimagesize( )函式將測定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 影象檔案的大小並返回影象的尺寸以及檔案型別和一個可以用於普通 HTML 檔案中 IMG
標記中的 height/width 文字字串。
比如上傳的gif檔案(只加了個檔案頭GIF89A)
0=>2573;
1=>16188;
2=>1;
3=>width="2573" height="16188";
channels=>3;
mime=>image/gif;
上傳的png影象
0=>473;
1=>406;
2=>3;
3=>width="473" height="406";
bits=>8;
mime=>image/png;
上傳的jpg影象
0=>1920;
1=>1080;
2=>2;
3=>width="1920" height="1080";
bits=>8;
channels=>3;
mime=>image/jpeg;
2.image_type_to_extension根據指定的影象型別返回對應的字尾名。
- 1 = GIF
- 2 = JPG
- 3 = PNG
- 4 = SWF
3.stripos() 函式查詢字串在另一字串中第一次出現的位置(不區分大小寫),此處是查詢字尾名在白名單中的位置
4.如果在白名單中,就保留副檔名,進行重新命名:10-99+年月日時分秒+副檔名上傳
pass-15 白名單-檔案包含漏洞-上傳圖片馬-exif_imagetype()
黑盒測試
和pass-14,pass-13沒什麼不同,均繞過
原始碼分析
function isImage($filename){
//需要開啟php_exif模組
$image_type = exif_imagetype($filename);
switch ($image_type) {
case IMAGETYPE_GIF:
return "gif";
break;
case IMAGETYPE_JPEG:
return "jpg";
break;
case IMAGETYPE_PNG:
return "png";
break;
default:
return false;
break;
}
}
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$temp_file = $_FILES['upload_file']['tmp_name'];
$res = isImage($temp_file);
if(!$res){
$msg = "檔案未知,上傳失敗!";
}else{
$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$res;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上傳出錯!";
}
}
}
1.使用exif_imagetype( )函式判斷一個影象的型別
- exif_imagetype() 讀取一個影象的第一個位元組並檢查其簽名。
- 如果發現了恰當的簽名則返回一個對應的常量,否則返回
false
。 - 返回值和 getimagesize() 返回的陣列中的索引 2 的值是一樣的,但本函式快得多。
- 返回值是整型1,2,3等,不是IMAGETYPE_GIF,IMAGETYPE_JPEG