Web通用漏洞--文件上传

web,通用,漏洞,文件,上传 · 浏览次数 : 10

小编点评

**文件上传绕过分析** 文件上传绕过分析是网站开发者利用不当漏洞进行文件上传的技巧。通过分析漏洞,网站开发者可以上传任意大小的文件,从而访问网站内部的敏感数据。 **绕过方法** * **白名单验证**:网站开发者使用白名单验证文件的后缀名,只允许合法的后缀名。通过在数据库中维护合法的后缀名,可以绕过验证。 * **空值爆破**:网站开发者利用空值爆破技术,在上传文件后,将上传过后的文件再访问数据库,进行无限制的上传。 * **绕过二次渲染**:网站开发者利用绕过二次渲染技术,在上传文件后,将上传过后的文件再次访问数据库,进行无限制的上传。 * **文件存储方案分站存储**:网站开发者利用文件存储方案分站存储技术,将文件存储在不同站点、服务器上,无法进行绕过。 **漏洞** * **白名单验证**:网站开发者在数据库中维护合法的后缀名,只允许合法的后缀名。通过在数据库中维护合法的后缀名,可以绕过验证。 * **空值爆破**:网站开发者利用空值爆破技术,在上传文件后,将上传过后的文件再访问数据库,进行无限制的上传。 **结果** 通过绕过方法,网站开发者可以上传任意大小的文件,从而访问网站内部的敏感数据。 **安全建议** * 对网站进行漏洞扫描。 * 严格验证文件的后缀名。 * 避免使用空值爆破技术。 * 对文件存储方案进行分站存储。 * 谨慎使用文件存储方案分站存储技术。

正文

Web通用漏洞--文件上传

概述

文件上传安全指的是攻击者通过利用上传实现后门的写入连接后门进行权限控制的安全问题,对于如何确保这类安全问题,一般会从原生态功能中的文件内容,文件后缀,文件类型等方面判断,但是漏洞可能不仅在本身的代码验证逻辑中出现安全问题,也会在语言版本,语言函数,中间件,引用的第三方编辑器等存在缺陷地方配合利用。另外文件上传也有多个存储逻辑,不同的文件存储方案也会给攻击者带来不一样的挑战!

靶场upload-labs-docker

js验证

采用前端代码进行文件后缀验证
在这里插入图片描述
绕过方法

  1. 删除前端代码
    通过查看前端代码,发现上传form表单有个javascirpt事件,即检测文件后缀白名单,删除即可
    在这里插入图片描述
  2. 在浏览器禁用javascript
  3. 将文件后缀修改为允许上传的后缀,通过前端校验后抓包修改文件后缀

修改解析规则

在这里插入图片描述
上传.htaccess文件添加配置解析规则,将png文件后缀进行php解析

AddType application/x-httpd-php .png

上传写有php代码的png文件,访问
在这里插入图片描述

文件类型绕过

在这里插入图片描述
源码

    <?php
        header("Content-type: text/html;charset=utf-8");
        error_reporting(0);
        //设置上传目录
        define("UPLOAD_PATH", dirname(__FILE__) . "/upload/");
        define("UPLOAD_URL_PATH", str_replace($_SERVER['DOCUMENT_ROOT'], "", UPLOAD_PATH));
        if (!file_exists(UPLOAD_PATH)) {
            mkdir(UPLOAD_PATH, 0755);
        }
        $is_upload = false;
        if (!empty($_POST['submit'])) {
            if (!in_array($_FILES['file']['type'], ["image/jpeg", "image/png", "image/gif", "image/jpg"])) {
                echo "<script>black();</script>";
            } else {
                $name = basename($_FILES['file']['name']);
                if (move_uploaded_file($_FILES['file']['tmp_name'], UPLOAD_PATH . $name)) {
                    $is_upload = true;
                } else {
                    echo "<script>alert('上传失败')</script>";
                }
            }
        }
    ?>

代码中通过查看type白名单进行过滤
通过抓包将数据包中的content-type进行修改即可上传成功
在这里插入图片描述

文件头检测

在这里插入图片描述
源码

 <?php
        header("Content-type: text/html;charset=utf-8");
        error_reporting(0);
        //设置上传目录
        define("UPLOAD_PATH", dirname(__FILE__) . "/upload/");
        define("UPLOAD_URL_PATH", str_replace($_SERVER['DOCUMENT_ROOT'], "", UPLOAD_PATH));
        if (!file_exists(UPLOAD_PATH)) {
            mkdir(UPLOAD_PATH, 0755);
        }
        $is_upload = false;
        if (!empty($_POST['submit'])) {
            if (!$_FILES['file']['size']) {
                echo "<script>error();</script>";
            } else {
                $file = fopen($_FILES['file']['tmp_name'], "rb");
                $bin = fread($file, 4);
                fclose($file);
                if (!in_array($_FILES['file']['type'], ["image/jpeg", "image/jpg", "image/png", "image/gif"])) {
                    echo "<script>black();</script>";
                } else if (!in_array(bin2hex($bin), ["89504E47", "FFD8FFE0", "47494638"])) {
                    echo "<script>black();</script>";
                } else {
                    $name = basename($_FILES['file']['name']);
                    if (move_uploaded_file($_FILES['file']['tmp_name'], UPLOAD_PATH . $name)) {
                        $is_upload = true;
                    } else {
                        echo "<script>error();</script>";
                    }
                }
            }
        }
    ?>

源码中对上传文件的类型和文件头都进行了检测

if (!in_array($_FILES['file']['type'], ["image/jpeg", "image/jpg", "image/png", "image/gif"]))
if (!in_array(bin2hex($bin), ["89504E47", "FFD8FFE0", "47494638"]))

那么将我们上传的文件头添加符合上传规则文件头并且修改数据包中的content-type类型即可成功上传
在这里插入图片描述
在这里插入图片描述

黑名单验证

在这里插入图片描述
题目中源码采用了黑名单验证的方式,将黑名单中的后缀进行替换为空,但是并没有进行循环验证处理,因此可以采用多重后缀名嵌套进行上传。
在这里插入图片描述

文件后缀大小写敏感

在这里插入图片描述
在linux系统中文件名大小写敏感,题目中源码只对小写后缀名进行过滤,可以采用大写文件名后缀进行上传。

在这里插入图片描述

零零截断(GET)

在这里插入图片描述
零零截断即在系统进行文件接受时,会错误得把%00当作结束符进行接受保存,从而不对%00后面的字符进行保存。%00使url进行解码后的结果其实是为空字节。

 <?php
        header("Content-type: text/html;charset=utf-8");
        error_reporting(0);
        //设置上传目录
        define("UPLOAD_PATH", dirname(__FILE__) . "/upload/");
        define("UPLOAD_URL_PATH", str_replace($_SERVER['DOCUMENT_ROOT'], "", UPLOAD_PATH));
        if (!file_exists(UPLOAD_PATH)) {
            mkdir(UPLOAD_PATH, 0755);
        }
        $is_upload = false;
        if (!empty($_POST['submit'])) {
            $name = basename($_FILES['file']['name']);
            $info = pathinfo($name);
            $ext = $info['extension'];
            $whitelist = array("jpg", "jpeg", "png", "gif");
            if (in_array($ext, $whitelist)) {
                
                $filename = rand(10, 99) . date("YmdHis") . "." . $ext;
                $des = $_GET['road'] . "/" . $filename;

                if (move_uploaded_file($_FILES['file']['tmp_name'], $des)) {
                    $is_upload = true;
                } else {
                    echo "<script>black();</script>";
                }
            } else {
                echo "文件类型不匹配";
            }
        }
    ?>

在文件进行保存的时候,文件路径与文件名相连接,路径中带有%00,于是将文件保存为2.php
在这里插入图片描述
关于php版本是否符合,在网站的返回数据包中可以查看
在这里插入图片描述

零零截断(POST)

在这里插入图片描述
POST型在进行零零截断的时候需要将文件路径写在传送数据的位置,由于GET型在写入%00时,系统会自动将地址栏的%00进行解码,但是POST不会,因此在进行上传过程中需要将%00进行解码发送。
在这里插入图片描述

配置绕过

在网站管理员进行网站配置过程中没有严格进行配置网站,导致php3,php5等文件后缀名文件也进行php解析。
在这里插入图片描述

<?php
        header("Content-type: text/html;charset=utf-8");
        error_reporting(0);
        //设置上传目录
        define("UPLOAD_PATH", dirname(__FILE__) . "/upload/");
        define("UPLOAD_URL_PATH", str_replace($_SERVER['DOCUMENT_ROOT'], "", UPLOAD_PATH));
        if (!file_exists(UPLOAD_PATH)) {
            mkdir(UPLOAD_PATH, 0755);
        }
        $is_upload = false;
        if (!empty($_POST['submit'])) {
            $name = basename($_FILES['file']['name']);
            $ext = pathinfo($name)['extension'];
            $blacklist = array("asp","aspx","php","jsp","htaccess");
            
            if (!in_array($ext, $blacklist)) {
                if (move_uploaded_file($_FILES['file']['tmp_name'], UPLOAD_PATH . $name)) {
                    $is_upload = true;
                } else {
                    echo "<script>error();</script>";
                }
            } else {
                    echo "<script>black();</script>";
            }
        }
    ?>

源码中采取了白名单验证后缀名,如何后缀名为php,asp等将不能通过验证
在这里插入图片描述

条件竞争

条件竞争是利用一种错误的逻辑进行的文件上传,所以可以将上传的文件中写入访问即创建的代码,再对该文件进行不断上传,同时不断访问该文件,只要访问到了该文件,便会创建一个后门文件出来。

在这里插入图片描述

 <?php
        header("Content-type: text/html;charset=utf-8");
        error_reporting(0);
        //设置上传目录
        define("UPLOAD_PATH", dirname(__FILE__) . "/upload/");
        define("UPLOAD_URL_PATH", str_replace($_SERVER['DOCUMENT_ROOT'], "", UPLOAD_PATH));
        if (!file_exists(UPLOAD_PATH)) {
            mkdir(UPLOAD_PATH, 0755);
        }
        $is_upload = false;
        if (!empty($_POST['submit'])) {
            $name = basename($_FILES['file']['name']);
            $ext = pathinfo($name)['extension'];
            $upload_file = UPLOAD_PATH . '/' . $name;
            $whitelist = array('jpg','png','gif','jpeg');
            
            if (move_uploaded_file($_FILES['file']['tmp_name'], UPLOAD_PATH . $name)) {
                if(in_array($ext,$whitelist)){
                    $rename_file = rand(10, 99).date("YmdHis").".".$ext;
                    $img_path = UPLOAD_PATH . '/'. $rename_file;
                    rename($upload_file, $img_path);
                    $is_upload = true;
                }else{
                    echo "<script>black();</script>";
                    unlink($upload_file);
                }
            } 
        }
    ?>

源码中先将文件进行存储,再进行判断文件是否合法。
首先抓取上传文件的数据包
在这里插入图片描述
发送至intruder模块进行空值爆破,无限制得上传该文件
在这里插入图片描述
再抓取访问该文件得数据包,依旧进行空值爆破
在这里插入图片描述
当访问数据包出现不同长度的返回包时,大概率时已经成功创建了,连接后门验证结果即可
在这里插入图片描述
连接成功
在这里插入图片描述

二次渲染

在进行文件上传过程中,很多网站会对上传后的图片进行二次渲染以适应web显示界面等。
在这里插入图片描述
在对绕过二次渲染的图片马中,gif文件最为简单
在这里插入图片描述
先将图片进行上传,然后将上传过后的图片进行下载,与源文件进行对比,在没有修改的部分插入代码即可。
在这里插入图片描述
经过对比灰色部分就是没有发生变化的部分,在灰色部分插入代码即可
在这里插入图片描述
重新上传,再次下载查看payload是否存在
在这里插入图片描述

使用网站本身的包含漏洞进行验证
在这里插入图片描述

move_uploaded_file缺陷

在这里插入图片描述
在保存文件名后面加上/.便可以上传成功

代码审计

不会!

文件解析方案

  1. 执行权限(有可能绕过)
    文件上传后,存储文件的文件夹无执行权限

  2. 解码还原(不能绕过)
    文件在上传过程中,源码通过函数将文件中的数据提取出来并进行编码,存储入数据库中。在使用文件时,调用数据编码进行解码还原。

文件存储方案

  1. 分站存储(不能绕过)
    网站与存储上传文件属于不同站点、不同服务器,在网站服务器进行上传,传输至存储文件服务器,一般会设置执行权限。
  2. 对象存储(不能绕过)
    OSS对象云存储,只能存储文件,并不能执行。具有key泄露的风险。

以上内容仅作学习,如有错误或瑕疵,欢迎批评指正,感谢阅读。

与Web通用漏洞--文件上传相似的内容:

Web通用漏洞--文件上传

# Web通用漏洞--文件上传 ## 概述 文件上传安全指的是攻击者通过利用上传实现后门的写入连接后门进行权限控制的安全问题,对于如何确保这类安全问题,一般会从原生态功能中的文件内容,文件后缀,文件类型等方面判断,但是漏洞可能不仅在本身的代码验证逻辑中出现安全问题,也会在语言版本,语言函数,中间件,

Web攻防--xxe实体注入

# web攻防--xxe实体注入 ## 漏洞简介 XML 外部实体注入(也称为 XXE)是一种 Web 安全漏洞,允许攻击者干扰应用程序对 XML 数据的处理。它通常允许攻击者查看应用程序服务器文件系统上的文件,并与应用程序本身可以访问的任何后端或外部系统进行交互。 在某些情况下,攻击者可以利用 X

Web通用漏洞--文件包含

# Web通用漏洞--文件包含 ## 文件包含原理 在项目开发过程中,开发人员通常会将重复使用的函数写入单个文件中,在使用该类函数时,直接调用文件即可,无需重新编写,这种调用文件的过程成为文件包含。在文件包含过程中,如果用户可以控制所包含的文件,则为文件包含漏洞。 ## 文件包含函数 PHP:inc

Web通用漏洞--XSS

# Web通用漏洞--XSS ## XSS原理 XSS称为跨站脚本攻击,这种漏洞利用通常是被动性攻击,即需要受害者做出某些行为来配合攻击行为,才能达到攻击效果 XSS的原理是恶意攻击者往 Web 页面里插入恶意可执行网页脚本代码,当用户浏览该页之时,嵌入其中 Web 里面的脚本代码会被执行,从而可以

Web通用漏洞--CSRF

# Web通用漏洞--CSRF ## 漏洞简介 CSRF(Cross Site Request Forgery, 跨站请求伪造/客户端请求伪造),即通过伪造访问数据包并制作成网页的形式,使受害者访问伪造网页,同时触发伪造的请求而达到攻击效果的一种手段。 ![在这里插入图片描述](https://im

Web通用漏洞--SSRF

# Web通用漏洞--SSRF ## 漏洞简介 SSRF(Server-Side Request Forgery:服务器端请求伪造) 一种由攻击者构造形成由服务端发起请求的一个安全漏洞; 一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。正是因为它是由服务端发起的,所以它能够请求到与它相连而

Web通用漏洞--RCE

# Web通用漏洞--RCE ## 漏洞简介 RCE远程代码/命令执行漏洞,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统。 RCE漏洞也分为代码执行漏洞和命令执行漏洞,所谓代码执行即通过漏洞点注入参数而使用源代码进行相应的操作,所谓的命令执行就是通过漏洞点注入参数使用源

Web通用漏洞--sql注入

# SQL注入 mysql注入目的:获取当前web权限 ## mysql注入--常规查询&union联合查询 1. MYSQL--Web组成架构 服务器搭建web服务可能存在多个站点搭建在一台服务器中,数据集中存储在数据库中,因此对数据库的管理也可以分为两种架构: 统一用户管理数据库,即对所有站点数

Web攻防--JNDI注入--Log4j漏洞--Fastjson反序列化漏洞

JNDI注入 什么是JNDI JNDI全称为 Java Naming and Directory Interface(Java命名和目录接口),是一组应用程序接口,为开发人员查找和访问各种资源提供了统一的通用接口,可以用来定义用户、网络、机器、对象和服务等各种资源。 JNDI支持的服务主要有:DNS

详解Web应用安全系列(1)注入漏洞之SQL注入

注入漏洞通常是指在可输入参数的地方,通过构造恶意代码,进而威胁应用安全和数据库安全。常见的注入漏洞包括:SQL注入和XSS跨站脚本攻击。 这篇文章我们主要讲SQL注入,SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加