
Tiefgehende technische Analyse von CVE-2023-46604, einer RCE-Schwachstelle im OpenWire-Protokoll von Apache ActiveMQ, einschließlich Aufschlüsselung der Paketstruktur und des Ausnutzungsmechanismus.
ActiveMQ ist ein Broker, der Clients umfasst, die JMS unterstützen, und ermöglicht die Kommunikation zwischen Systemen, die nicht nur Java, sondern auch verschiedene andere Sprachen verwenden. Darüber hinaus ist es ein Open-Source-Messaging- und Integrationsmuster-Server, der über Clustering-Funktionen sowie DB und FileSystem die Konsistenz und Dauerhaftigkeit zwischen den einzelnen Systemen aufrechterhält.
OpenWire ist ein binäres Messaging-Protokoll, das in Apache ActiveMQ verwendet wird. Es wurde für eine effiziente Datenübertragung zwischen dem Broker (ActiveMQ) und den Clients entwickelt.
CVE-2023-46604 ist eine Schwachstelle im OpenWire-Protokoll (während des Marshal-Prozesses) in ActiveMQ. Sie ermöglicht es einem entfernten Angreifer mit Netzwerkzugriff auf einen Java-basierten OpenWire-Broker oder -Client, die im OpenWire-Protokoll serialisierten Klassentypen zu manipulieren, beliebige Shell-Befehle auszuführen und den Client bzw. den Broker (jeweils) dazu zu bringen, alle auf dem Klassenpfad befindlichen Klassen zu instanziieren. Sie ist eine der repräsentativen Angriffsmethoden der APT-Gruppe Andariel.
CVE-2023-46604 läuft so ab, dass während des Datenaustauschs über das OpenWire-Protokoll ein XML-Aufruf manipuliert oder bösartige Daten eingefügt werden, um Remote-Befehle auszuführen. Das OpenWire-Protokoll übernimmt grundsätzlich die Serialisierung und Übertragung von Daten. Die Schwachstelle nutzt aus, dass bei diesem Serialisierungsprozess bösartige Klassentypen zugelassen werden.
[Abbildung] POC
[Abbildung] XML
Wir werden dies anhand der Analyse der Pakete untersuchen, die in ActiveMQ 5.17.3 über das OpenWire-Protokoll gesendet werden. Zunächst müssen wir uns vor der Paketanalyse mit der Form des Pakets vertraut machen.패킷 Header
+----------------------------------------------------------------------------------+
| Packet Length | Command | Command Id | Command response required | CorrelationId |
|---------------|---------|------------|---------------------------|---------------|
| 00000066 | 1f | 00000000 | 00 | 00000000 |
+----------------------------------------------------------------------------------+
패킷 Body
+--------------------------------------------------------------------------------------+
| not-null | not-null | classname-size | classname | not-null | message-size | message |
|----------|----------|----------------|-----------|----------|--------------|---------|
| 01 | 01 | 0043 | ..... | 01 | 0012 | ..... |
+--------------------------------------------------------------------------------------+
OpenWire 패킷 Body 형식
[=If not-null is 1===========]
+----------+ [ +-------+----------------+ ]
| not-null | [ | size | encoded-string | ]
+----------+ [ +-------+----------------+ ]
| byte | [ | short | size octects | ]
+----------+ [ +-------+----------------+ ]
[============================]
[Abbildung 1] WireShark OpenWire-Paketprüfung
In [Abbildung 1] ist die tatsächliche Payload mit dem oben beschriebenen Header- und Body-Format des Pakets zu sehen (der Einfachheit halber erfolgt der Aufruf nicht über den ClassPath wie bei der ursprünglichen POC-Methode, sondern über das FileSystem). Wir werden nun im Code genauer untersuchen, welche Wirkung diese Paketinhalte entfalten und warum sie auf diese Weise gesendet werden müssen.
[Abbildung 2] Bedeutung des Paket-Headers
패킷 Header 끊어서 파악
+----------------------------------------------------------------------------------+
| Packet Length | Command | Command Id | Command response required | CorrelationId |
|---------------|---------|------------|---------------------------|---------------|
| 00000066 | 1f | 00000000 | 00 | 00000000 |
+----------------------------------------------------------------------------------+
Packet Length : 00000066 / OpenWire 같은 프로토콜은 기본적으로 패킷을 길이를 명시.
Command : 1f / 는 ExecptionResponse(31)을 명시 하기 위한 설정 31은 16진수(hex)로 1f.
Command Id : 00000000 / 는 int 형태 4바이트 형태 임으로 16진수 표현시 00 00 00 00.
Command response required : 00 / 는 boolean 타입으로 True(01), False(00) 에서 False.
CorrelationId : Command Id와 같은 유형
[Abbildung 2] enthält ergänzende Erläuterungen zu den Formaten der einzelnen Header-Felder und den zugehörigen Code-Werten, um das Verständnis des obigen Paket-Headers zu erleichtern. Nachdem wir uns nun den Header angesehen haben, betrachten wir anhand der Body-Inhalte, wie der Code durchlaufen wird.
[Abbildung 3] Bedeutung des Paket-Bodys
패킷 Body 내용 끊어서 파악
+--------------------------------------------------------------------------------------+
| not-null | not-null | classname-size | classname | not-null | message-size | message |
|----------|----------|----------------|-----------|----------|--------------|---------|
| 01 | 01 | 0043 | ..... | 01 | 0012 | ..... |
+--------------------------------------------------------------------------------------+