1. 程式人生 > 其它 >buuctf 刷題記錄 [第二章 web進階]檔案上傳

buuctf 刷題記錄 [第二章 web進階]檔案上傳

buuctf 刷題記錄 [第二章 web進階]檔案上傳

上傳,下面給了程式碼

程式碼審計

<?php
header("Content-Type:text/html; charset=utf-8");
// 每5分鐘會清除一次目錄下上傳的檔案
require_once('pclzip.lib.php');

if(!$_FILES){

        echo '

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>檔案上傳章節練習題</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <style type="text/css">
        .login-box{
            margin-top: 100px;
            height: 500px;
            border: 1px solid #000;
        }
        body{
            background: white;
        }
        .btn1{
            width: 200px;
        }
        .d1{
            display: block;
            height: 400px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="login-box col-md-12">
        <form class="form-horizontal" method="post" enctype="multipart/form-data" >
            <h1>檔案上傳章節練習題</h1>
            <hr />
            <div class="form-group">
                <label class="col-sm-2 control-label">選擇檔案:</label>
                <div class="input-group col-sm-10">
                    <div >
                    <label for="">
                        <input type="file" name="file" />
                    </label>
                    </div>
                </div>
            </div>
                
        <div class="col-sm-8  text-right">
            <input type="submit" class="btn btn-success text-right btn1" />
        </div>
        </form>
        </div>
    </div>
</body>
</html>
';

    show_source(__FILE__);
}else{
    $file = $_FILES['file'];

    if(!$file){
        exit("請勿上傳空檔案");
    }
    $name = $file['name'];

    $dir = 'upload/';
    $ext = strtolower(substr(strrchr($name, '.'), 1));
    $path = $dir.$name;

    function check_dir($dir){
        $handle = opendir($dir);
        while(($f = readdir($handle)) !== false){
            if(!in_array($f, array('.', '..'))){
                if(is_dir($dir.$f)){
                    check_dir($dir.$f.'/');
                 }else{
                    $ext = strtolower(substr(strrchr($f, '.'), 1));
                    if(!in_array($ext, array('jpg', 'gif', 'png'))){
                        unlink($dir.$f);
                    }
                }
            
            }
        }
    }

    if(!is_dir($dir)){
        mkdir($dir);
    }

    $temp_dir = $dir.md5(time(). rand(1000,9999));
    if(!is_dir($temp_dir)){
        mkdir($temp_dir);
    }

    if(in_array($ext, array('zip', 'jpg', 'gif', 'png'))){
        if($ext == 'zip'){
            $archive = new PclZip($file['tmp_name']);
            foreach($archive->listContent() as $value){
                $filename = $value["filename"];
                if(preg_match('/\.php$/', $filename)){
                     exit("壓縮包內不允許含有php檔案!");
                 }
            }
            if ($archive->extract(PCLZIP_OPT_PATH, $temp_dir, PCLZIP_OPT_REPLACE_NEWER) == 0) {
                check_dir($dir);
                   exit("解壓失敗");
            }

            check_dir($dir);
            exit('上傳成功!');
        }else{
            move_uploaded_file($file['tmp_name'], $temp_dir.'/'.$file['name']);
            check_dir($dir);
            exit('上傳成功!');
        }
    }else{
        exit('僅允許上傳zip、jpg、gif、png檔案!');
    }
}

程式碼分為3個功能

1.將上傳的檔案儲存在upload路徑下,同時檢查壓縮包內的檔名是否有帶有.或者..的,並且檢查檔案是否是jpg,gif,png

$dir = 'upload/';
$ext = strtolower(substr(strrchr($name, '.'), 1));
$path = $dir.$name;


function check_dir($dir){
$handle = opendir($dir);
while(($f = readdir($handle)) !== false){
if(!in_array($f, array('.', '..'))){
if(is_dir($dir.$f)){
check_dir($dir.$f.'/');
}else{
$ext = strtolower(substr(strrchr($f, '.'), 1));
if(!in_array($ext, array('jpg', 'gif', 'png'))){
unlink($dir.$f);

直接上傳的'jpg', 'gif', 'png檔案是沒有這個待遇的,會被放入一個tmp路徑

2.tmp路徑

$temp_dir = $dir.md5(time(). rand(1000,9999));
if(!is_dir($temp_dir)){
mkdir($temp_dir);

move_uploaded_file($file['tmp_name'], $temp_dir.'/'.$file['name']);
            check_dir($dir);
            exit('上傳成功!');

tmp路徑是隨機的md5值,從1000到9999

3.檔案解壓縮

if(in_array($ext, array('zip', 'jpg', 'gif', 'png'))){
        if($ext == 'zip'){
            $archive = new PclZip($file['tmp_name']);
            foreach($archive->listContent() as $value){
                $filename = $value["filename"];
                if(preg_match('/\.php$/', $filename)){
                     exit("壓縮包內不允許含有php檔案!");

apache漏洞

apache伺服器,有檔案解析漏洞,也就是可以上傳類似backdoor.php.notexist這種檔案,

如果遇到無法解析的字尾名會向前解析,也就是跳過notexist字尾,直接解析php字尾

用010editor改檔名

首先確定目錄穿越時候用的名字

比如需要到根目錄就是../../

然後計算好起的名字的長度

例如../../1.php.xxx這個名字就是15位的

然後給這個還沒有壓縮的馬起個佔15字元的名字,例如123456789123456字尾無所謂,反正到時候都需要010editer改

然後zip壓縮一下

用010edirer改

上傳,訪問檔案

參考:
https://www.cnblogs.com/tac2664/p/14540591.html