文件上传这个功能点是现在大部分 UGC 站点必备的功能啦,像是头像、文章编辑、评论区等模块都标配。在编码时不考虑上传文件的内容和文件类型就有可能被上传 WebShell。

最常见的利用方法是对正常上传点,传递脚本直接获取 Web 服务控制权限,或者上传一个 HTML 页面将链接发给用户进行钓鱼;用户一看 URL 是官方就有可能放松警惕。

文件上传分为 WebServer 解析、应用检验不严格这两种类型。

上传功能原理分析(待补充)常见的上传方式:

  1. from 表单 multipart/form-data。
  2. 编码,如 data url base64 编码图片。

使用 Java 写个上传功能。

目录

1 WebServer 解析问题

就算代码写的没问题,Web 服务器存在问题会把其他文件当做其他正常脚本解析。

1.1 Apache 1.x / 2.x 解析漏洞(待补充)

Apache 处理 shell.php.jss.zd 从右到做依次判断后缀名能不能解析,不能往前走,直到能解析就停下来,此时得到处理的文件是 shell.php

Apache 加载的 PHP 模块配置文件正则匹配默认解析 pht、phtml、php3、php4、php5。

1.2 IIS 5.x / 6.0 / 7.5 解析漏洞(待补充)

IIS 调用 asp.dll 解析文件名时出现问题。

  1. Web 服务器上存在 .asp.asa.cer 结尾的目录,其目录下所有文件被访问时都会被当做脚本执行。
  2. 上传一个 xx.asp;.jpgxx.asa;.jpgxx.cer;.jpg 的图片,访问时这个图片会被当做脚本执行。

1.3 Nginx(待补充)

2 常见绕过

2.1 后缀校验

1.没有判断后缀

截取字符串没有以最后一个点开始,而是只是判断文件后缀中是否包含正确后坠姆,导致多后缀也可以绕过限制。

2.大小写

没有将文件后缀统一转换为小写校验。

Windows 下更改文件它会忽略大小写,最终指向同一个文件,这个特性在切换目录也可以提现出来,Linux 则当成两个不同的文件,它对大小写是区分的。

系统特性差异.png

3.文件后缀加空格。加了空格就不再是同一个黑名单字符串。

4.遇到黑名单中的后缀直接剔除,后面代码检查没有后缀无法上传。那么可以嵌套 1.asaspxpx,最终得到 1.aspx,此操作有人称双写绕过。

5.遇到仅仅检查黑名单后缀无法上传,aspx 可以尝试上传 aspx、ashx、ascx、asmx。asp 尝试 asp、cer、asa。php 尝试上传 php、php2、php3、php4、php5、pht、phtm、phtml。jsp 尝试 jspx。

NTFS 文件流

这种绕过方式适用于黑名单。

每个文件都对应着一个文件流,即 Default,而每个文件可以有多个文件流。

创建文件流的格式:源文件:文件流名:文件流数据格式

很多人在上传时这样写:shell.ext::$DATA

如果服务器没有这个文件名,就会自动创建一个,有就把原文件内容重写。

为啥重写?像我们编辑一个文件时显示的内容都是默认文件流中的,Payload 中把文件流名留空不写就相当于对默认文件流写入数据。

NTFS默认文件流

我们重新创建一个文件流就依附在源文件上,可以用 dir /R 查看。

NTFS附加文件流

  1. 上传漏洞可以多加个完整的 filename 参数,有些程序可能取第二个文件名的值,WAF 也可能只匹配第一个参数值。

Apache htaccess 配置(待补充)

htaccess 可以针对指定目录进行配置,颗粒度会更细,放置该文件的目录其子目录和文件都会受到影响。

下面的配置是将 .configz 的文件交给 PHP 解析。

AddType application/x-httpd-php .configz

这个配置是将 shell.* 这个文件交给 PHP 解析。

<FilesMatch "shell">
    SetHandler application/x-httpd-php
</FilesMatch>

操作步骤:

  1. 上传 .htaccess 文件,内容是配置某个后缀文件能够交给语言解析。
  2. 上传指定后缀文件

需要给出详细测试 .htaccess 解析其他后缀的图例,如,设置 .htaccess 解析 jpg 为 php。

配合文件包含 GetShell

File Inclusion

验证文件内容和后缀,那我们直接上传正常图片,如果服务器存在文件包含漏洞那么可以在图片文件头后面中添加一句话,让代码把中的内容当做代码执行。

文件类型与文件头绕过

文件类型更改请求 Content-type 即可。

文件头是不变的,有些代码仅检测文件头,可以把对应文件头后面加上一句话来上传。既限制了后缀有检查了文件头那么可以上传一个正常图片配合解析漏洞/文件包含拿 Shell。

下面是 16 进制的文件头(使用 UltraEdit 查看)。

常见文件头格式

Zip Slip(待补充)

应用在解压缩文件时获取了压缩包内文件名,由于文件名存在 ../ 目特殊字符,在写入文件时使用包内的文件名会自动穿越路径。

或者是有些应用设置白名单只允许上传压缩包、或者图片文件,但存在解压接口,可以直接解压缩指定文件。而且解压缩又没限制格式,给文件就行。

https://github.com/snyk/zip-slip-vulnerability

文件上传后自解压漏洞

解压上传的压缩文件,文件名存在 ../ 导致解压后切换目录。

或者利用一个正常解压接口去解压压缩包。

SSI 执行命令(待补充)

上传 .shtml。

开启 SSI 并利用执行系统命令。

条件竞争(待补充)

有一种场景是检测到文件后缀是不允许上传的,程序会将其删除。

此时可以一边上传同时进行快速请求此文件,一旦被访问占用掉无法删除,直接成功保留住文件。

字符串截断

上传 shell.php.jpg,通过在 .jpg 开头放置一个结尾符,最后代码遇到就会直接停止在 shell.php,对这个文件名进行操作就成功截断为 php 文件了。

通过结尾符表示文件结束,%00 是 URL 编码后的结尾符。

%00 截断需要 PHP Version 小于 5.3.7。

Burp 抓包修改文件名处输入的标记字符,转换到十六进制中将标记字符改为 00,或者 1.php%00/1.jpg,选中 %00 Ctrl + Shift + U。

二次渲染绕过(待补充)

  1. 上传符合长宽比的图片(如 1x1大小的图片),避免被图片缩小,导致内容改变。
  2. 常见库绕过,如 PHP 图片处理 GD 库。

靶场练习

upload-labs

GitHub - c0ny1/upload-labs: 一个想帮你总结所有类型的上传漏洞的靶场

前端 JS 验证

在浏览器关掉 JS。

CheckFile.png

closeJS.JPG

这种方法比较好用,还有个地方可以让它不执行 JS 脚本,它是提交表单是调用这个方法我们可以双击把这双引号内内容删掉,就不会触发检测了。

elements.png

也可以在本地写一个 HTML 表单进行提交。

文件 MIME 验证

他的验证方式是检测 Content-Type 的MIME是否为图片类型 ,只有匹配上了才放你通过。

MimeSourceCode.png

我们将原来的 mime Content-Type: application/octet-stream 改为图片的 MIME 就可以绕过了。

MIME

文件后缀验证

它这里黑名单验证,会把名字转换为小写并重新用 时间+随机值 命名,文件后缀无法加空格绕过。

ExtendFormat.JPG

Web Security Academy

实战利用

获取权限

上传 WebShell。直接写 Shell,可以通过 ../ 目录遍历,进行切换目录。

Java 写文件 new File(path, filename),文件名为空,path 直接绝对路径 /path/index.jsp 可以写直接把文件写入,而不是建立成目录。

如果 WebServer 权限够,可以切目录上传到 Linux 任务计划目录 GetShell。

上传文件写公钥到用户目录,SSH 直接连。

XSS

.html.svg.xml 打 XSS。

.svg

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
   <polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
   <script type="text/javascript">
      alert(document.domain);
   </script>
</svg>
<svg><desc><![CDATA[</desc><script>alert(1)</script>]]></svg>

.xml

<html>
    <head></head>
    <body>
        <something:script src="http://localhost/1.js"
            xmlns:something="http://www.w3.org/1999/xhtml">
        </something:script>
    </body>
</html>
<html>
    <head></head>
    <body>
        <something:script xmlns:something="http://www.w3.org/1999/xhtml">alert(1)</something:script>
        <a:script xmlns:a="http://www.w3.org/1999/xhtml">alert(2)</a:script>
        <info>
          <name>
            <value><![CDATA[<script>confirm(document.domain)</script>]]></value>
          </name>
            <description>
              <value>Hello</value>
            </description>
            <url>
              <value>http://google.com</value>
            </url>
        </info>
    </body>
</html>

SSTI

传模板文件尝试 SSTI。

XXE

利用技巧 2,文件上传 xlsx 文件

业务场景:有时应用会解析 excel 内文件数据作为内容进行数据处理最终展示内容。

利用方法:

  1. 创建 xx.xlsx 文件
  2. 将 xx.xlsx 后缀改为压缩包格式,这里使用 zip
  3. 将压缩包内 [Content_Types].xml 文件添加 XXE Payload
    xlsx xxe.png
  4. 解压的文件打包回来。
  5. 上传文件,查看是否收到 XXE Request 或者文件内容。

利用技巧 2,文件上传 svg 文件

<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/passwd" > ]>
<svg width="500px" height="500px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1
<text font-size="40" x="0" y="16">&xxe;</text>
</svg>

覆盖原有文件

DOS

https://github.com/barrracud4/image-upload-exploits

应用不限制上传文件的大小,可以上传超大文件,导致应用瘫痪。

防御

  1. 代码采用白名单校验扩展名。
  2. 对前端传来的图片采用伪随机数命名(时间戳加上伪随机数),不返回上传后的路径,增加找 Shell 难度;要是头像这种在模板上调用图片,这种情况也没办法。
  3. 对图片二次处理(其他语言也有对应图片处理库),就算你上传脚本,渲染后图片中代码会被破坏掉无法正常解析。
  4. 限制上传文件大小,以避免服务器资源耗尽(最低成本 DDOS)。
  5. 取消上传目录执行权限(未测试),IIS 可以用 Web.config 配置,其他 Web 容器需要搜索下资料。
  6. 可以将放置图片单独放在一台服务器或云存储,脚本在图片服务器上没有执行环境不能被解析。
  7. 使用新版本 WebServer 做好安全配置;避免 Web 服务器低版本漏洞和不安全配置问题。

问题

后续需要把这些问题融合到文章中。

问:其他 WebServer 可以支持 htaccess 吗?还是说只有 Apache 能够使用。
答:

问:在实战中会遇到各种奇怪的情景,这里提供一个实际场景,有一个上传点只能 Upload DLL 文件,代码直接读取文件名来决定文件存储位置,这时候你如何利用?
答:CGI-BIN 目录能不能上传。其他没法子。

问:任意文件上传 PDF XSS 如何利用?
答:

问:现在应用有些用 SpringBoot 写完打包程 jar 包运行,现在只能上传 .jar 咋利用?
答:没法子。

问:文件上传测试步骤?
答:

  1. 文件上传功能正常。
    • 上传到 OSS
    • 自建服务器
  2. 能够上传脚本后缀文件。
  3. 能够找到文件路径并成功访问被解析。
    • 上传后返回文件 ID
    • 上传路径是动态的

问:找不到路径怎么办?
答:

  1. SQL 注入获取站点路径,路径下对应文件。
  2. 任意文件读取,获取源码分析怎么保存文件。
  3. 更改上传参数抛异常显示路径。基本不可能遇到。
  4. 通过 JS 有没可能写入目录拼接。
  5. 当前上传功能不显示,可以看看其他静态文件是否与上传文件目录一致。
  6. 扫目录

问:脚本不解析怎么办?
答:

  1. 上传 shtml 尝试执行 SSI。
  2. 上传 html
  3. 上传 .htaccess。上传后要被重命名基本凉凉,而且 WebServer 必须是 Apache。
  4. 更改目录或文件名参数,上传到其他目录。
  5. 上传文件后缀大小写更改,或者尝试其他后缀,因为有些 WebServer 能解析其他文件后缀。
  6. 宝塔配置漏洞,所有 php 命名的文件被解析。

问:什么是图片马
答:将代码放在图片尾部不会破坏图片展示,文件后缀还是脚本格式,这就是图片马,可以用作检测文件内容绕过。

问:遇到 LBS(负载均衡) 如何解决?
答:

  1. 多次上传,确保每台服务器上都有 WebShell
  2. 使用脚本流量转发到指定服务器。https://mp.weixin.qq.com/s/4Bmz_fuu0yrLMK1oBKKtRA
  3. 服务器如果在公网的情况下直接访问 IP(不过负载通常都是内网 IP)
  4. 看看上传请求中有没标识可以选择后端应用,比如根据 Cookie 字段来决定使用那台服务器。
  5. 看看研发怎么解决这个问题,就能找到思路,搜索 “负载均衡 文件上传”。

参考链接

最近更新:

发布时间:

摆哈儿龙门阵