1. 文件包含漏洞介绍
文件包含漏洞是一种Web应用程序中非常常见的安全漏洞,其主要原因是在应用程序中的文件处理功能中没有对用户提供的输入进行充分的校验与过滤,导致攻击者可以通过构造恶意参数值,在应用程序中获取到本应不能被访问的文件资源,从而进行非法的操作。文件包含漏洞最常见的便是本地文件包含漏洞(Local File Inclusion,LFI)与远程文件包含漏洞(Remote File Inclusion,RFI)
1.1 本地文件包含漏洞
本地文件包含漏洞是指攻击者通过在URL参数中注入特殊字符,使得应用程序把这些字符当做了文件名进行处理,进而在应用程序中实现任意文件读取、文件删除等危险操作。例如:
// vuln.jsp
<% String file = request.getParameter("file");
FileInputStream fis = new FileInputStream(file);
int length = fis.available();
byte[] buffer = new byte[length];
fis.read(buffer);
String content = new String(buffer, "UTF-8");
out.print(content); %>
上述代码中,当处理用户传递进来的“file”参数值时没有进行任何的过滤或者校验, 因此攻击者可以通过在URL中注入包含directory traversal和null字节攻击的伪造参数值来获取其他任意文件的内容。这种漏洞环境下,攻击者可以获取其具有权限的所有操作文件,例如tomcat/conf/server.xml等文件。
1.2 远程文件包含漏洞
远程文件包含漏洞是指攻击者通过在URL中注入可执行代码,使应用程序在读取文件时通过远程方式加载恶意文件并执行,造成服务器被控制、敏感数据泄露等危险情况。例如:
// vuln.jsp
<% String url = request.getParameter("url");
URLConnection conn = new URL(url).openConnection();
InputStream stream = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String line;
while ((line = reader.readLine()) != null) {
out.println(line);
} %>
上述代码中,攻击者可以通过构造URL,将攻击者可控制的参数传入,通过该参数来控制应用程序远程加载恶意文件并执行,从而达到控制服务器的目的。
2. 文件包含漏洞的影响
文件包含漏洞是一种十分危险的漏洞,由于其本质上是基于文件操作进行的攻击,因此其可以对Web应用程序以及服务器造成以下危害:
2.1 盗取敏感信息
攻击者可以通过构造特殊的参数,获取攻击者没有权限访问的文件资源,从而获取到应用程序中存储的敏感信息,例如密钥、证书、配置文件、日志文件等。根据攻击者的恶意程度,这些信息可能会被用于高级攻击,例如中间人攻击。
2.2 引起重大的安全漏洞
由于威胁模型不同,本地文件包含漏洞与远程文件包含漏洞对服务器的威胁也略有不同。对于本地文件包含漏洞可能导致的威胁包含如下三种:
目录遍历:获取其具有权限的所有操作文件,例如tomcat/conf/server.xml等文件。
文件读取:攻击者可以获取攻击者没有权限访问的敏感信息。
文件覆盖:攻击者可以通过将虚假文件路径发送到服务器,成功实现删除、替换、修改文件等目的。
而远程文件包含漏洞则可以直接引起code执行漏洞,从而达到GET SHELL或者控制服务器等目的;或者通过访问恶意Web页面或加载恶意CSS及JS,诱导用户下载木马或盗取大量的用户敏感信息。
2.3 影响应用程序可用性
在攻击者通过文件包含漏洞,获取存储于服务器端应用程序相关的敏感数据后,大量的恶意访问,大量恶意访问等到的返回结果会导致服务器过载,影响服务器的稳定性和可用性。
3. 文件包含漏洞修复
在代码开发中充分的过滤用户提供的数据是修复文件包含漏洞的核心方法。过滤的方式不同,会对应着不同的修复方法。
3.1 过滤字符
过滤掉URL中或者用户输入中出现的目录遍历字符串和恶意字符,使得恶意输入无法通过处理,从而有效地防止LFI和RFI等攻击。
// vuln.jsp的修复代码
<%
String file = request.getParameter("file");
// 假设为Windows环境下
file = file.replace("/","\\").replace("..\\","").replace("..%5c","").replace("%00","");
FileInputStream fis = new FileInputStream(file);
int length = fis.available();
byte[] buffer = new byte[length];
fis.read(buffer);
String content = new String(buffer, "UTF-8");
out.print(content); %>
3.2 解码字符
在URL传递过去的参数在接收端很有可能是经过编码处理的,因此对于一个恶意输入的参数,我们需要对其进行decode解码,从而获取其真实的信息,使得无法伪造任意文件路径。
// vuln.jsp的修复代码
<%
String url = URLDecoder.decode(request.getParameter("url"), "UTF-8");
URLConnection conn = new URL(url).openConnection();
InputStream stream = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String line;
while ((line = reader.readLine()) != null) {
out.println(line);
} %>
4. 文件包含漏洞总结
文件包含漏洞是Web应用程序中非常常见的安全漏洞,其主要是由于Web开发人员对用户输入进行处理时没有充分的严密过滤和校验,导致攻击者可以通过伪造URL或者输入信息的方式,访问到本应不能被访问的文件资源,从而进行非法的操作。文件包含漏洞的修复需要开发人员充分了解文件包含漏洞的特点,理解过滤字符和解码字符的方式,并根据具体的业务场景实际进行修复。