一、漏洞描述
如果网站提供文件上传功能,但是对用户上传的内容过滤不严格,导致用户可以上传任意文件甚至恶意文件, 包括恶意脚本文件、exe程序等,那么这个网站就存在文件上传漏洞。
二、漏洞成因
- 1、服务器配置不当。
- 2、开放了文件上传功能,但是对上传的内容没有做限制。
- 3、限制不严格导致被绕过。
三、漏洞危害
任意文件上传:恶意脚本、程序等。
上传的可写目录也具有可执行权限,上传webshell导致网站沦陷。
通过其他漏洞提权,导致服务器沦陷,波及旁站。
四、webshell
4.1 概念
通过上传漏洞获得的网站后门,webshell也是一个命令解释器,继承web用户权限。本质上是一个可以在服务端运行的脚本文件。
4.2 大马
代码复杂,功能强大:文件管理、执行系统命令
⚠️:密码一般写在文件中
4.3 小马
4.3.1 一句话木马
- asp
<%eval request("x")%>
<%execute request("x")%>
- aspx(ASP.NET)
<%@ Page Language="Jscript"%>
<%eval(Request.Item["x"],"unsafe");%>
<%@ Page Language="Jscript"%>:
这行代码是一个指令,告诉ASP.NET页面,页面中的脚本应该使用JScript(也就是微软的JavaScript实现)来编写。这允许你在ASP.NET页面中使用JavaScript代码。
<%eval(Request.Item["x"],"unsafe");%>:
<% ... %>:这是ASP.NET中执行服务器端代码的语法。
eval:这是一个JavaScript函数,它接受一个字符串参数,并尝试执行这个字符串作为代码。这是一个非常危险的函数,因为它可以执行任何JavaScript代码,包括恶意代码。
Request.Item["x"]:这行代码从HTTP请求中获取名为"x"的项的值。这通常是一个查询字符串参数,例如在URL中 ?x=someValue。
"unsafe":这是eval函数的一个参数,指定了代码执行的上下文。在这种情况下,它允许代码在全局上下文中执行,这意味着它可以访问和修改全局变量。
【asp VS aspx】
ASP(Active Server Pages)和ASP.NET(通常以文件扩展名.aspx表示)是微软开发的两种不同的服务器端脚本技术,用于创建动态网页。它们之间存在一些关键的区别:
一、技术基础:
ASP:基于VBScript或JavaScript,是一种较老的技术,运行在IIS(Internet Information Services)服务器上。
ASP.NET:是.NET Framework的一部分,支持多种语言(如C#、VB.NET等),提供了更强大的功能和性能。
二、执行模式:
ASP:解释执行,每次请求页面时,服务器都会解释执行ASP代码。
ASP.NET:编译执行,.aspx页面在第一次请求时被编译成中间语言(IL),然后由.NET运行时环境执行,这提供了更好的性能。
三、开发环境:
ASP:开发环境相对简单,通常使用文本编辑器和IIS。
ASP.NET:提供了集成开发环境(IDE),如Visual Studio,支持代码提示、调试和其他高级功能。
四、状态管理:
ASP:状态管理较为有限,通常依赖于Cookies或隐藏表单字段。
ASP.NET:提供了更丰富的状态管理选项,如ViewState、Session State、Cache等。
五、安全性:
ASP:安全性较低,容易受到脚本注入等攻击。
ASP.NET:提供了更高级的安全特性,如输入验证、成员资格和角色管理。
六、跨平台性:
ASP:主要运行在Windows服务器上。
ASP.NET:虽然主要也是在Windows上运行,但随着.NET Core的发展,ASP.NET Core已经支持跨平台运行。
总的来说,ASP.NET是ASP的后继者,提供了更现代、更强大的Web开发功能。随着技术的发展,ASP.NET已经演进到ASP.NET Core,这是一个更轻量级、高性能、跨平台的框架。
- php
<?php @eval($_REQUEST['cmd’]);?>
<?php assert($_POST['x']);?>
- jsp
- jspx
jSP和jspx的一句话木马比较复杂一些。
【jsp vs jspx】
JSP(JavaServer Pages)和 JSPX 是 Java Web 开发中用于创建动态网页的技术。它们允许开发者在 HTML 页面中嵌入 Java 代码。以下是 JSP 和 JSPX 的主要区别:
1、文件扩展名:
JSP:文件通常以 .jsp 作为扩展名。
JSPX:文件以 .jspx 作为扩展名。
2、XML基础:
JSP:不是基于 XML 的,这意味着在 JSP 文件中,HTML 标签不需要关闭,可以自由地混合 HTML 和 Java 代码。
JSPX:基于 XML 的,要求页面必须符合 XML 的格式,所有的 HTML 标签都需要正确关闭,以确保文件在 XML 格式上是有效的。
3、脚本元素:
JSP:使用 <% %> 来嵌入 Java 代码,使用 <%! %> 来声明类级别的变量和方法,使用 <%= %> 来输出表达式的结果。
JSPX:使用 <jsp:scriptlet> 来嵌入 Java 代码,使用 <jsp:declaration> 来声明方法,输出表达式的结果通常使用 JSPX 的标准动作 <jsp:expression>。
4、标准动作和标签库:
JSP:可以使用 JSP 标准标签库(JSTL)来增加功能,但需要手动添加标签库的指令。
JSPX:天然支持 JSP 标准标签库,不需要额外的指令就可以使用 JSTL。
5、配置和部署:
JSP:在 web.xml 中配置 servlet 映射。
JSPX:通常不需要在 web.xml 中进行额外的配置,因为它们是作为 JSP 的扩展。
6、开发工具支持:
JSP:大多数 Java IDE 和文本编辑器都支持 JSP 开发。
JSPX:可能需要更高级的 IDE 支持,因为它是基于 XML 的。
7、性能:
JSP:在性能上可能略有优势,因为它们不需要遵循 XML 的严格格式。
JSPX:由于 XML 的解析可能稍微慢一些,但这种差异通常可以忽略不计。
8、可读性和维护性:
JSPX:由于其 XML 基础,可以提供更好的可读性和维护性,特别是对于大型项目。
在实际开发中,选择 JSP 还是 JSPX 通常取决于项目需求、团队偏好以及开发工具的支持。JSPX 提供了更严格的结构,有助于保持代码的整洁和一致性,而 JSP 则提供了更多的灵活性。随着 JavaServer Faces (JSF) 框架的流行,JSPX 也变得更加流行,因为 JSF 页面默认使用 .jspx 扩展名。
在Java Web开发中,如果后端文件以JSP或JSPX结尾,这通常意味着该Web系统可能是基于以下框架开发的:
1、JavaServer Pages (JSP):JSP是一种服务器端技术,允许开发者在HTML页面中嵌入Java代码。JSP文件通常用于生成动态Web内容。如果一个Web系统的后端文件以.jsp结尾,这可能表明它是一个传统的JSP应用。
2、JavaServer Faces (JSF):JSF是一个基于组件的Web应用框架,它使用JSPX文件作为其视图技术。JSPX文件是JSP的XML兼容版本,它们提供了更严格的格式,并且与JSF的组件模型紧密集成。如果后端文件以.jspx结尾,这可能意味着该系统使用了JSF框架。
3、Spring MVC:虽然Spring MVC通常与Thymeleaf或Freemarker模板引擎一起使用,但它也可以与JSP或JSPX文件一起工作。在Spring MVC应用中,控制器会处理HTTP请求并返回一个视图名称,这个视图名称可以映射到一个JSP或JSPX页面。
4、Struts:Struts是一个MVC框架,它也支持使用JSP和JSPX文件作为其视图层。在Struts应用中,JSP和JSPX文件用于展示数据和处理用户输入。
5、其他Java EE技术:除了上述框架,还有其他Java EE技术可能使用JSP和JSPX文件,如EJB(Enterprise JavaBeans)。
需要注意的是,JSP和JSPX文件可以与多种Java Web框架一起使用,它们本身并不局限于特定的框架。开发者可以根据自己的需求和偏好选择合适的框架和技术栈。
4.3.2 配合菜刀、蚁剑使用
一句话木马短小精悍,功能强大,但是需要配合中国菜刀或者中国蚁剑客户端使用。它们能够实现的功能包括:
- 文件管理
- 虚拟终端
- 数据库管理:此时需要知道连接数据库的账密
1)中国菜刀
中国菜刀是一句话木马的管理器,也是命令操作接口。中国菜刀在连接一句话木马的时候需要填写密码(实际上就是变量名)。
中国菜刀与一句话木马配合实现了三大基本功能,如下。
@文件管理
在中国菜刀页面继承Web用户权限可以实现文件管理,包括文件查看、上传、下载、修改、删除甚至运行exe程序等。
@虚拟终端
在中国菜刀下可以获得类似于cmd和bash的命令行接口,可以执行相关命令。
@数据库管理
我们可以使用中国菜刀进行数据库管理,此时需要知道连接数据库的账密。
2)蚁剑
php一句话木马:
连接蚁剑:
- 文件管理
- 虚拟终端
- 数据库管理
配置:密码root
4.4 getshell
GetShell,顾名思义,就是获取Webshell的过程和结果。当然任意文件上传是GetShell的主要方式,但并不是唯一途径。
五、文件上传漏洞的基础利用和防御绕过
5.1 利用条件
- 有可访问的文件上传功能
任意文件上传漏洞,首先要有能上传文件的的地方,即——要有文件上传点。有一些网站虽然貌似没有上传点,但是其实存在上传代码的。虽然没有明确使用上传功能 ,但使用了上传有关的函数,这种情况需要通过代码审计去看。
最常见的就是上传头像。
写权限+执行权限
Web容器可以解析webshell
能访问得到上传的文件:如果访问不到,则无法对文件进行控制,也就没有漏洞的说法
无视以上条件配置不当:有PUT方法(只要有PUT方法必有文件上传漏洞)
5.2 利用 HTTP PUT方法上传文件
5.2.1 Apache 如何开启 PUT方法
1)telent 测试 web服务器开启了哪些方法
用OPTIONS方法探测目标服务器开启了哪些方法。
可以看到支持的方法有五个,没有开启PUT方法。
telnet 192.168.33.4 80
OPTIONS / HTTP/1.1
HOST:192.168.33.4
2)开启PUT方法
- 操作配置文件httpd.conf[记得备份], 开启dav相关模块
ctrl +F dav搜索dav
取消102和103行的注释,开启两个模块。
启用模块:
添加DAV On
- 开启文件锁【要创建dav文件夹】
DavLockDB C:\phpstudy\WWW\DavLock 【放在httpd.conf 的第一行】
创建C:\phpstudy\WWW\DavLock目录
重启服务。
3)再次用OPTIONS方法测试
没有PUT方法,但也可以尝试上传文件并成功。
5.2.2 PUT方法的上传漏洞
1)利用put方法上传webshell
PUT /php/infosxk.php HTTP/1.1
HOST:192.168.33.4
Content-Length:18
<?php phpinfo();?>
⚠️:不要太相信ctrl c ctrl v,有可能会输入其他的字符。
访问测试:
5.3 防御绕过和利用
5.3.1 黑白名单策略
黑白名单是最常用的安全策略之一。在计算机安全中,黑白名单类似于一个列表,列表中写了一些条件或规则,如果“客体”在黑名单中,一律“禁止”,如果“客体”在白名单中,一律“允许”。类似于手机号码的黑白名单。配合使用,白名单优先级更高。
- 绕过思路:找黑名单之外的可以上传的后缀,白名单的话不太好绕过。
- 但如果是前端的限制,则无论是黑名单和白名单对攻击者来说都是失效的,只需要抓包改包就行了。
5.3.2 前端限制与绕过
F1:因为JS脚本的运行环境是浏览器,我们可以修改JS代码,甚至删除表单事件。
F2:使恶意文件后缀名符合白名单策略,用Burp 挂代理抓包,然后修改文件后缀名即可。
对于文件上传,只从Web前端进行检测显然防护不足,那么服务器端检测就特别重要了。一般服务器端检测,采用黑白名单策略。
5.3.3 服务器端限制
1)MIME检测
MIME(Multipurpose Internet Mail Extensions)是描述消息内容类型的因特网标准。MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据。常见的MIME类型如下:
在HTTP协议中,使用Content-Type 字段表示文件的MIME类型。当我们上传文件的时候,抓到HTTP数据包。在服务器端会检测Content-Type类型。
⚠️:Content-Type 是由浏览器定义的。
- 绕过方法:利用BP,修改Content-Type类型绕过,服务器对MIME类型的检测。
2)文件内容检测
除了检测上传文件的Content-Type类型,为了保持安全性,服务器端还会检测文件内容。
PHP中有一个函数getimagesize(),这个函数本意是检查图片的大小,但是在检查之前,该函数会判断目标文件是否是一张图片。 因此,可以用该函数来检测文件的内容。【upload-load 14关。】
- 图片木马绕过内容检测(图片木马的制作)【具体方法见
图片木马制作
一文。】
3)后缀名检测
- 黑名单
寻找其他未被禁止上传的文件类型做尝试:
- 白名单
只能上传白名单格式的文件。
利用漏洞需要结合其他漏洞(文件解析漏洞等)。
绕过方法总结
冷门后缀 (php2、php3、php4、php5、phtml、pht…)
大小写绕过
双写绕过
改.htaccess解析
GET/post型00截断
Web容器解析漏洞
改.user.ini自动包含
Windows特性 空格
Windows特性 点.
条件竞争
六、 00截断
00就是Null (空)字符,URL中表现为%00,00截断会导致文件上传路径截断。
【我们以upload-labs第12关为例子说明这个问题。】
原理分析:php move_upload_file()函数的实现基于C语言,C语言中,字符串的结尾为\0,null。见到null,C语言会认为该字符串已经结束。利用上述特点,可以截断上传文件的路径,将文件另存为我们想要的目标文件,比如webshell等。
6.1 upload-labs 12关(EX)
1、上传phpinfo.php BP抓包测试(直接跳过本地限制这一环,本地限制的绕过过于简单)
上传失败: 提示:只允许上传.jpg|.png|.gif类型文件!
2、BP抓包改后缀名为合法后缀名。
src=”../upload//5820210705074748.jpg
上传成功,进行了另存和重命名。
注意到 Content-Type为php也过去了,说明服务器没有对MIME类型做检测。
注意到内容为php脚本,也过去了,说明服务器没有对内容进行检测。
综上,服务器对上传文件的后缀名做了限制并进行了另存重命名操作。
3、00截断
URL中默认传递了save_path变量,指明要保存的路径。
/upload-labs-master/Pass-12/index.php?save_path=../upload/
上传的文件被保存在,/upload/目录下。
save_path=../upload/sxk.php 提示上传出错。
根据00截断的原理,实现文件的另存。
save_path=../upload/sxk.php%00
还是上传出错。
PHP版本 ,推荐5.2.17 ,其他版本可能会导致部分Pass无法突破。
应该是PHP版本的问题,思路没问题,phpstudy换成5.2.17版本的还是截断不成功。
【见5.4.2,路径00截断+文件名绕过后缀检测。】
6.2 PHP 00截断
1)用在哪里
除了php配置的那个解析漏洞之外,正经使用%00截断绕过应该是放在上传文件路径后,而非文件名处。
2)原理
0x00是字符串的结束标识符,攻击者通过手动添加字符串结束标识符的方式,将00后面内容截断。但是00后面的东西又能帮助我们绕过文件检测。
3)条件
要求GPC处于关闭状态,且php版本小于5.3.29才可利用。
4)使用
- 为什么00截断用在上传后文件目录?
在文件名中构造00截断,比如1.php%001.jpg。在程序提取后缀名的时候,遇到%00就认为结束了。这个时候,他提取到的后缀名还是.php,然后.php被限制上传,所以绕过失败。
文件名检测代码:
$uploaded_name = $_FILES[ 'file' ][ 'name' ];
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1); // 提取上传文件后缀
$target_name = md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext; // 对上传文件进行重命名
if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ))
{
move_uploaded_file($_FILES["file"]["tmp_name"],
$dir . $target_name); // 将临时文件移动到指定目录
$result = $dir . $target_name;
echo "Stored in: $result";
}
else{
echo "Invalid file";
}
- 正确用法
在数据包中,含有上传后文件目录的情况才可使用。比如在数据包中存在path:/uploads/
为什么修改path才可以,因为程序中检测的是文件的后缀名,如果后缀合法则拼接路径和文件名,那么攻击者修改了path以后的拼接结果为:uploads/aaa.php%00/2018051413370000.jpg,移动文件的时候会将文件保存为uploads/aaa.php,从而达到Getshell效果。
5)%00(urldecode)
- 为什么要进行urldecode操作呢?
原因在于上传的表单中有一个enctype的属性,并且需要enctype=”multipart/form-data” (不对表单中数据进行编码),path大多数都是存放在表单中的,因此需要在数据包中进行urldecode操作使%00变成字符串结束符号。
- 直接添加%00而不进行urldecode操作
因为path也可以存放在URL或者Cookie中,而在提交数据的时候,浏览器会对数据做一次urldecode的操作,而到服务端,会对数据进行一次urldecode的操作,因此如果path在非enctype=multipart/form-data的表单中或URL or Cookie中的时候,就可以直接写%00不需要进行URLdecode操作,让服务端对%00进行URL解码即可。
注意⚠️:
简单些说,path在url、cookie或者上传方式不是multipart/from-data的时候,就不用进行对%00进行url解码。
七、 .htaccess文件上传
7.1 .htaccess文件介绍
.htaccess文件 (或者”分布式配置文件”),全称是Hypertext Access(超文本入口)。 它提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。 .htaccess文件是用于apache服务器下的控制文件访问的配置文件,因此Nginx下是不会生效的。
.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
7.2 .htaccess 文件上传漏洞原理
【上传.htaccess文件覆盖更改服务器的配置,按照攻击者目标解析执行上传的文件】