Closed Marsman1996 closed 4 years ago
fixed in PR #532
Two CVEs were assigned here: CVE-2018-20552 and CVE-2018-20553.
Hi,your patch of CVE-2018-20552 isn't right. The crash occurs at the following code:
873 * ICMP
874 */
875 else if (proto == IPPROTO_ICMP) {
876
877 /* prevent alignment issues */
// data=0x00007ffffffed8d8 → [...] → 0x0000800000010000, hl=0x2c
→ 878 memcpy(&icmp_hdr, (data + TCPR_ETH_H + hl), TCPR_ICMPV4_H);
879
880 dbgx(3, "%s uses ICMP... ", srcip);
881
882 /*
883 * if port unreachable, then source == server, dst == client
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "tcpprep", stopped, reason: BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x51c4e8 → packet2tree(data=0x606000000020 "", len=0x32)
[#1] 0x51b3cc → add_tree_ipv4(ip=0xcbcbcbcb, data=0x606000000020 "", len=0x32)
[#2] 0x5111e9 → process_raw_packets(pcap=0x616000000380)
[#3] 0x50fa14 → main(argc=0x4, argv=0x7fffffffe458)
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤ p len
$9 = 0x32
gef➤ p hl
$10 = 0x2c
gef➤ p hl+0xe
$11 = 0x3a
gef➤
The overflow is caused by the line tree.c:751, which doesn't check the ip_hl whether proper.
memcpy(&ip_hdr, (data + TCPR_ETH_H + hl), TCPR_IPV4_H);
node->family = AF_INET;
node->u.ip = ip_hdr.ip_src.s_addr;
proto = ip_hdr.ip_p;
hl += ip_hdr.ip_hl * 4;
As this poc shows, it made the ip_hl to be 0xb, which is bigger than the right one.
gef➤ p ip_hdr
$8 = {
ip_hl = 0xb,
ip_v = 0xc,
ip_tos = 0xcb,
ip_len = 0xcbcb,
ip_id = 0x32,
ip_off = 0x0,
ip_ttl = 0xcb,
ip_p = 0x1,
ip_sum = 0x0,
ip_src = {
s_addr = 0xcbcbcbcb
},
ip_dst = {
s_addr = 0xcbcbcbcb
}
}
Reopening to investigate
The patch for CVE-2018-20553 is also wrong.
This issue is an error of reading out of the heap buffer. When the program read structure vlan_hdr_t
, it doesn't check the relationship of length between vlan_hdr_t
and datalen
. The above poc can make 'vlan_hdr_t' larger than datalen
, which causes the read out of bound.
─
178 if ((size_t)datalen >= sizeof(eth_hdr_t) + l2_len) {
179 uint16_t ether_type = ntohs(((eth_hdr_t*)(pktdata + l2_len))->ether_type);
180
181 while (ether_type == ETHERTYPE_VLAN) {
182 vlan_hdr_t *vlan_hdr = (vlan_hdr_t *)(pktdata + l2_len);
// vlan_hdr=0x00007ffffffed9b8 → [...] → 0x0000000000000000
→ 183 ether_type = ntohs(vlan_hdr->vlan_len);
184 l2_len += 4;
185 if ((size_t)datalen < sizeof(vlan_hdr_t) + l2_len) {
186 l2_len = -1;
187 break;
188 }
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "tcpprep", stopped, reason: BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x528fa1 → get_l2len(pktdata=0x603000000010 "", datalen=0x11, datalink=0x1)
[#1] 0x529232 → get_ipv4(pktdata=0x603000000010 "", datalen=0x11, datalink=0x1, newbuff=0x7fffffffdf50)
[#2] 0x510461 → process_raw_packets(pcap=0x616000000380)
[#3] 0x50fa14 → main(argc=0x4, argv=0x7fffffffe508)
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤ p vlan_hdr
$16 = (vlan_hdr_t *) 0x603000000010
gef➤ p &(vlan_hdr->vlan_len) //notice: vlan_len is 2 bytes
$17 = (uint16_t *) 0x603000000020
gef➤
Fixed first issue in PR #609 and second issue was fixed in #584
Both tested in Ubuntu 18.04, 64bit, gcc 7.3.0, tcpreplay (master 2d87447). And
tcpprep -V
returnsTriggered by
./tcpprep --auto=bridge --pcap=$POC --cachefile=/dev/null
POC1
poc file: https://github.com/Marsman1996/pocs/blob/master/tcpreplay/poc15-packet2tree-heapoverflow
ASAN info:
POC2
poc file: https://github.com/Marsman1996/pocs/blob/master/tcpreplay/poc16-get_l2len-heapoverflow
ASAN info: