
Análise técnica aprofundada do CVE-2023-46604, uma vulnerabilidade de RCE no protocolo OpenWire do Apache ActiveMQ, incluindo decomposição da estrutura de pacotes e mecanismo de exploração.
O ActiveMQ é um broker que inclui clientes que suportam JMS, permitindo comunicação entre sistemas que utilizam diversas linguagens, não apenas Java. Além disso, é um servidor de padrões de mensagens e integração de código aberto que mantém a consistência e persistência entre os sistemas por meio de recursos de clustering, banco de dados e sistema de arquivos.
OpenWire é um protocolo de mensagens binárias usado no Apache ActiveMQ. Foi projetado para transferência eficiente de dados entre o broker (ActiveMQ) e o cliente.
CVE-2023-46604 é uma vulnerabilidade no protocolo OpenWire (no processo de Marshal) do ActiveMQ que permite que um atacante remoto com acesso à rede a um broker ou cliente OpenWire baseado em Java manipule os tipos de classe serializados no protocolo OpenWire para executar comandos de shell arbitrários, fazendo com que o cliente ou o broker (respectivamente) instancie qualquer classe no classpath. É uma das técnicas de ataque distintamente usadas pelo grupo APT Andariel.
CVE-2023-46604 ocorre quando, durante a troca de dados através do protocolo OpenWire, são manipuladas chamadas XML ou inseridos dados maliciosos para executar comandos remotos. O protocolo OpenWire lida basicamente com serialização e transmissão de dados, e a vulnerabilidade explora o fato de que tipos de classe maliciosos são permitidos durante esse processo de serialização.
[Imagem] POC
[Imagem] XML
패킷 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 | ]
+----------+ [ +-------+----------------+ ]
[============================]
[Imagem 1] Verificação de pacote OpenWire no WireShark
[Imagem 2] Significado do cabeçalho do pacote
패킷 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와 같은 유형
A [Imagem 2] é uma explicação adicional para ajudar a entender o cabeçalho do pacote acima, com a forma de cada item do cabeçalho e a descrição do código especificado. Agora que vimos o cabeçalho, vamos ver como o conteúdo do corpo passa pelo código.
[Imagem 3] Significado do corpo do pacote
패킷 Body 내용 끊어서 파악
+--------------------------------------------------------------------------------------+
| not-null | not-null | classname-size | classname | not-null | message-size | message |
|----------|----------|----------------|-----------|----------|--------------|---------|
| 01 | 01 | 0043 | ..... | 01 | 0012 | ..... |
+--------------------------------------------------------------------------------------+
not-null (01) | / [그림 3]의 첫번째 함수에서 not-null pass
not-null (01) | classname-size (0043) | classname / [그림 3]의 두번째 함수에서 not-null pass, 세번째 함수에서 사이즈 체크 위한
not-null (01) | message-size (0012) | message / [그림 3]의 두번째 함수에서 not-null pass, 세번째 함수에서 사이즈 체크 위한
A [Imagem 3] mostra como os valores definidos no corpo do pacote atuam. Finalmente, através da [Imagem 4], os dados serializados carregam e instanciam a classe.
[Imagem 4] Execução de RCE via createThrowable
[Imagem 5] Exemplo de execução de calculadora RCE
[Imagem 5] Git Diff (5.17.2 -> 5.17.6)
[Imagem 5] Função validate
Ao contrário de outras análises, a razão pela qual analisamos o pacote de ataque nesta vulnerabilidade foi para entender e estudar como o ataque é realmente executado.
Ao examinar minuciosamente a estrutura e o fluxo do pacote, foi possível compreender claramente a forma específica que o atacante usa para comprometer o sistema e seu mecanismo de operação.