简介

在网络安全领域,文件上传漏洞是一个常见且危险的漏洞。通过这些漏洞,攻击者可以上传恶意文件并在目标服务器上执行任意代码,从而控制整个系统。在 Upload-Lab 的第15关,我们将学习如何通过巧妙利用头文件来绕过文件上传的验证限制。这一关的挑战在于理解和利用 头文件的细节,从而成功绕过服务器的安全检查。

攻击思路

下面是第15关关键源码部分:

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

这段代码用于检查文件是否是图片,并返回文件扩展名。如果不是图片,返回 false。代码使用了 getimagesizeimage_type_to_extension 来获取文件的信息和扩展名。然而,代码存在一些漏洞,可能导致安全问题和错误行为。

代码漏洞分析

  1. 文件类型检查不够严格
    • 代码使用 getimagesize 获取文件信息,然后使用 image_type_to_extension 获取文件扩展名。然而,getimagesize 仅检查文件头信息,这意味着恶意用户可以创建一个伪造的文件头,使文件通过检查,但实际上是一个恶意文件。
  2. 文件扩展名比较存在问题
    • stripos($types, $ext) >= 0 用于检查文件扩展名是否在允许的类型中。但这段代码会误将任何包含在 $types 中的字符串视为有效。例如,如果 $ext.jpegabc,则 stripos 仍会返回非负值。
  3. 未处理 **getimagesize** 错误
    • 如果 getimagesize 失败,它会返回 false。当前代码假设 getimagesize 总是成功并返回一个数组。如果 getimagesize 失败,代码将抛出未定义索引的错误。

解法步骤

  1. 构造webshell脚本

在桌面上新建一个名为webshell.php的脚本,内容如下所示:

GIF89a
<?php phpinfo(); ?>

其中GIF89awebshell脚本伪装GIF图片绕过文件上传验证。

补充知识:

  • Png图片文件包括8字节:89 50 4E 47 0D 0A 1A 0A。即为 .PNG
  • Jpg图片文件包括2字节:FF D8
  • Gif图片文件包括6字节:47 49 46 38 39|37 61 。即为 GIF89(7)a
  • Bmp图片文件包括2字节:42 4D。即为 BM

上传成功后,如下图所示:

  1. 验证上传结果

尝试访问上传的文件并执行命令。例如,访问 http://localhost/include.php?file=upload/9420240807113231.gif,返回如下信息,则说明文件上传绕过成功。

结语

通过第15关的学习,我们深入了解了如何利用头文件绕过文件上传验证限制。这不仅增强了我们对文件上传漏洞的认识,也提高了我们在实际工作中防御此类攻击的能力。在实践中,了解攻击手法和防御措施同样重要,只有这样才能构建更为安全的网络应用。