本文主要讲我对漏洞的探索和探索过程中发现的一个可以进行缓存攻击的坑。
问题
struts2 的漏洞在网上已经够热闹了,各个技术站点都是头条显示,微博上也有大佬转发。
这个漏洞的危害行在于允许执行远程命令,直接攻击服务器,危害无穷;根源在于struts2框架把用户输入的数据当作命令执行了,这也是一切注入估计的根源。
今天旁边的同事soul在调试官方给出的可攻击的demo,想看看到底是怎么攻击;我好奇的是既然攻击可以远程启动一个子进程的话,那么那些输入的 java代码应该会被编译,然后再执行,如果是这样的话,这框架不会是对每个输入都进行动态编译吧,这会很影响性能的,所以我想看看struts2到底是怎么处理的,就看我同事调试。
听过debug跟踪,发现struts2也不是直接调用Java 编译器的(毕竟性能问题在那里),而是直接根据输入命令解析为对应的命令对象(struts2称为Expression),在执行这个命令对象,这些命令对象会缓存在 com.opensymphony.xwork2.ognl.OgnlUtil
对象的一个 ConcurrentMap<String, Object>
属性里,键是输入的action 名称,值是命令对象,这样,对于每个输入参数,都先在缓存查找,如果没有则进行解析,这个逻辑如下:
public Object compile(String expression, Map context) throws OgnlException {
Object tree;
if (enableExpressionCache) {
tree = expressions.get(expression);
if (tree == null) {
tree = Ognl.parseExpression(expression);
expressions.putIfAbsent(expression, tree);
}
} else {
tree = Ognl.parseExpression(expression);
}
if (!enableEvalExpression && isEvalExpression(tree, context)) {
throw new OgnlException("Eval expressions has been disabled");
}
return tree;
}
这个远程漏洞的解决方法
仍然用公开的攻击方法进行攻击,根据抛出的异常信息,发现,对输入参数名进行了检查。
在 com.opensymphony.xwork2.interceptor.ParametersInterceptor
类里有两个常量:
public static final String ACCEPTED_PARAM_NAMES = "\\w+((\\.\\w+)|(\\[\\d+\\])|(\\(\\d+\\))|(\\['\\w+'\\])|(\\('\\w+'\\)))*";
protected static final int PARAM_NAME_MAX_LENGTH = 100;
在此类的其他代码检查了参数名是否匹配ACCEPTED_PARAM_NAMES
,且长度不超过PARAM_NAME_MAX_LENGTH
。
这样之前的那些攻击因为特殊字符都不能通过了,也就避免了这个漏洞。
还有一个改动是在其他地方,是解决redirect
和redirectAction
的,具体可对比代码。
总之,这个远程漏洞攻击确实是解决了。
新的问题
在调试过程发现的一个现象是:每个请求参数都有一个对应的缓存在 com.opensymphony.xwork2.ognl.OgnlUtil
的缓存里,以参数名为键,也就是说,这是一个单例对象,且是全局共享。
最大的问题是,哪怕我输入的参数名不是合法的Action的属性,它也会缓存在那里,这就是说:这个缓存的内容是用户可以决定的。
所以问题就简单了,我发送的每个请求的参数名都是不一样的,拿soul本地部署的struts-blank实例来测试,每个请求就一个参数,1万多个参数就让他OOME了。
这个问题的另一个副作用在于,即使还没有OOME,只要缓存的数量足够多时,也会导致 ConcurrentMap
退化成一个链表,因为每个位桶的链都会很长,这个影响就像之前爆出的Java Hash 漏洞攻击的效果一样。
我觉得这是一个bug,就在strtus2官网注册,提了个issue https://issues.apache.org/jira/browse/WW-4146,struts2的leader也很快回复了,说这个缓存是可以禁用的(从前面的代码也可以看出,只是我一激动就提单了): <constant name="struts.ognl.enableExpressionCache" value="false"/>
,所以这不算是个bug吧,但我觉得这绝对一个坑了,因为默认是开启缓存的,也就是说默认情况下,我是可以让用了struts2的应用OOME的。
这个问题的为难之处在于,虽然可以关闭缓存来避免OOME,但是没有缓存肯定会导致性能劣化。如果用了缓存,不管用什么缓存机制,都可能被攻击。
目前也没有好的解决方法,所以还是先把缓存禁用了,慢总比无法访问好。
相关推荐
在2017年,Struts2被发现存在一个名为CVE-2017-9791的高危漏洞,该漏洞可能导致远程代码执行(RCE),从而使攻击者能够控制服务器,窃取敏感信息,甚至导致服务瘫痪。针对这个漏洞,Struts2官方发布了修复版本2.3....
对于安全性,Struts2 提供了内置的拦截器来实现输入校验和防止常见的Web攻击,例如XSS(跨站脚本攻击)和CSRF(跨站请求伪造)。拦截器可以在请求到达Action之前进行校验,如果校验未通过,则可以终止请求的进一步...
Struts2是一个流行的Java Web应用程序框架,用于构建和维护可扩展、模块化和易于管理的MVC(模型-视图-控制器)应用。从2.3.15.1升级到2.3.35是一个重要的更新过程,因为它涉及到安全补丁、性能优化和新功能的引入。...
本项目"Struts2 BBS"是一个用Struts2、JSP(JavaServer Pages)和MySQL数据库构建的论坛系统,旨在展示如何在实际开发中整合这三个核心技术。 1. **Struts2框架**:Struts2作为ActionServlet,处理HTTP请求,通过...
为了提升性能,Struts2提供了缓存机制,如Action实例的多线程支持和结果页面的缓存。同时,通过合理配置拦截器链,可以避免不必要的操作,进一步提高响应速度。 总的来说,Struts2 JAR包是Java web开发中不可或缺的...
此外,还有元标签用来控制页面缓存和描述。 2. **Struts2配置**: `struts.xml`是Struts2的核心配置文件,它定义了应用程序的行为。在这个例子中,配置了两个动作(Action): - `downloadList`:当用户访问`...
- Struts2 OGNL2.6.11版本之前存在安全漏洞,如著名的CVE-2017-5638,攻击者可以通过精心构造的OGNL表达式来执行任意代码。2.6.11版本修复了这些漏洞,增强了对OGNL表达式的过滤和限制。 5. **OGNL的优化**: - ...
8. **安全增强**:Struts2.3.4.1版本中,通常会包含对已知安全漏洞的修复,例如XSS(跨站脚本攻击)和CSRF(跨站请求伪造)防护。 在实际开发中,你可以通过以下步骤使用Struts2.3.4.1: 1. 添加Struts2的依赖库到...
- **XSS(跨站脚本攻击)**:Struts2的OGNL表达式可能导致XSS漏洞,需进行输入验证和输出编码。 - **CVE-2017-9805**:这是一个著名的Struts2远程代码执行漏洞,提醒我们定期更新框架以修复安全漏洞。 8. **...
- 使用最新版本的Struts2及其插件,修复已知的安全漏洞。 - 对敏感操作进行权限检查,防止未授权访问。 - 使用合适的插件防止SQL注入、XSS攻击等。 9. **调试与测试**: - 利用Struts2的日志功能进行问题排查。...
安全性方面,Struts2提供了多种机制来防止常见的Web攻击,但开发者仍需了解潜在风险并采取相应措施。 在提供的源码文件列表中,我们可以看到不同目录下的lib文件夹,这通常包含了各章节中所用到的依赖库,比如...
IIS也经常被曝出漏洞,如缓存溢出漏洞、配置不当导致的目录遍历、服务拒绝攻击等。 5. JBoss是一个开源的应用服务器,遵循Java EE标准。JBoss主要被企业级客户使用,用于部署和管理Java应用程序。JBoss的漏洞也主要...
Struts2 2.5.16版本虽然包含了重要的安全更新,但历史上Struts2曾爆出过严重漏洞,如CVE-2017-5638(S2-045)。因此,保持框架及时更新对于避免安全风险至关重要。 5. **最佳实践**: - 使用最新稳定版本,定期...
例如,通过新增参数 `struts.excludedClasses` 和 `struts.excludedPackageNamePatterns`,开发者可以严格限制某些不安全的对象类型和包名,如 `java.lang.Object`、`ognl.OgnlContext` 等,以防止恶意攻击。...
2. **CVE-2017-5638**:Struts 1的一个严重漏洞,允许远程代码执行,影响了大量使用Struts 1的应用程序,需要及时打补丁或升级至更安全的版本。 **如何部署和使用Struts 1.2.9:** 1. 解压`struts-1.2.9-bin.zip`,...
Struts2、Spring3和MyBatis是Java Web开发中常用的三大框架,它们各自负责不同的职责,协同工作可以构建出高效、灵活的企业级应用。这个压缩包提供的最全jar包集合,显然是为了方便开发者在搭建环境时快速获取所需的...
3. **安全性问题**:Struts框架历史上曾出现过几次严重的安全漏洞,例如著名的CVE-2017-5638(Struts2 S2-045),这是一个远程代码执行漏洞,允许攻击者通过精心构造的HTTP请求注入恶意代码。因此,理解和防御Struts...
9. **安全问题**:Struts2历史上曾出现过严重的安全漏洞,如CVE-2017-5638(Struts Shatter漏洞)。及时更新Struts2版本,应用安全补丁,避免安全风险。 10. **测试与调试**:Struts2应用的测试可能较为复杂,因为...
- **XSS与CSRF攻击**:使用Struts2的安全插件,如Struts2-Security插件,防止XSS和CSRF攻击。 - **参数注入**:对用户输入进行校验,避免SQL注入等安全风险。 9. **版本兼容性**: - 遇到问题时,考虑更新Struts...
Struts2.3.1.1版本可能会对已知的安全漏洞进行修复,例如OWASP Top Ten中的XSS、CSRF等攻击。 6. **源码分析**: 源码分析有助于开发者深入理解Struts2的工作原理,可以学习到Action的生命周期、拦截器的执行流程...