首页
学习
活动
专区
圈层
工具
发布

代码审计| Spring框架实例篇

Java代码审计Spring框架思路篇中,斗哥为大家讲述了如何得到Spring审计的Demo,审计源码,根据IDEA与Spring框架审计思路初步判定是否存在漏洞。

Java代码审计Spring框架知识篇中,斗哥讲述Spring框架漏洞分析和利用的必备知识,如java命令执行函数、SpEL表达式使用,两者的配合使用构造Spring框架漏洞的命令执行POC。

本期Java代码审计Spring框架实例篇将结合前两篇的知识,以Spring Messaging 远程命令执行漏洞为例,根据审计思路来分析,深入学习Spring框架的代码审计。

0X01 漏洞环境说明

Spring曝出的漏洞并不多但危害都很大,比如Spring Messaging 远程命令执行漏洞。

1.Spring框架中通过spring-messaging模块来实现STOMP。 2.客户端定义headers并且其中包含selector,传入SpEL(可带有恶意代码),向服务器端发送消息。 3.服务端和客户端建立起连接后,服务端接收到SUBSCRIBE订阅消息后获取headers并且在当前会话中查找headers中的selector值最终执行。

0X02 漏洞流程复现

1、STOMP说明:

STOMP(Simple Text-Orientated Messaging Protocol) 面向消息的简单文本协议,用于服务器在客户端之间进行异步消息传递,它定义了服务端与客户端之间的格式化文本传输方式。 STOMP是基于帧的协议:由命令和一个或多个头信息、一个空行及负载(文本或字节)所组成。 其中可用的命令包括: CONNECT、SEND、SUBSCRIBE、UNSUBSCRIBE、BEGIN、COMMIT、ABORT、ACK、NACK、DISCONNECT 客户端可以使用SEND命令来发送消息以及编辑消息的内容,用SUBSCRIBE命令来订阅消息以及确定接收对象。

2、WebSocket说明:

WebSocket 协议提供了 通过一个套接字实现全双工通信的功能。也能够实现 web 浏览器 和 server 间的 异步通信。(支持SockJS,用来解决浏览器端、服务器以及代理不支持WebSocket的问题。)

WebSocket是底层协议,而 STOMP 是基于 WebSocket(SockJS)的上层协议 就像HTTP在TCP套接字之上添加了请求-响应模型层一样,STOMP在WebSocket之上提供了一个基于帧的线路格式(frame-based wire format)层,用来定义消息的语义。

3、建立连接:

1.客户端与服务器进行HTTP握手连接。

2.客户端通过发送CONNECT帧建立连接。

3.服务器端接收到连接尝试返回CONNECTED帧。

4.客户端通过SUBSCRIBE向服务端订阅消息。

连接服务器JS代码:

代码语言:javascript
复制
function run() {
  selector = document.getElementById('expression').value
  stompClient = Stomp.client('ws://' + window.location.hostname + ':' + window.location.port + '/hello');
  //向服务器发起连接
  stompClient.connect({}, function(frame) {
    //连接成功时,服务器响应CONNECT帧的回调方法
    stompClient.subscribe('/topic/greetings', function() {}, {
      "selector": selector
    })
  });
}

headers如果客户端进行定义,也就是说只要我们在headers当中的selector传入SpEL命令执行的poc就可以达到表达式注入的目的。

0X03 动态分析

分析流程: 1.已爆出漏洞方法或自认为可疑处打上断点 2.debug运行 3.在客户端发送初步POC 4.动态调试 5.在客户端发送POC,调试修改直到成功执行 (1)动态调试发现服务器根据订阅ID来确定会话,从客户端获取headers和selector进行绑定。

(2)然后从会话headers中获取selector值当作expression最后执行(上文提到headers可以在客户端定义,所以我们在headers当中的selector传入poc就可以达到表达式注入的目的。而selector则是用SpEL表达式编写)。 DefaultSubscriptionRegistry类的addSubscriptionInternal方法中,有expression = this.expressionParser.parse Expression(selector)

如果要命令执行,则还需要expression.getValue或epression.setValue。 (3)查看调用栈,客户端在发送send message时会调用getValue。 服务器调用filterSubscription对消息进行过滤,最终到通过expression.getValue()执行了POC。

Boolean.TRUE.equals(expression.getValue(context, Boolean.class))最终到通过expression.getValue()执行了POC。

0X04 小小总结

相信通过本期Java代码审计Spring框架实例篇。相信小伙伴们对Spring框架的代码审计有了更深入的了解,当你要审计某个源码时一定要先知道整个代码的逻辑流程,再进行动态调试这样可以事半功倍。 下期斗哥将带来Java代码审计Spring框架修复篇,对Spring Messaging 远程命令执行漏洞demo进行修改与补丁分析。

PS:回答文章下方的选择题,回答正确者即有机会获得斗哥独家赠送的文章源码与材料哦!(答案请在文章下方留言)

STOMP协议中什么命令是用来订阅消息与服务器进行交互?

A. SEND

B. SUBSCRIBE

C. BEGIN

D. COMMIT

下一篇
举报
领券