Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid memory access in do_checksum() #538

Closed
SegfaultMasters opened this issue Feb 12, 2019 · 3 comments
Closed

Invalid memory access in do_checksum() #538

SegfaultMasters opened this issue Feb 12, 2019 · 3 comments
Assignees
Labels

Comments

@SegfaultMasters
Copy link

Description - we observed that there is an Invalid memory access at do_checksum () in checksum.c .The same be triggered by sending a crafted pcap file to the tcpreplay-edit binary. It allows an attacker to cause Denial of Service (Segmentation fault) or possibly have unspecified other impact.

Command - tcpreplay-edit -r 80:84 -s 20 -b -C -m 1500 -P --oneatatime -i $INTERFACE $POC

POC - REPRODUCER

Debug -

GDB -

Program received signal SIGSEGV, Segmentation fault.
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x555500000000 
$rbx : 0x00005555557b7bb8 → 0x0000337330706e65 ("enp0s3"?)
$rcx : 0x3 
$rdx : 0xffffffffaa841df2
$rsp : 0x00007fffffffd930 → 0x0000000000000000
$rbp : 0x00007fffffffd990 → 0x00007fffffffd9d0 → 0x00007fffffffda70 → 0x00007fffffffdbc0 → 0x00007fffffffdd10 → 0x00007fffffffdd40 → 0x00007fffffffddd0 → 0x00007fffffffe210
$rsi : 0x3 
$rdi : 0x00005555557be20e → 0x0011323003000062 ("b"?)
$rip : 0x00005555555696dc → <do_checksum+524> movzx eax, WORD PTR [rax+0x6]
$r8 : 0x15 
$r9 : 0x00005555557be200 → 0x6567616d692f0000
$r10 : 0x00005555557b9700 → 0x0000000000000000
$r11 : 0x00007ffff78d6000 → <__fread_chk+0> push r13
$r12 : 0x00007ffff7bbb954 → 0x6800424d30314e45 ("EN10MB"?)
$r13 : 0x00007fffffffe2f0 → 0x000000000000000e
$r14 : 0x0 
$r15 : 0x0 
$eflags: [zero CARRY PARITY ADJUST sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000 
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffd930│+0x0000: 0x0000000000000000 ← $rsp
0x00007fffffffd938│+0x0008: 0x00000011557be239
0x00007fffffffd940│+0x0010: 0x00005555557be20e → 0x0011323003000062 ("b"?)
0x00007fffffffd948│+0x0018: 0x00005555557b86c0 → 0x0000000000000001
0x00007fffffffd950│+0x0020: 0x00007fffffffd980 → 0x00007fffffffd9d0 → 0x00007fffffffda70 → 0x00007fffffffdbc0 → 0x00007fffffffdd10 → 0x00007fffffffdd40 → 0x00007fffffffddd0
0x00007fffffffd958│+0x0028: 0x00000000aa841df2
0x00007fffffffd960│+0x0030: 0x0000000000000000
0x00007fffffffd968│+0x0038: 0x00005555557be20e → 0x0011323003000062 ("b"?)
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
0x5555555696d1 <do_checksum+513> add rax, rdx
0x5555555696d4 <do_checksum+516> mov QWORD PTR [rbp-0x18], rax
0x5555555696d8 <do_checksum+520> mov rax, QWORD PTR [rbp-0x18]
→ 0x5555555696dc <do_checksum+524> movzx eax, WORD PTR [rax+0x6]
0x5555555696e0 <do_checksum+528> test ax, ax
0x5555555696e3 <do_checksum+531> je 0x555555569939 <do_checksum+1129>
0x5555555696e9 <do_checksum+537> mov rax, QWORD PTR [rbp-0x18]
0x5555555696ed <do_checksum+541> mov WORD PTR [rax+0x6], 0x0
0x5555555696f3 <do_checksum+547> cmp QWORD PTR [rbp-0x28], 0x0
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── source:checksum.c+99 ────
94 break;
95 
96 case IPPROTO_UDP:
97 udp = (udp_hdr_t *)(data + ip_hl);
98 /* No need to recalculate UDP checksums if already 0 */
// udp=0x00007fffffffd978 → 0x0000555500000000
→ 99 if (udp->uh_sum == 0)
100 break;
101 udp->uh_sum = 0;
102 if (ipv6 != NULL) {
103 sum = do_checksum_math((uint16_t *)&ipv6->ip_src, 32);
104 } else {
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "tcpreplay-edit", stopped, reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x5555555696dc → do_checksum(tcpedit=0x5555557b86c0, data=0x5555557be20e "b", proto=0x11, len=0x557be239)
[#1] 0x555555565fbc → fix_ipv4_checksums(tcpedit=0x5555557b86c0, pkthdr=0x7fffffffdb50, ip_hdr=0x5555557be20e)
[#2] 0x555555564991 → tcpedit_packet(tcpedit=0x5555557b86c0, pkthdr=0x7fffffffdac0, pktdata=0x7fffffffdab0, direction=TCPR_DIR_C2S)
[#3] 0x55555555c589 → send_packets(ctx=0x5555557aa260, pcap=0x5555557ba860, idx=0x0)
[#4] 0x555555563169 → replay_file(ctx=0x5555557aa260, idx=0x0)
[#5] 0x555555562a1b → tcpr_replay_index(ctx=0x5555557aa260)
[#6] 0x555555562341 → tcpreplay_replay(ctx=0x5555557aa260)
[#7] 0x55555555f112 → main(argc=0x1, argv=0x7fffffffe360)
────────────────────────────────────────────────────────────────────────────────────────────

gef➤ p *udp
Cannot access memory at address 0x555500000000

@fklassen fklassen self-assigned this Feb 12, 2019
@fklassen fklassen added the bug label Feb 12, 2019
@carnil
Copy link

carnil commented Feb 17, 2019

CVE-2019-8381 was assigned for this issue.

@cbiedl
Copy link

cbiedl commented Mar 10, 2019

Unless I'm mistaken the problem is get_layer4_v6 may return zero, and does so as a length of 3 is way to short to extract any useful information. Fix then was to check for that situation and bail out. In other words:

--- a/src/tcpedit/checksum.c
+++ b/src/tcpedit/checksum.c
@@ -62,7 +62,10 @@ do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int len) {
         proto = get_ipv6_l4proto(ipv6, len);
         dbgx(3, "layer4 proto is 0x%hx", (uint16_t)proto);
 
-        ip_hl = (u_char*)get_layer4_v6(ipv6, len) - (u_char*)data;
+        u_char *layer = (u_char*)get_layer4_v6(ipv6, len);
+        if (layer == NULL)
+            return -1;
+        ip_hl = layer - (u_char*)data;
         dbgx(3, "ip_hl proto is 0x%d", ip_hl);
 
         len -= (ip_hl - TCPR_IPV6_H);

Result is:

(...)
DEBUG3 in tcpedit.c:tcpedit_packet() line 353: doing IPv4 checksum: needtorecalc=0
DEBUG3 in checksum.c:do_checksum() line 63: layer4 proto is 0x11

Fatal Error in send_packets.c:send_packets() line 553:
 Error editing packet #1: 

Did I miss something?

fklassen added a commit that referenced this issue Mar 12, 2019
Bugs #538 add check for packet length in do_checksum()
@fklassen
Copy link
Member

fixed in PR #548

GabrielGanne pushed a commit to GabrielGanne/tcpreplay that referenced this issue May 2, 2019
GabrielGanne added a commit to GabrielGanne/tcpreplay that referenced this issue May 9, 2019
prevent the function from interpreting as packet header if there is not
enough bytes.

Fixes appneta#538
Fixes appneta#556
fklassen added a commit that referenced this issue Jun 2, 2020
…ow_do_checksum

Bug #556 #538 guard HBO in checksum - fix as per @GabrielGanne
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants