摘要:由于上傳后文件后綴仍為,服務器仍將該上傳文件以解析。文件是服務器中的一個配置文件,它負責相關目錄下的網頁配置。文件流實際應用文件系統包括對備用數據流的支持。在中,此默認數據流稱為。
靶機搭建
推薦使用Windows系統搭建,我最先使用docker pull c0ny1/upload-labs的鏡像在Pass-03遇到問題,初步判斷是該鏡像內的php.conf文件配置錯誤導致。
下載地址(https://github.com/c0ny1/uplo...)
Windows系統下解壓,第一次運行或者每次改變靶機環境的目錄時,都要運行一下modify_path.bat文件之后,再運行phpStudy.exe啟動環境。
靶機包含漏洞類型分類 判斷上傳漏洞類型的方法 闖關記錄 Pass-01 提示與查看源碼本pass在客戶端使用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 + "類型的文件,當前文件類型為:" + ext_name; alert(errMsg); return false; } }解題思路
前端校驗上傳文件的后綴名是否為.jpg|.png|.gif,使用Burp Suite抓包攔截數據包并修改上傳文件的后綴名即可繞過前端的后綴名限制。
解題步驟準備上傳文件,文件內容為
將文件命名為info.jpg
瀏覽器設置代理使得Burp Suite可以抓包,Burp Suite中的Proxy--intercept--intercept is on,抓取數據包為:
修改數據包為info.jpg為info.php后放行;
訪問上傳文件的url后顯示:
Pass-02 提示與查看源碼本pass在服務端對數據包的MIME進行檢查!
$is_upload = false; $msg = null; if (isset($_POST["submit"])) { if (file_exists(UPLOAD_PATH)) { if (($_FILES["upload_file"]["type"] == "image/jpeg") || ($_FILES["upload_file"]["type"] == "image/png") || ($_FILES["upload_file"]["type"] == "image/gif")) { $temp_file = $_FILES["upload_file"]["tmp_name"]; $img_path = UPLOAD_PATH . "/" . $_FILES["upload_file"]["name"] if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = "上傳出錯!"; } } else { $msg = "文件類型不正確,請重新上傳!"; } } else { $msg = UPLOAD_PATH."文件夾不存在,請手工創建!"; } }解題思路
對文件MIME類型進行了驗證判斷,即請求數據中的Content-Type為image/jpeg|image/png|image/gif,在攔截請求包時修改該內容即可繞過上傳限制。由于上傳后文件后綴仍為php,服務器仍將該上傳文件以php解析。
解題步驟上傳文件名為info2.php
Burp Suite抓包修改包內容為:
訪問上傳文件的url后顯示:
Pass-03 提示與查看源碼本pass禁止上傳.asp|.aspx|.php|.jsp后綴文件!
$is_upload = false; $msg = null; if (isset($_POST["submit"])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".asp",".aspx",".php",".jsp"); $file_name = trim($_FILES["upload_file"]["name"]); $file_name = deldot($file_name);//刪除文件名末尾的點 $file_ext = strrchr($file_name, "."); $file_ext = strtolower($file_ext); //轉換為小寫 $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 = "不允許上傳.asp,.aspx,.php,.jsp后綴文件!"; } } else { $msg = UPLOAD_PATH . "文件夾不存在,請手工創建!"; } }解題思路
黑名單判斷,服務器端禁止上傳".asp",".aspx",".php",".jsp"后綴的腳本文件,可以上傳例如php3, phtml后綴的文件繞過,前提是配置文件(C:UsersxxxxxDesktopupload-labs-envApacheconfhttpd.conf)中有如下配置:
AddType application/x-httpd-php .php .php3 .phtml
服務器會將php3, phtml后綴的文件當成php解析。
解題步驟修改上傳文件的文件名為info3.php3
上傳后訪問可見phpinfo()
Pass-04 提示與查看源碼本pass禁止上傳.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后綴文件!
$is_upload = false; $msg = null; if (isset($_POST["submit"])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".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); //轉換為小寫 $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 . "文件夾不存在,請手工創建!"; } }解題思路
依然是黑名單判斷,不過這次的限制更多,但是沒有包括.htaccess,可以利用配合Apache的.htaccess文件上傳解析漏洞。
.htaccess
.htaccess文件是Apache服務器中的一個配置文件,它負責相關目錄下的網頁配置。通過.htaccess文件,可以實現:網頁301重定向、自定義404錯誤頁面、改變文件擴展名、允許/阻止特定的用戶或者目錄的訪問、禁止目錄列表、配置默認文檔等功能IIS平臺上不存在該文件,該文件默認開啟,啟用和關閉在httpd.conf文件中配置。
靶機中httpd.conf相關配置:
# AllowOverride controls what directives may be placed in .htaccess files. # It can be "All", "None", or any combination of the keywords: # Options FileInfo AuthConfig Limit # AllowOverride All
造成了我們可以上傳.htaccess文件解析漏洞,來繞過驗證進行上傳WEBShell。
解題步驟
準備1.htaccess:
AddType application/x-httpd-php .jpg
使得服務器將所有.jpg后綴的文件當做php文件解析
上傳.htaccess:
Burp Suite抓包修改包內容為:
修改文件名為.htaccess并放行數據包
上傳文件info4.jpg:
查看文件:
Pass-05 提示與查看源碼本pass禁止上傳.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|.htaccess后綴文件!
$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 . "文件夾不存在,請手工創建!"; } }解題思路
黑名單判斷加入.htaccess,但是源代碼中沒有$file_ext = strtolower($file_ext); //轉換為小寫這一行代碼,可以使用大小寫繞過。
解題步驟上傳文件名info5.PhP
Pass-06 提示與查看源碼本pass禁止上傳.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后綴文件!
$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 = $_FILES["upload_file"]["name"]; $file_name = deldot($file_name);//刪除文件名末尾的點 $file_ext = strrchr($file_name, "."); $file_ext = strtolower($file_ext); //轉換為小寫 $file_ext = str_ireplace("::$DATA", "", $file_ext);//去除字符串::$DATA 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 . "文件夾不存在,請手工創建!"; } }解題思路
源代碼缺少$file_ext = trim($file_ext); //收尾去空,可以文件名后綴增加空格繞過
解題步驟上傳文件名info6.php
Pass-07 提示與查看源碼本pass禁止上傳所有可以解析的后綴!
$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_ext = strrchr($file_name, "."); $file_ext = strtolower($file_ext); //轉換為小寫 $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."/".$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = "上傳出錯!"; } } else { $msg = "此文件類型不允許上傳!"; } } else { $msg = UPLOAD_PATH . "文件夾不存在,請手工創建!"; } }解題思路
源代碼缺少$file_name = deldot($file_name);//刪除文件名末尾的點限制,可以文件名后綴增加.繞過,windows系統下會自動去掉后綴名中最后的.
解題步驟上傳文件名info7.php.
Pass-08 提示與查看源碼本pass禁止上傳.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|.htaccess后綴文件!
$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 = strtolower($file_ext); //轉換為小寫 $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 . "文件夾不存在,請手工創建!"; } }解題思路
源代碼缺少 $file_ext = str_ireplace("::$DATA", "", $file_ext);//去除字符串::$DATA限制,可以文件名后綴增加::$DATA繞過
Windows下NTFS文件系統的一個特性,即NTFS文件系統的存儲數據流的一個屬性 DATA 時,就是請求 a.asp 本身的數據,如果a.asp 還包含了其他的數據流,比如 a.asp:lake2.asp,請求 a.asp:lake2.asp::$DATA,則是請求a.asp中的流數據lake2.asp的流數據內容。
NTFS文件流實際應用
NTFS文件系統包括對備用數據流的支持。這不是眾所周知的功能,主要包括提供與Macintosh文件系統中的文件的兼容性。備用數據流允許文件包含多個數據流。每個文件至少有一個數據流。在Windows中,此默認數據流稱為:$DATA。
解題步驟上傳文件名info8.php::$DATA,訪問時去除后綴
Pass-09 提示與查看源碼本pass只允許上傳.jpg|.png|.gif后綴的文件!
$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 = strtolower($file_ext); //轉換為小寫 $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."/".$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = "上傳出錯!"; } } else { $msg = "此文件類型不允許上傳!"; } } else { $msg = UPLOAD_PATH . "文件夾不存在,請手工創建!"; } }解題思路
由$img_path = UPLOAD_PATH."/".$file_name;得上傳后文件的URL命名規則是由$file_name直接拼接而成
解題步驟上傳文件名info9.php. .
Pass-10 提示與查看源碼本pass會從文件名中去除.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|.htaccess字符!
$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","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); $temp_file = $_FILES["upload_file"]["tmp_name"]; $img_path = UPLOAD_PATH."/".$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = "上傳出錯!"; } } else { $msg = UPLOAD_PATH . "文件夾不存在,請手工創建!"; } }解題思路
$file_name = str_ireplace($deny_ext,"", $file_name);只對文件后綴名進行一次過濾,雙寫文件名繞過。
解題步驟上傳文件名改成info10.pphphp
Pass-11 提示與查看源碼本pass上傳路徑可控!
$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類型文件!"; } }解題思路
服務器端上傳文件名的后綴做了限制
$img_path = $_GET["save_path"]."/".rand(10, 99).date("YmdHis").".".$file_ext;可知上傳路徑命名規則使用用戶get請求的save_path值拼接而成。
考慮使用上傳路徑名%00截斷繞過,不過這需要對文件有足夠的權限,比如說創建文件夾,上傳的文件名寫成1.jpg, save_path改成../upload/1.php%00,最后保存下來的文件就是1.php
解題步驟修改save_path值為../upload/info11.php%00上傳圖片文件:
訪問http://192.168.30.212//upload/info11.php:
Pass-12 提示與查看源碼本pass上傳路徑可控!
$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類型文件!"; } }解題思路
$img_path = $_POST["save_path"]."/".rand(10, 99).date("YmdHis").".".$file_ext;和Pass-11相比將GET換為了POST,思路相同
這次的save_path是通過post傳進來的,在進行00截斷時需要在hex中修改
解題步驟修改post參數的值,這里在php的后面添加了一個空格和字母a,其實寫什么都可以,只是一般空格的16進制為0x20,比較好記,加個a好找到空格的位置,如果寫個任意字符,再去查他的16進制表示也可以:
打開hex,修改16進制內容:
修改前
修改后
訪問上傳文件:
路徑:
訪問http://192.168.30.212/upload/info12.php:
00截斷原理 原理系統在對文件名按16進制讀取文件(或者說二進制)時,如果遇到0x00(ascii碼為零),就會認為讀取已結束。所以本來上傳的info12.jpg文件名就被替換為info12.php。
%00與0x00截斷原理一樣,只是在Pass-11中為GET方式,服務器在進行URL解碼時將其解碼成0x00,Pass-12中為POST方式,沒有URL解碼這一步驟,所以要在hex值中修改,形成0x00截斷。
Pass-13 提示與查看源碼本pass檢查圖標內容開頭2個字節!
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 = "上傳出錯!"; } } }解題思路
服務端檢測文件頭,并將上傳文件的后綴重命名為檢測到的文件類型
關于服務端檢測文件頭,我們可以在文件起始加入jpg|png|gif文件的文件頭來繞過
十進制轉十六進制: gif為47 49 , png為89 50, jpg為ff d8
關于文件上傳后被重命名為圖片文件,不能當做php解析,我們可以利用文件包含漏洞
解題步驟 gifgif文件頭為GIF89a ,上傳文件info13.php:
GIF89a
利用文件包含漏洞訪問上傳文件,http://10.0.0.108/include.php?file=./upload/8820190612142038.gif
png文件頭標識 (8 bytes) 89 50 4e 47 0d 0a 1a 0a
利用文件包含漏洞訪問上傳文件
jpg文件頭標識 (2 bytes): ff, d8
利用文件包含漏洞訪問上傳文件
Pass-14 提示與查看源碼本pass使用getimagesize()檢查是否為圖片文件!
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 = "上傳出錯!"; } } }解題思路
這里使用getimagesize()檢查是否為圖片文件:
getimagesize() 函數用于獲取圖像大小及相關信息,成功返回一個數組,失敗則返回 FALSE 并產生一條 E_WARNING 級的錯誤信息。
示例:
返回結果:
Array ( [0] => 350 [1] => 318 [2] => 2 [3] => width="350" height="318" [bits] => 8 [channels] => 3 [mime] => image/jpeg )
我們用到了索引[2],給出的是圖像的類型,返回的是數字,其中1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF(intel byte order),8 = TIFF(motorola byte order),9 = JPC,10 = JP2,11 = JPX,12 = JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM
與上一題解題思路一致,修改文件頭繞過,但是本題的驗證不只是文件頭的前兩位。
解題步驟 gif文件頭:GIF89a
png文件頭hex:89 50 4e 47 0d 0a 1a 0a
jpg上傳正常jpg圖片,抓包修改包內容,文件末尾加入
利用文件包含漏洞訪問上傳文件:
初次嘗試出錯:
猜測可能是文件內容有干擾PHP解析的數據出現,后刪除部分內容上傳后成功
Pass-16 提示與查看源碼本pass使用exif_imagetype()檢查是否為圖片文件!
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 = "上傳出錯!"; } } }解題思路
exif_imagetype()函數是php內置函數,用來獲取圖片類型,思路同上題,文件頭繞過
解題步驟同Pass-16
Pass-16 提示與查看源碼本pass重新渲染了圖片!
$is_upload = false; $msg = null; if (isset($_POST["submit"])){ // 獲得上傳文件的基本信息,文件名,類型,大小,臨時文件路徑 $filename = $_FILES["upload_file"]["name"]; $filetype = $_FILES["upload_file"]["type"]; $tmpname = $_FILES["upload_file"]["tmp_name"]; $target_path=UPLOAD_PATH."/".basename($filename); // 獲得上傳文件的擴展名 $fileext= substr(strrchr($filename,"."),1); //判斷文件后綴與類型,合法才進行上傳操作 if(($fileext == "jpg") && ($filetype=="image/jpeg")){ if(move_uploaded_file($tmpname,$target_path)){ //使用上傳的圖片生成新的圖片 $im = imagecreatefromjpeg($target_path); if($im == false){ $msg = "該文件不是jpg格式的圖片!"; @unlink($target_path); }else{ //給新圖片指定文件名 srand(time()); $newfilename = strval(rand()).".jpg"; //顯示二次渲染后的圖片(使用用戶上傳圖片生成的新圖片) $img_path = UPLOAD_PATH."/".$newfilename; imagejpeg($im,$img_path); @unlink($target_path); $is_upload = true; } } else { $msg = "上傳出錯!"; } }else if(($fileext == "png") && ($filetype=="image/png")){ if(move_uploaded_file($tmpname,$target_path)){ //使用上傳的圖片生成新的圖片 $im = imagecreatefrompng($target_path); if($im == false){ $msg = "該文件不是png格式的圖片!"; @unlink($target_path); }else{ //給新圖片指定文件名 srand(time()); $newfilename = strval(rand()).".png"; //顯示二次渲染后的圖片(使用用戶上傳圖片生成的新圖片) $img_path = UPLOAD_PATH."/".$newfilename; imagepng($im,$img_path); @unlink($target_path); $is_upload = true; } } else { $msg = "上傳出錯!"; } }else if(($fileext == "gif") && ($filetype=="image/gif")){ if(move_uploaded_file($tmpname,$target_path)){ //使用上傳的圖片生成新的圖片 $im = imagecreatefromgif($target_path); if($im == false){ $msg = "該文件不是gif格式的圖片!"; @unlink($target_path); }else{ //給新圖片指定文件名 srand(time()); $newfilename = strval(rand()).".gif"; //顯示二次渲染后的圖片(使用用戶上傳圖片生成的新圖片) $img_path = UPLOAD_PATH."/".$newfilename; imagegif($im,$img_path); @unlink($target_path); $is_upload = true; } } else { $msg = "上傳出錯!"; } }else{ $msg = "只允許上傳后綴為.jpg|.png|.gif的圖片文件!"; } }解題思路
程序通過imagecreatefromjpeg()函數調用了PHP GD庫(GD庫,是php處理圖形的擴展庫),對圖片進行了轉換。
將一個正常顯示的圖片,上傳到服務器。下載被渲染后與原始圖片對比,在仍然相同的數據塊部分內部插入Webshell代碼,然后上傳。
特殊的上傳技巧,繞過PHP圖片轉換實現遠程代碼執行
大佬解題:https://xz.aliyun.com/t/2657
解題步驟http://www.secgeek.net/POC/PO...
使用鏈接中的圖片上傳
需要代碼審計!
$is_upload = false; $msg = null; if(isset($_POST["submit"])){ $ext_arr = array("jpg","png","gif"); $file_name = $_FILES["upload_file"]["name"]; $temp_file = $_FILES["upload_file"]["tmp_name"]; $file_ext = substr($file_name,strrpos($file_name,".")+1); $upload_file = UPLOAD_PATH . "/" . $file_name; if(move_uploaded_file($temp_file, $upload_file)){ if(in_array($file_ext,$ext_arr)){ $img_path = UPLOAD_PATH . "/". rand(10, 99).date("YmdHis").".".$file_ext; rename($upload_file, $img_path); $is_upload = true; }else{ $msg = "只允許上傳.jpg|.png|.gif類型文件!"; unlink($upload_file); } }else{ $msg = "上傳出錯!"; } }解題思路
unlink() 函數刪除文件。
這里先將文件保存在服務器中,再判斷后綴名,若后綴名不合法則刪除文件
通過條件競爭的方式在unlink之前,訪問上傳文件。
利用條件競爭刪除文件時間差繞過。
解題步驟burp suite抓上傳info17.php文件的數據包,進行大量重放
Intruder設置:
然后不斷在瀏覽器中訪問,發現通過競爭可以訪問到上傳文件:
Pass-18 提示與查看源碼需要代碼審計!
//index.php $is_upload = false; $msg = null; if (isset($_POST["submit"])) { require_once("./myupload.php"); $imgFileName =time(); $u = new MyUpload($_FILES["upload_file"]["name"], $_FILES["upload_file"]["tmp_name"], $_FILES["upload_file"]["size"],$imgFileName); $status_code = $u->upload(UPLOAD_PATH); switch ($status_code) { case 1: $is_upload = true; $img_path = $u->cls_upload_dir . $u->cls_file_rename_to; break; case 2: $msg = "文件已經被上傳,但沒有重命名。"; break; case -1: $msg = "這個文件不能上傳到服務器的臨時文件存儲目錄。"; break; case -2: $msg = "上傳失敗,上傳目錄不可寫。"; break; case -3: $msg = "上傳失敗,無法上傳該類型文件。"; break; case -4: $msg = "上傳失敗,上傳的文件過大。"; break; case -5: $msg = "上傳失敗,服務器已經存在相同名稱文件。"; break; case -6: $msg = "文件無法上傳,文件不能復制到目標目錄。"; break; default: $msg = "未知錯誤!"; break; } } //myupload.php class MyUpload{ ...... ...... ...... var $cls_arr_ext_accepted = array( ".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt", ".html", ".xml", ".tiff", ".jpeg", ".png" ); ...... ...... ...... /** upload() ** ** Method to upload the file. ** This is the only method to call outside the class. ** @para String name of directory we upload to ** @returns void **/ function upload( $dir ){ $ret = $this->isUploadedFile(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->setDir( $dir ); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->checkExtension(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->checkSize(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } // if flag to check if the file exists is set to 1 if( $this->cls_file_exists == 1 ){ $ret = $this->checkFileExists(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } } // if we are here, we are ready to move the file to destination $ret = $this->move(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } // check if we need to rename the file if( $this->cls_rename_file == 1 ){ $ret = $this->renameFile(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } } // if we are here, everything worked as planned :) return $this->resultUpload( "SUCCESS" ); } ...... ...... ...... };
網頁上顯示的代碼并不全?。?!需要去WWW文件夾中查看
解題思路對文件后綴名做了白名單判斷,然后檢查文件大小、文件是否存在等等。
將文件上傳后,對文件重新命名,同樣存在條件競爭的漏洞。
function renameFile(){ // if no new name was provided, we use if( $this->cls_file_rename_to == "" ){ $allchar = "abcdefghijklnmopqrstuvwxyz" ; $this->cls_file_rename_to = "" ; mt_srand (( double) microtime() * 1000000 ); for ( $i = 0; $i<8 ; $i++ ){ $this->cls_file_rename_to .= substr( $allchar, mt_rand (0,25), 1 ) ; } } // Remove the extension and put it back on the new file name $extension = strrchr( $this->cls_filename, "." ); $this->cls_file_rename_to .= $extension; if( !rename( $this->cls_upload_dir . $this->cls_filename, $this->cls_upload_dir . $this->cls_file_rename_to )){ return "RENAME_FAILURE"; } else { return 1; } }
初始文件命名規則$this->cls_upload_dir . $this->cls_filename,重命名規則$this->cls_upload_dir . $this->cls_file_rename_to,當大量文件需要被重命名時就會出現條件競爭
move在rename之前,move操作進行了一次文件保存, 然后rename進行了一次更改文件名。
利用burp不間斷地發送上傳圖片馬的數據包,由于條件競爭,程序會出現來不及rename的問題,從而上傳成功。
查看配置mime.types,這里記錄著可被Apache服務器所識別的文件屬性:
#application/x-7z-compressed 7z
7z后綴并不被Apache服務器所識別,卻在上傳文件名后綴的白名單中,可以利用Apache的解析漏洞將上傳的7z后綴文件當做php文件解析。
Apache的解析漏洞Apache服務器在解析多后綴文件名的文件時,會從后往前辨別后綴,一直辨別到可以解析的后綴。
解題步驟不停發包方法同上題
觀察文件夾中上傳文件夾的名字:
也可根據源代碼中的命名規則不停地訪問文件,直到返回結果:
Pass-19 提示與查看源碼本pass的取文件名通過$_POST來獲取。
$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","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess"); $file_name = $_POST["save_name"]; $file_ext = pathinfo($file_name,PATHINFO_EXTENSION); if(!in_array($file_ext,$deny_ext)) { $temp_file = $_FILES["upload_file"]["tmp_name"]; $img_path = UPLOAD_PATH . "/" .$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; }else{ $msg = "上傳出錯!"; } }else{ $msg = "禁止保存為該類型文件!"; } } else { $msg = UPLOAD_PATH . "文件夾不存在,請手工創建!"; } }解題思路
黑名單策略,文件名用戶可控,文件命名upload-19.php.繞過
解題步驟 Pass-20 提示與查看源碼Pass-20來源于CTF,請審計代碼!
$is_upload = false; $msg = null; if(!empty($_FILES["upload_file"])){ //檢查MIME $allow_type = array("image/jpeg","image/png","image/gif"); if(!in_array($_FILES["upload_file"]["type"],$allow_type)){ $msg = "禁止上傳該類型文件!"; }else{ //檢查文件名 $file = empty($_POST["save_name"]) ? $_FILES["upload_file"]["name"] : $_POST["save_name"]; if (!is_array($file)) { $file = explode(".", strtolower($file)); } $ext = end($file); $allow_suffix = array("jpg","png","gif"); if (!in_array($ext, $allow_suffix)) { $msg = "禁止上傳該后綴文件!"; }else{ $file_name = reset($file) . "." . $file[count($file) - 1]; $temp_file = $_FILES["upload_file"]["tmp_name"]; $img_path = UPLOAD_PATH . "/" .$file_name; if (move_uploaded_file($temp_file, $img_path)) { $msg = "文件上傳成功!"; $is_upload = true; } else { $msg = "文件上傳失??!"; } } } }else{ $msg = "請選擇要上傳的文件!"; }解題思路
文件命名規則:$file_name = reset($file) . "." . $file[count($file) - 1];
reset():將內部指針指向數組中的第一個元素,并輸出。
end():將內部指針指向數組中的最后一個元素,并輸出。
$file = empty($_POST["save_name"]) ? $_FILES["upload_file"]["name"] : $_POST["save_name"];如果save_name不為空則file為save_name,否則file為filename
if (!is_array($file))判斷如果file不是數組則以"."分組
文件名命名規則$file_name = reset($file) . "." . $file[count($file) - 1];
我們POST傳入一個save_name列表:["info20.php", "", "jpg"],此時empty($_POST["save_name"]) 為假則file為save_name,所以由$ext = end($file);為jpg可以通過后綴名判斷(判斷結束后最后一個元素jpg彈出),并且最終文件名組裝為upload20.php.
解題步驟上傳包數據為:
訪問:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/31708.html
摘要:出題思路本次題目來自于我的一個外包項目實踐?;睾现票荣愐苑昼姙橐换睾?。選手在比賽過程中需要盜取到對手的密鑰,以竊聽他方內容,并修改己方密鑰以放泄露動態該部分同樣由中心服務器與完成。 Author: RytiaDate: 20190427Blog: www.zzfly.net本人才學疏淺,望君不吝賜教 背景 受學校老師邀請,為學弟學妹舉辦分享會介紹 AWD 相關經驗,本人一時頭腦風暴采用...
閱讀 3105·2021-11-18 10:02
閱讀 2617·2021-10-13 09:47
閱讀 3033·2021-09-22 15:07
閱讀 791·2019-08-30 15:43
閱讀 1809·2019-08-30 10:59
閱讀 1684·2019-08-29 15:34
閱讀 1702·2019-08-29 15:06
閱讀 438·2019-08-29 13:28