upload-labs 文件上傳靶機闖關記錄

靶機搭建

推薦使用 Windows系統搭建,我最早使用 docker pull c0ny1/upload-labs的鏡像在 Pass-03遇到問題,初步判斷是該鏡像內的 php.conf文件配置錯誤致使。
  1. 下載地址(https://github.com/c0ny1/uplo...
  2. Windows系統下解壓,第一次運行或者每次改變靶機環境的目錄時,都要運行一下modify_path.bat文件以後,再運行phpStudy.exe啓動環境。

靶機包含漏洞類型分類

clipboard.png

判斷上傳漏洞類型的方法

clipboard.png

闖關記錄

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抓包攔截數據包並修改上傳文件的後綴名便可繞過前端的後綴名限制。php

解題步驟

  • 準備上傳文件,文件內容爲
<?php phpinfo(); ?>

將文件命名爲info.jpghtml

  • 瀏覽器設置代理使得Burp Suite能夠抓包,Burp Suite中的Proxy--intercept--intercept is on,抓取數據包爲:

clipboard.png
修改數據包爲info.jpginfo.php後放行;前端

  • 訪問上傳文件的url後顯示:

clipboard.png

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-Typeimage/jpeg|image/png|image/gif,在攔截請求包時修改該內容便可繞過上傳限制。因爲上傳後文件後綴仍爲php,服務器仍將該上傳文件以php解析。git

解題步驟

  • 上傳文件名爲info2.php
  • Burp Suite抓包修改包內容爲:

clipboard.png

  • 訪問上傳文件的url後顯示:

clipboard.png

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)中有以下配置:github

AddType application/x-httpd-php .php .php3 .phtml

服務器會將php3, phtml後綴的文件當成php解析。web

解題步驟

  • 修改上傳文件的文件名爲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文件上傳解析漏洞。docker

  • .htaccess
.htaccess文件是Apache服務器中的一個配置文件,它負責相關目錄下的網頁配置。經過 .htaccess文件,能夠實現:網頁301重定向、自定義404錯誤頁面、改變文件擴展名、容許/阻止特定的用戶或者目錄的訪問、禁止目錄列表、配置默認文檔等功能IIS平臺上不存在該文件,該文件默認開啓,啓用和關閉在 httpd.conf文件中配置。

靶機中httpd.conf相關配置:shell

# 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。windows

解題步驟

  • 準備1.htaccess:
AddType application/x-httpd-php .jpg

使得服務器將全部.jpg後綴的文件當作php文件解析數組

  • 上傳.htaccess:

Burp Suite抓包修改包內容爲:

clipboard.png
修改文件名爲.htaccess並放行數據包

  • 上傳文件info4.jpg:
<?php phpinfo(); ?>
  • 查看文件:

clipboard.png

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上傳圖片文件:

clipboard.png

  • 訪問http://192.168.30.212//upload/info11.php

clipboard.png

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進製表示也能夠:

clipboard.png

  • 打開hex,修改16進制內容:

修改前
clipboard.png
修改後

clipboard.png

  • 訪問上傳文件:

路徑:

clipboard.png

訪問http://192.168.30.212/upload/info12.php

clipboard.png

00截斷原理

原理

系統在對文件名按16進制讀取文件(或者說二進制)時,若是遇到0x00(ascii碼爲零),就會認爲讀取已結束。因此原本上傳的info12.jpg文件名就被替換爲info12.php

%000x00截斷

原理同樣,只是在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解析,咱們能夠利用文件包含漏洞

解題步驟

gif

  • gif文件頭爲GIF89a ,上傳文件info13.php:
GIF89a
<?php phpinfo(); ?>
  • 利用文件包含漏洞訪問上傳文件,http://10.0.0.108/include.php?file=./upload/8820190612142038.gif

clipboard.png

png

  • 文件頭標識 (8 bytes) 89 50 4e 47 0d 0a 1a 0a

clipboard.png

  • 利用文件包含漏洞訪問上傳文件

clipboard.png

jpg

  • 文件頭標識 (2 bytes): ff, d8

clipboard.png

  • 利用文件包含漏洞訪問上傳文件

clipboard.png

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 級的錯誤信息。
示例:
<?php
$array = getimagesize("images/flower_1.jpg");
print_r($array);
?>

返回結果:

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 phpinfo(); ?>
  • 利用文件包含漏洞訪問上傳文件:

clipboard.png

  • 初次嘗試出錯:

clipboard.png

猜想多是文件內容有干擾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的圖片文件!";
    }
}

解題思路

解題步驟

http://www.secgeek.net/POC/PO...
使用連接中的圖片上傳

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

解題思路

  • unlink() 函數刪除文件。
  • 這裏先將文件保存在服務器中,再判斷後綴名,若後綴名不合法則刪除文件
  • 經過條件競爭的方式在unlink以前,訪問上傳文件。

clipboard.png

  • 利用條件競爭刪除文件時間差繞過。

解題步驟

  • burp suite抓上傳info17.php文件的數據包,進行大量重放

Intruder設置:

clipboard.png

  • 而後不斷在瀏覽器中訪問,發現經過競爭能夠訪問到上傳文件:

clipboard.png

clipboard.png

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服務器在解析多後綴文件名的文件時,會從後往前辨別後綴,一直辨別到能夠解析的後綴。

解題步驟

  • 不停發包方法同上題
  • 觀察文件夾中上傳文件夾的名字:

clipboard.png

  • 也可根據源代碼中的命名規則不停地訪問文件,直到返回結果:

clipboard.png

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.繞過

解題步驟

clipboard.png

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不爲空則filesave_name,不然filefilename
  • if (!is_array($file))判斷若是file不是數組則以'.'分組
  • 文件名命名規則$file_name = reset($file) . '.' . $file[count($file) - 1];
  • 咱們POST傳入一個save_name列表:['info20.php', '', 'jpg'],此時empty($_POST['save_name']) 爲假則filesave_name,因此由$ext = end($file);jpg能夠經過後綴名判斷(判斷結束後最後一個元素jpg彈出),而且最終文件名組裝爲upload20.php.

解題步驟

  • 上傳包數據爲:

clipboard.png

  • 訪問:

clipboard.png

相關文章
相關標籤/搜索