最新消息:图 床

簡單粗暴的文件上傳漏洞

COOL IAM 222浏览 0评论

作者:Anthem
來源:信安之路(ID:xazlsec)

前言

文件上傳漏洞可以說是日常滲透測試用得最多的一個漏洞,因為用它獲得服務器權限最快最直接。但是想真正把這個漏洞利用好卻不那麼容易,其中有很多技巧,也有很多需要掌握的知識。俗話說,知己知彼方能百戰不殆,因此想要研究怎麼防護漏洞,就要了解怎麼去利用。

特點

  • 利用簡單
  • 危害大

產生原因

缺少必要的校驗

代碼審計

基礎

關於PHP中$_FILES數組的使用方法

$_FILES/[‘file’][‘name’] 客戶端文件名稱

$_FILES/[‘file’][‘type’] 文件的MIME類型

$_FILES/[‘file’][‘size’] 文件大小 單位字節

$_FILES/[‘file’][‘tmp_name’] 文件被上傳后再服務器端臨時文件名,可以在php.ini中指定

需要注意的是在文件上傳結束后,默認的被儲存在臨時文件夾中,這時必須把他從臨時目錄中刪除或移動到其他地方,否則,腳本運行完畢后,自動刪除臨時文件,可以使用copy或者*move_uploaded_file兩個函數

程序員對某些常用函數的錯誤認識

這些函數有:empty()、isset()、strpos()、rename()等,如下面的代碼:

#!php
if($operateId == 1){
    $date = date("Ymd");
    $dest = $CONFIG->basePath."data/files/".$date."/";
    $COMMON->createDir($dest);
    //if (!is_dir($dest))   mkdir($dest, 0777);
    $nameExt = strtolower($COMMON->getFileExtName($_FILES['Filedata']['name']));
    $allowedType = array('jpg', 'gif', 'bmp', 'png', 'jpeg');
    if(!in_array($nameExt, $allowedType)){
        $msg = 0;
    }
    if(empty($msg)){
        $filename = getmicrotime().'.'.$nameExt;
        $file_url = urlencode($CONFIG->baseUrl.'data/files/'.$date."/".$filename);
        $filename = $dest.$filename;
        if(empty($_FILES['Filedata']['error'])){
            move_uploaded_file($_FILES['Filedata']['tmp_name'],$filename);
        }
        if (file_exists($filename)){
            //$msg = 1;
            $msg = $file_url;
            @chmod($filename, 0444);
        }else{
            $msg = 0;
        }
    }
    $outMsg = "fileUrl=".$msg;
    $_SESSION["eoutmsg"] = $outMsg;
    exit;
}

我們來看上面的這段代碼,要想文件成功的上傳, if(empty($msg)) 必須為True才能進入if的分支,接下來我們來看empty函數何時返回True,看看PHP Manual怎麼說,如圖

客戶端校驗

JavaScript校驗

驗證代碼
<?php
//文件上傳漏洞演示腳本之js驗證
$uploaddir = 'uploads/';
if (isset($_POST['submit'])) {
    if (file_exists($uploaddir)) {
        if (move_uploaded_file($_FILES['upfile']['tmp_name'], $uploaddir . '/' . $_FILES['upfile']['name'])) {
            echo '文件上傳成功,保存於:' . $uploaddir . $_FILES['upfile']['name'] . "/n";
        }
    } else {
        exit($uploaddir . '文件夾不存在,請手工創建!');
    }
    //print_r($_FILES);
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=gbk"/>
    <meta http-equiv="content-language" content="zh-CN"/>
    <title>文件上傳漏洞演示腳本--JS驗證實例</title>
    <script type="text/javascript">
       function checkFile() {
            var file = document.getElementsByName('upfile')[0].value;
            if (file == null || file == "") {
                alert("你還沒有選擇任何文件,不能上傳!");
                return false;
            }
            //定義允許上傳的文件類型
            var allow_ext = ".jpg|.jpeg|.png|.gif|.bmp|";
            //提取上傳文件的類型
            var ext_name = file.substring(file.lastIndexOf("."));
            //alert(ext_name);
            //alert(ext_name + "|");
            //判斷上傳文件類型是否允許上傳
            if (allow_ext.indexOf(ext_name + "|") == -1) {
                var errMsg = "該文件不允許上傳,請上傳" + allow_ext + "類型的文件,當前文件類型為:" +     ext_name;
                alert(errMsg);
                return false;
            }
        }
    </script>
<body>
<h3>文件上傳漏洞演示腳本--JS驗證實例</h3>
<form action="" method="post" enctype="multipart/form-data" name="upload" onsubmit="return     checkFile()">
    <input type="hidden" name="MAX_FILE_SIZE" value="204800"/>
    請選擇要上傳的文件<input type="file" name="upfile"/>
    <input type="submit" name="submit" value="上傳"/>
</form>
</body>
</html>

客戶端JS驗證通常做法是驗證上傳文件的擴展名是否符合驗證條件

繞過姿勢

1.通過firefox的F12修改js代碼繞過驗證
2.使用burp抓包直接提交,繞過js驗證

服務器端校驗

文件頭content-type字段校驗(服務端MIME類型檢測)

MIME類型介紹

MIME type的縮寫為(Multipurpose Internet Mail Extensions)代表互聯網媒體類型(Internet media type),MIME使用一個簡單的字符串組成,最初是為了標識郵件Email附件的類型,在html文件中可以使用content-type屬性表示,描述了文件類型的互聯網標準。

Internet中有一個專門組織IANA來確認標準的MIME類型,但Internet發展的太快,很多應用程序等不及IANA來確認他們使用的MIME類型為標準類型。因此他們使用在類別中以x-開頭的方法標識這個類別還沒有成為標準,例如:x-gzip,x-tar等。事實上這些類型運用的很廣泛,已經成為了事實標準。只要客戶機和服務器共同承認這個MIME類型,即使它是不標準的類型也沒有關係,客戶程序就能根據MIME類型,採用具體的處理手段來處理數據。

Response對象通過設置ContentType使客戶端瀏覽器,區分不同種類的數據,並根據不同的MIME調用瀏覽器內不同的程序嵌入模塊來處理相應的數據。

MIME類型格式:

類別/子類別;參數
Content-Type: [type]/[subtype]; parameter

MIME主類別:

text:用於標準化地表示的文本信息,文本消息可以是多種字符集和或者多種格式的;

Multipart:用於連接消息體的多個部分構成一個消息,這些部分可以是不同類型的數據;

Application:用於傳輸應用程序數據或者二進制數據;

Message:用於包裝一個E-mail消息;

Image:用於傳輸靜態圖片數據;

Audio:用於傳輸音頻或者音聲數據;

Video:用於傳輸動態影像數據,可以是與音頻編輯在一起的視頻數據格式。

常見MIME類型:
利用PHP特性(使用數組繞過)

转载请注明:IAMCOOL » 簡單粗暴的文件上傳漏洞

0 0 vote
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x