文件上传漏洞

文件上传漏洞及其危害

文件上传漏洞是指网络攻击者上传了一个可执行的文件到服务器并执行。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。

由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致用户可以越过其本身权限向服务器上传可执行的动态脚本文件。

打个比方来说,如果你使用 windows 服务器并且以 asp 作为服务器端的动态网站环境,那么在你的网站的上传功能处,就一定不能让用户上传 asp 类型的文件,否则他上传一个 webshell,你服务器上的文件就可以被他任意更改了。因此文件上传漏洞带来的危害常常是毁灭性的,Apache、Tomcat、Nginx等都曝出过文件上传漏洞。

比如,我们向后台传输了一个php文件,该文件的内容很简单,就一行代码,通过eval函数执行请求参数中hacker字段的值。

如果我们将这个文件上传到服务器,并假设存储到了 http://localhost/images/shell.php

那么这个时候我们去利用命令行执行

1
curl -d "hacker=echo get_current_user();" http://localhost/images/shell.php

这个时候就会回显会服务器当前的用户。

当然我们也可以利用其它php自带的系统函数去推测出整个后台服务器的信息。

文件上传漏洞初阶:后缀域名绕过

后缀名检测

我们开头所讲的这个例子之所以能够执行成功,很重要的一部分原因是因为文件的后缀名是php,所以服务器在解析整个文件的时候会使用php的解析器去执行代码。

如果这个文件只是一个普通的txt文件,即使其中有恶意代码,我们的服务器也只是把它当做一段普通的字符串而已。

所以基于这个前提,如果我们能够对上传文件的后缀名进行一个检测,对于类似php这样的文件后缀名进行拦截,就可以避免这样的漏洞。

如何绕过检测

以php为例,如果我们的后缀名检测只检测*.php,那如果我上传的是php3类型的文件,其实就可以上传成功,但是像Apache2这样的代理,会将以php,php3,php4,php5为后缀的所有文件当做php文件解析。

文件上传漏洞中阶

服务器关联漏洞

IIS5.x / 6.0 解析漏洞

  • 当创建以.asp结尾的文件目录时,在此目录下的任何文件都会被解析成asp文件。
  • 服务器默认不解析“;”以后的内容

基于两点,我们可以有两种利用形式

Nginx解析漏洞

在低版本的Nginx中存在一个由PHP-CGI导致的文件解析漏洞。

PHP的配置文件中有一个关键的选项cgi.fix_pathinfo在本机中位于php.in配置文件中,默认是开启的。

当URL中有不存在的文件时,PHP就会默认向前解析。

基于这一点,我们可以:

Apache解析漏洞

Apache在1.x和2.x版本中存在解析漏洞

Apache会从右向左判断后缀,并且会跳过无法识别的后缀,直到找到第一个可以识别的后缀,然后根据改后缀来解析。

基于这一点,我们可以:

  • 上传shell.php.test
  • 访问shell.php.test,服务器会解析shell.php.test文件,但是按照php文件格式进行解析。

前端认证绕过

很多网站都只是在前端利用JavaScript来做校验。

利用该漏洞:

  • 通过抓包的方式,修改内容。
  • 通过Chrome禁止或者删除JavaScript代码

.htaccess绕过

.htaccess文件(分布式配置文件)提供了一种方式,使得配置文件可以随文件夹不同而不同,其所放置的文件夹与子文件夹都会受到影响,其语法与Apache主配置文件相同。

如果服务器启用了htaccess,我们可以去上传htaccess文件,从而修改该文件夹的服务器配置

  • 上传一个.htaccess文件,文件内容设置为[AddType application/x-httpd-php .test]
  • 上传一句话木马文件,文件名设置为shell.test。
  • 访问shell.test,其实就会当做php文件来执行。

大小写绕过

针对黑名单的检测,我们可以改变后缀名的大小写来绕过。

比如我们想上传一个php文件,我们可以上传一个pHp。

但问题是,为什么这样是可以运行的:

  • php真的等同于pHp?
  • 如果不同,那为什么pHp可以执行。

对于Windows系统,它其实对于后缀名是大小写不敏感的。

但是对与Linux系统,他是对于大小写是敏感的,但是由于这一点,可能会导致用户使用起来不方便,所以有的开发者会手动修改自己app的配置,让它是大小写不敏感的。

文件上传漏洞高阶

Windows文件流特性绕过

Windows的文件流系统是NTFS的,NTFS文件系统实现了多文件流特性。

NTFS环境下一个文件默认使用的是未命名的文件流,但同时我们也可以创建其他命名的文件流,Windows资源管理器默认情况下并不会显示文件的命名文件流,这些命名的文件流功能上和磨人的为命名文件流是相同的。

我们可以在Windows平台上尝试以下三个命令:

1
echo 111 > test.txt:1.txt  // 向test.txt的命名文件流1.txt中写入数据111
1
echo 222 > test.txt // 向test.txt中写入数据222
1
echo test > test.txt::$data // 向test.txt的默认文件流中写入数据test

通过第一个命令,我们会创建一个test.txt文件,但是我们打开该文件会发现什么内容都没有,而此时我们通过notepad test.txt:1.txt打开该文件流,又可以看见111

而第二个和第三个命令是相同的效果,会在文件中写入内容。

基于以上的特性,我们可以这样理解,NTFS文件流允许我们让一个文件拥有多个文件流,平时我们的图形化界面使用的都是默认的未命名文件流,但是其他的文件流一旦通过命令行创建,其实是真实存在并且附着在文件上的,而且这种附着可以无视后缀名,也就是说你完全可以把一个php附着在txt文件上,比如

1
echo 恶意代码 > test.txt:shell.php

这段代码可以将恶意代码附着在一个普通的txt文件上,从而帮助我们绕过类型检测。

文件头部检查绕过

不同类型的文件其实都有自己标志性的文件头。

有的服务器可能会对这些文件头进行校验。

为了绕过这个漏洞,我们可以尝试将代码直接拼接到允许的文件类型后面,然后用解析器去执行它,如:

1
cat shell.php > test.jpg

这样我们就将一段php代码拼接在test.jpg之后。

这个时候我们再用php解析器去执行,是可以成功执行最后的代码的。

这里有一点要注意,图片中可能会存在一些解析器无法执行的字符编码,所以我们可以把这些无法解析的内容直接删除,因为我们需要的只是jpg文件的头部。