Web通用漏洞--文件上传

概述

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

靶场upload-labs-docker

js验证

采用前端代码进行文件后缀验证



绕过方法

  1. 删除前端代码

    通过查看前端代码,发现上传form表单有个javascirpt事件,即检测文件后缀白名单,删除即可

  2. 在浏览器禁用javascript
  3. 将文件后缀修改为允许上传的后缀,通过前端校验后抓包修改文件后缀

修改解析规则



上传.htaccess文件添加配置解析规则,将png文件后缀进行php解析

  1. AddType application/x-httpd-php .png

上传写有php代码的png文件,访问

文件类型绕过



源码

  1. <?php
  2. header("Content-type: text/html;charset=utf-8");
  3. error_reporting(0);
  4. //设置上传目录
  5. define("UPLOAD_PATH", dirname(__FILE__) . "/upload/");
  6. define("UPLOAD_URL_PATH", str_replace($_SERVER['DOCUMENT_ROOT'], "", UPLOAD_PATH));
  7. if (!file_exists(UPLOAD_PATH)) {
  8. mkdir(UPLOAD_PATH, 0755);
  9. }
  10. $is_upload = false;
  11. if (!empty($_POST['submit'])) {
  12. if (!in_array($_FILES['file']['type'], ["image/jpeg", "image/png", "image/gif", "image/jpg"])) {
  13. echo "<script>black();</script>";
  14. } else {
  15. $name = basename($_FILES['file']['name']);
  16. if (move_uploaded_file($_FILES['file']['tmp_name'], UPLOAD_PATH . $name)) {
  17. $is_upload = true;
  18. } else {
  19. echo "<script>alert('上传失败')</script>";
  20. }
  21. }
  22. }
  23. ?>

代码中通过查看type白名单进行过滤

通过抓包将数据包中的content-type进行修改即可上传成功

文件头检测



源码

  1. <?php
  2. header("Content-type: text/html;charset=utf-8");
  3. error_reporting(0);
  4. //设置上传目录
  5. define("UPLOAD_PATH", dirname(__FILE__) . "/upload/");
  6. define("UPLOAD_URL_PATH", str_replace($_SERVER['DOCUMENT_ROOT'], "", UPLOAD_PATH));
  7. if (!file_exists(UPLOAD_PATH)) {
  8. mkdir(UPLOAD_PATH, 0755);
  9. }
  10. $is_upload = false;
  11. if (!empty($_POST['submit'])) {
  12. if (!$_FILES['file']['size']) {
  13. echo "<script>error();</script>";
  14. } else {
  15. $file = fopen($_FILES['file']['tmp_name'], "rb");
  16. $bin = fread($file, 4);
  17. fclose($file);
  18. if (!in_array($_FILES['file']['type'], ["image/jpeg", "image/jpg", "image/png", "image/gif"])) {
  19. echo "<script>black();</script>";
  20. } else if (!in_array(bin2hex($bin), ["89504E47", "FFD8FFE0", "47494638"])) {
  21. echo "<script>black();</script>";
  22. } else {
  23. $name = basename($_FILES['file']['name']);
  24. if (move_uploaded_file($_FILES['file']['tmp_name'], UPLOAD_PATH . $name)) {
  25. $is_upload = true;
  26. } else {
  27. echo "<script>error();</script>";
  28. }
  29. }
  30. }
  31. }
  32. ?>

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

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

那么将我们上传的文件头添加符合上传规则文件头并且修改数据包中的content-type类型即可成功上传



黑名单验证



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

文件后缀大小写敏感



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

零零截断(GET)



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

  1. <?php
  2. header("Content-type: text/html;charset=utf-8");
  3. error_reporting(0);
  4. //设置上传目录
  5. define("UPLOAD_PATH", dirname(__FILE__) . "/upload/");
  6. define("UPLOAD_URL_PATH", str_replace($_SERVER['DOCUMENT_ROOT'], "", UPLOAD_PATH));
  7. if (!file_exists(UPLOAD_PATH)) {
  8. mkdir(UPLOAD_PATH, 0755);
  9. }
  10. $is_upload = false;
  11. if (!empty($_POST['submit'])) {
  12. $name = basename($_FILES['file']['name']);
  13. $info = pathinfo($name);
  14. $ext = $info['extension'];
  15. $whitelist = array("jpg", "jpeg", "png", "gif");
  16. if (in_array($ext, $whitelist)) {
  17. $filename = rand(10, 99) . date("YmdHis") . "." . $ext;
  18. $des = $_GET['road'] . "/" . $filename;
  19. if (move_uploaded_file($_FILES['file']['tmp_name'], $des)) {
  20. $is_upload = true;
  21. } else {
  22. echo "<script>black();</script>";
  23. }
  24. } else {
  25. echo "文件类型不匹配";
  26. }
  27. }
  28. ?>

在文件进行保存的时候,文件路径与文件名相连接,路径中带有%00,于是将文件保存为2.php



关于php版本是否符合,在网站的返回数据包中可以查看

零零截断(POST)



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

配置绕过

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

  1. <?php
  2. header("Content-type: text/html;charset=utf-8");
  3. error_reporting(0);
  4. //设置上传目录
  5. define("UPLOAD_PATH", dirname(__FILE__) . "/upload/");
  6. define("UPLOAD_URL_PATH", str_replace($_SERVER['DOCUMENT_ROOT'], "", UPLOAD_PATH));
  7. if (!file_exists(UPLOAD_PATH)) {
  8. mkdir(UPLOAD_PATH, 0755);
  9. }
  10. $is_upload = false;
  11. if (!empty($_POST['submit'])) {
  12. $name = basename($_FILES['file']['name']);
  13. $ext = pathinfo($name)['extension'];
  14. $blacklist = array("asp","aspx","php","jsp","htaccess");
  15. if (!in_array($ext, $blacklist)) {
  16. if (move_uploaded_file($_FILES['file']['tmp_name'], UPLOAD_PATH . $name)) {
  17. $is_upload = true;
  18. } else {
  19. echo "<script>error();</script>";
  20. }
  21. } else {
  22. echo "<script>black();</script>";
  23. }
  24. }
  25. ?>

源码中采取了白名单验证后缀名,如何后缀名为php,asp等将不能通过验证

条件竞争

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

  1. <?php
  2. header("Content-type: text/html;charset=utf-8");
  3. error_reporting(0);
  4. //设置上传目录
  5. define("UPLOAD_PATH", dirname(__FILE__) . "/upload/");
  6. define("UPLOAD_URL_PATH", str_replace($_SERVER['DOCUMENT_ROOT'], "", UPLOAD_PATH));
  7. if (!file_exists(UPLOAD_PATH)) {
  8. mkdir(UPLOAD_PATH, 0755);
  9. }
  10. $is_upload = false;
  11. if (!empty($_POST['submit'])) {
  12. $name = basename($_FILES['file']['name']);
  13. $ext = pathinfo($name)['extension'];
  14. $upload_file = UPLOAD_PATH . '/' . $name;
  15. $whitelist = array('jpg','png','gif','jpeg');
  16. if (move_uploaded_file($_FILES['file']['tmp_name'], UPLOAD_PATH . $name)) {
  17. if(in_array($ext,$whitelist)){
  18. $rename_file = rand(10, 99).date("YmdHis").".".$ext;
  19. $img_path = UPLOAD_PATH . '/'. $rename_file;
  20. rename($upload_file, $img_path);
  21. $is_upload = true;
  22. }else{
  23. echo "<script>black();</script>";
  24. unlink($upload_file);
  25. }
  26. }
  27. }
  28. ?>

源码中先将文件进行存储,再进行判断文件是否合法。

首先抓取上传文件的数据包



发送至intruder模块进行空值爆破,无限制得上传该文件



再抓取访问该文件得数据包,依旧进行空值爆破



当访问数据包出现不同长度的返回包时,大概率时已经成功创建了,连接后门验证结果即可



连接成功

二次渲染

在进行文件上传过程中,很多网站会对上传后的图片进行二次渲染以适应web显示界面等。



在对绕过二次渲染的图片马中,gif文件最为简单



先将图片进行上传,然后将上传过后的图片进行下载,与源文件进行对比,在没有修改的部分插入代码即可。



经过对比灰色部分就是没有发生变化的部分,在灰色部分插入代码即可



重新上传,再次下载查看payload是否存在

使用网站本身的包含漏洞进行验证

move_uploaded_file缺陷



在保存文件名后面加上/.便可以上传成功

代码审计

不会!

文件解析方案

  1. 执行权限(有可能绕过)

    文件上传后,存储文件的文件夹无执行权限

  2. 解码还原(不能绕过)

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

文件存储方案

  1. 分站存储(不能绕过)

    网站与存储上传文件属于不同站点、不同服务器,在网站服务器进行上传,传输至存储文件服务器,一般会设置执行权限。
  2. 对象存储(不能绕过)

    OSS对象云存储,只能存储文件,并不能执行。具有key泄露的风险。

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

Web通用漏洞--文件上传的更多相关文章

  1. 基于 java 【Web安全】文件上传漏洞及目录遍历攻击

    前言:web安全之文件上传漏洞,顺带讲一下目录遍历攻击.本文基于 java 写了一个示例. 原理 在上网的过程中,我们经常会将一些如图片.压缩包之类的文件上传到远端服务器进行保存.文件上传攻击指的是恶 ...

  2. JAVA Web 之 struts2文件上传下载演示(二)(转)

    JAVA Web 之 struts2文件上传下载演示(二) 一.文件上传演示 详细查看本人的另一篇博客 http://titanseason.iteye.com/blog/1489397 二.文件下载 ...

  3. JAVA Web 之 struts2文件上传下载演示(一)(转)

    JAVA Web 之 struts2文件上传下载演示(一) 一.文件上传演示 1.需要的jar包 大多数的jar包都是struts里面的,大家把jar包直接复制到WebContent/WEB-INF/ ...

  4. WEB安全:文件上传漏洞

    文件上传漏洞过程 用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力. 一般的情况有: 上传文件WEB脚本语言,服务器的WEB容器解释并执行了用户上传的脚本,导致代码执行: ...

  5. web安全之文件上传漏洞攻击与防范方法

    一. 文件上传漏洞与WebShell的关系 文件上传漏洞是指网络攻击者上传了一个可执行的文件到服务器并执行.这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等.这种攻击方式是最为直接和有效 ...

  6. Web安全-之文件上传漏洞场景

    1   上传漏洞危害介绍 上传是Web中最常见的功能,如果上传功能存在设计.编码缺陷,就容易形成上传漏洞,从而成为致命的安全问题,攻击者可以通过上传脚本木马,实现查看/篡改/删除源码和任意涂鸦网页,可 ...

  7. WEB安全性测试之文件上传漏洞

    1.漏洞描述:文件上传漏洞,是指可以利用WEB上传一些特定的文件包含特定代码如(<?php phpnfo;?> 可以用于读取服务器配置信息.上传成功后可以点击) 上传漏洞是指用户上传了一个 ...

  8. web安全之文件上传漏洞

    成因: 当文件上传时,若服务端脚本语言未对上传的文件进行严格验证和过滤,若恶意用户上传恶意的 脚本文件时,就有可能控制整个网站甚至是服务器,这就是文件上传漏洞. 权限: 1. 后台权限:登陆了后台,可 ...

  9. WEB漏洞——文件上传

    有关文件上传的知识 为什么文件上传存在漏洞 上传文件时,如果服务端代码未对客户端上传的文件进行严格的验证和过滤就容易造成可以上传任意文件的情況,包括上传脚本文件(asp.aspx.php.jsp等格式 ...

  10. 24:WEB漏洞-文件上传之WAF绕过及安全修复

    本课重点 案例1:上传数据包参数对应修改测试 案例2:safedog+云服务器+uploadlabs测试 案例3:safedog+云服务器+uploadlabs_fuzz测试 案例4:文件上传安全修复 ...

随机推荐

  1. 2022-08-05:以下go语言代码输出什么?A:65, string;B:A, string;C:65, int;D:报错。

    2022-08-05:以下go语言代码输出什么?A:65, string:B:A, string:C:65, int:D:报错. package main import ( "fmt&quo ...

  2. 2022-05-30:给定一个n*2的二维数组,表示有n个任务。 一个信息是任务能够开始做的时间,另一个信息是任务的结束期限,后者一定大于前者,且数值上都是正数, 你作为单线程的人,不能并行处理任务,

    2022-05-30:给定一个n*2的二维数组,表示有n个任务. 一个信息是任务能够开始做的时间,另一个信息是任务的结束期限,后者一定大于前者,且数值上都是正数, 你作为单线程的人,不能并行处理任务, ...

  3. 2021-10-30:有效的字母异位词。给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位

    2021-10-30:有效的字母异位词.给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词.注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位 ...

  4. 百度飞桨(PaddlePaddle) - PaddleOCR 文字识别简单使用

    百度飞桨(PaddlePaddle)安装 OCR 文字检测(Differentiable Binarization --- DB) OCR的技术路线 PaddleHub 预训练模型的网络结构是 DB ...

  5. vue全家桶进阶之路41:Vue3 语法糖<script setup>

    <script setup> 是 Vue 3 中的一种语法糖,它可以使组件的脚本更加简洁.易读,并且减少了一些样板代码.使用 <script setup>,你可以将组件的 pr ...

  6. SQL Server2019 新增字段并设置默认值

    命令: ALTER TABLE 表名 add 列名 数据类型 default 默认值 not null 例如: ALTER TABLE LJEL005H add el_req int default ...

  7. MongoDB + SpringBoot 的基础CRUD、聚合查询

    1.数据准备 1.1.springboot导包 springboot版本:2.7.10 点击查看代码 <!--mongodb的包--> <dependency> <gro ...

  8. 在程序里如何停止整个python项目的运行

    我们的项目无可避免的会遇到一些场景,当出现某个故障或者异常,必须停止整个项目的运行,这时只需要在抛出的异常里执行以下即可: os._exit(0)

  9. git push origin master 提示输入用户名和密码

    今天更换了一台电脑,重新配置了SSH keys:但是在push得时候提示我输入用户名和密码 taodeMacBook-Pro:my_trip_proj tao$ git push origin mas ...

  10. Linux 服务器更换主板后,网卡识别失败的处理方法

    上周日,由于断电,公司所在的集群服务器在关机断电重启后,发现唯一的一个登陆节点主板出现了故障,以致于 log 登陆节点的 Red Hat Enterprise 6 系统无法启动. 由于集群是生信所有分 ...