Heap Buffer Overflow blf_read_apptextmessage Function

May 22, 2023

CVE Number

CVE-2023-2854

Credits

Huascar Tejeda of Pentraze Cybersecurity

Summary

A heap buffer overflow vulnerability has been discovered in Wireshark’s g_strndup function, which could potentially lead to remote code execution.

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 lies within the blf_read_apptextmessage function (found in the blf.c file), which is used by the Wireshark BLF (Binary Logging Format) plugin. The Address Sanitizer (ASAN) and GDB backtrace revealed a heap-buffer-overflow when the g_strsplit_set function is called. This function splits the string on the specified delimiters and creates an array of tokens.

In the provided backtrace, g_strsplit_set is called with text and “;” as the input parameters. If this string is carefully crafted, it could lead to arbitrary code execution when the process attempts to read or write to a memory area it doesn’t own, which is typical behavior for a heap-buffer-overflow vulnerability.

Steps to reproduce:

Open the trigger file using a Wireshark binary compiled with the -DENABLE_ASAN option:

$ tshark -r trigger
=================================================================
==147490==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000311440 at pc 0x7ffff745be47 bp 0x7fffffffc730 sp 0x7fffffffbed8
READ of size 17 at 0x602000311440 thread T0
    #0 0x7ffff745be46 in __interceptor_strncpy ../../../../src/libsanitizer/asan/asan_interceptors.cpp:484
    #1 0x7fffdfd3982b in g_strndup (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x7382b)
    #2 0x7fffdfd3daba in g_strsplit_set (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x77aba)
    #3 0x7fffdfa5933f in blf_read_apptextmessage /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/blf.c:1646
    #4 0x7fffdfa5933f in blf_read_block /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/blf.c:1820
    #5 0x7fffdfa5a79f in blf_read /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/blf.c:1846
    #6 0x7fffdfb34583 in wtap_read /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/wtap.c:1555
    #7 0x55555558eb8f in process_cap_file_single_pass /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/tshark.c:3534
    #8 0x55555558eb8f in process_cap_file /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/tshark.c:3746
    #9 0x55555558eb8f in main /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/tshark.c:2260
    #10 0x7fffdf629d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #11 0x7fffdf629e3f in __libc_start_main_impl ../csu/libc-start.c:392
    #12 0x555555591754 in _start (/home/htejeda/fuzzing/wireshark/wireshark-4.0.5/build-asan/run/tshark+0x3d754)

0x602000311440 is located 0 bytes to the right of 16-byte region [0x602000311430,0x602000311440)
allocated by thread T0 here:
    #0 0x7ffff74b4a37 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
    #1 0x7fffdfa592c2 in blf_read_apptextmessage /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/blf.c:1637
    #2 0x7fffdfa592c2 in blf_read_block /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/blf.c:1820
    #3 0x7fffffffdd2f  ([stack]+0x1fd2f)
...
...

ASAN

=================================================================
==147490==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000311440 at pc 0x7ffff745be47 bp 0x7fffffffc730 sp 0x7fffffffbed8
READ of size 17 at 0x602000311440 thread T0
    #0 0x7ffff745be46 in __interceptor_strncpy ../../../../src/libsanitizer/asan/asan_interceptors.cpp:484
    #1 0x7fffdfd3982b in g_strndup (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x7382b)
    #2 0x7fffdfd3daba in g_strsplit_set (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x77aba)
    #3 0x7fffdfa5933f in blf_read_apptextmessage /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/blf.c:1646
    #4 0x7fffdfa5933f in blf_read_block /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/blf.c:1820
    #5 0x7fffdfa5a79f in blf_read /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/blf.c:1846
    #6 0x7fffdfb34583 in wtap_read /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/wtap.c:1555
    #7 0x55555558eb8f in process_cap_file_single_pass /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/tshark.c:3534
    #8 0x55555558eb8f in process_cap_file /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/tshark.c:3746
    #9 0x55555558eb8f in main /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/tshark.c:2260
    #10 0x7fffdf629d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #11 0x7fffdf629e3f in __libc_start_main_impl ../csu/libc-start.c:392
    #12 0x555555591754 in _start (/home/htejeda/fuzzing/wireshark/wireshark-4.0.5/build-asan/run/tshark+0x3d754)

0x602000311440 is located 0 bytes to the right of 16-byte region [0x602000311430,0x602000311440)
allocated by thread T0 here:
    #0 0x7ffff74b4a37 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
    #1 0x7fffdfa592c2 in blf_read_apptextmessage /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/blf.c:1637
    #2 0x7fffdfa592c2 in blf_read_block /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/blf.c:1820
    #3 0x7fffffffdd2f  ([stack]+0x1fd2f)

SUMMARY: AddressSanitizer: heap-buffer-overflow ../../../../src/libsanitizer/asan/asan_interceptors.cpp:484 in __interceptor_strncpy
Shadow bytes around the buggy address:
  0x0c048005a230: fa fa 00 03 fa fa 00 03 fa fa 00 fa fa fa 00 02
  0x0c048005a240: fa fa 00 fa fa fa 00 00 fa fa 00 00 fa fa fd fa
  0x0c048005a250: fa fa fd fa fa fa fd fa fa fa fd fd fa fa fd fd
  0x0c048005a260: fa fa 00 05 fa fa fd fd fa fa 00 05 fa fa 00 00
  0x0c048005a270: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00
=>0x0c048005a280: fa fa 00 00 fa fa 00 00[fa]fa 01 fa fa fa fa fa
  0x0c048005a290: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c048005a2a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c048005a2b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c048005a2c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c048005a2d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
  Shadow gap:              cc
==147490==ABORTING

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

Register info:
   rax - 0x0000000000000000 (0)
   rbx - 0x00007ffff72d5a80 (140737340332672)
   rcx - 0x00007fffdf696a7c (140736941615740)
   rdx - 0x0000000000000006 (6)
   rsi - 0x0000000000024022 (147490)
   rdi - 0x0000000000024022 (147490)
   rbp - 0x0000000000024022 (0x24022)
   rsp - 0x00007fffffffaf00 (0x7fffffffaf00)
    r8 - 0x00007fffffffafd0 (140737488334800)
    r9 - 0x0000000000000000 (0)
   r10 - 0x0000000000000008 (8)
   r11 - 0x0000000000000246 (582)
   r12 - 0x0000000000000006 (6)
   r13 - 0x0000000000000016 (22)
   r14 - 0x00007fffd6670000 (140736790462464)
   r15 - 0x0000000000010000 (65536)
   rip - 0x00007fffdf696a7c (0x7fffdf696a7c <__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)

GDB Backtrace

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

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

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

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

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

#5  0x00007ffff74d26f2 in __sanitizer::Abort (/lib/x86_64-linux-gnu/libasan.so.6)
                       at ../../../../src/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp:151

#6  0x00007ffff74de2ac in __sanitizer::Die (/lib/x86_64-linux-gnu/libasan.so.6)
                       at ../../../../src/libsanitizer/sanitizer_common/sanitizer_termination.cpp:58

#7  0x00007ffff74bd75c in __asan::ScopedInErrorReport::~ScopedInErrorReport (/lib/x86_64-linux-gnu/libasan.so.6)
                       at ../../../../src/libsanitizer/asan/asan_report.cpp:190

#8  0x00007ffff74bcff5 in __asan::ReportGenericError (/lib/x86_64-linux-gnu/libasan.so.6)
                       at ../../../../src/libsanitizer/asan/asan_report.cpp:478

#9  0x00007ffff745be66 in __interceptor_strncpy (/lib/x86_64-linux-gnu/libasan.so.6)
                       at ../../../../src/libsanitizer/asan/asan_interceptors.cpp:484

#10 0x00007fffdfd3982c in g_strndup (/lib/x86_64-linux-gnu/libglib-2.0.so.0)
#11 0x00007fffdfd3dabb in g_strsplit_set (/lib/x86_64-linux-gnu/libglib-2.0.so.0)
#12 0x00007fffdfa59340 in blf_read_apptextmessage (/home/htejeda/fuzzing/wireshark/wireshark-4.0.5/build-asan/run/libwiretap.so.13)
                       ????: gboolean blf_read_apptextmessage(timestamp = (guint64)<optimized out>, object_length = (gint64)<optimized out>, data_start = (gint64)<optimized out>, block_start = (gint64)0, err_info = (gchar **)0x7fffffffd320, err = (int *)0x7fffffffd030, params = (blf_params_t *)0x7fffffffcd30) {
                       ||||:
                       ||||: /* Local reference: gchar ** tokens = <optimized out>; */
                       ||||: /* Local reference: gchar * text = 0x602000311430 ";3eff582ae\t5148b\002\021"; */
                       1644: 
                       1645:     /* returns a NULL terminated array of NULL terminates strings */
                       1646:     gchar **tokens = g_strsplit_set(text, ";", -1);
                       ||||:
                       ----: }
                       at /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/blf.c:1646

#13 0x00007fffdfa59340 in blf_read_block (/home/htejeda/fuzzing/wireshark/wireshark-4.0.5/build-asan/run/libwiretap.so.13)
                       1693: gboolean blf_read_block(params = (blf_params_t *)0x7fffffffcd30, start_pos = (gint64)0, err = (int *)0x7fffffffd030, err_info = (gchar **)0x7fffffffd320) {
                       ||||:
                       ||||: /* Local reference: blf_params_t * params = 0x7fffffffcd30; */
                       ||||: /* Local reference: int * err = 0x7fffffffd030; */
                       ||||: /* Local reference: gchar ** err_info = 0x7fffffffd320; */
                       ||||: /* Local reference: gint64 start_pos = 0; */
                       1818: 
                       1819:         case BLF_OBJTYPE_APP_TEXT:
                       1820:             if (!blf_read_apptextmessage(params, err, err_info, start_pos, start_pos + header.header_length, header.object_length, timestamp)) {
                       ||||:
                       ----: }
                       at /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/blf.c:1820

#14 0x00007fffdfa5a7a0 in blf_read (/home/htejeda/fuzzing/wireshark/wireshark-4.0.5/build-asan/run/libwiretap.so.13)
                       1837: gboolean blf_read(wth = (wtap *)<optimized out>, rec = (wtap_rec *)<optimized out>, buf = (Buffer *)<optimized out>, err = (int *)<optimized out>, err_info = (gchar **)<optimized out>, data_offset = (gint64 *)0x7fffffffd3c0) {
                       ||||:
                       ||||: /* Local reference: wtap * wth = <optimized out>; */
                       ||||: /* Local reference: int * err = <optimized out>; */
                       ||||: /* Local reference: gchar ** err_info = <optimized out>; */
                       1844:     blf_tmp.blf_data = (blf_t *)wth->priv;
                       1845: 
                       1846:     if (!blf_read_block(&blf_tmp, blf_tmp.blf_data->current_real_seek_pos, err, err_info)) {
                       ||||:
                       ----: }
                       at /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/blf.c:1846

#15 0x00007fffdfb34584 in wtap_read (/home/htejeda/fuzzing/wireshark/wireshark-4.0.5/build-asan/run/libwiretap.so.13)
                       1545: gboolean wtap_read(wth = (wtap *)0x60f000001030, rec = (wtap_rec *)0x7fffffffdd30, buf = (Buffer *)0x7fffffffd4a0, err = (int *)0x7fffffffd030, err_info = (gchar **)0x7fffffffd320, offset = (gint64 *)0x7fffffffd3c0) {
                       ||||:
                       ||||: /* Local reference: int * err = 0x7fffffffd030; */
                       ||||: /* Local reference: gchar ** err_info = 0x7fffffffd320; */
                       ||||: /* Local reference: wtap * wth = 0x60f000001030; */
                       ||||: /* Local reference: wtap_rec * rec = 0x7fffffffdd30; */
                       ||||: /* Local reference: Buffer * buf = 0x7fffffffd4a0; */
                       ||||: /* Local reference: gint64 * offset = 0x7fffffffd3c0; */
                       1553: 	*err = 0;
                       1554: 	*err_info = NULL;
                       1555: 	if (!wth->subtype_read(wth, rec, buf, err, err_info, offset)) {
                       ||||:
                       ----: }
                       at /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/wiretap/wtap.c:1555

#16 0x000055555558eb90 in process_cap_file_single_pass (/home/htejeda/fuzzing/wireshark/wireshark-4.0.5/build-asan/run/tshark)
                       ????: pass_status_t process_cap_file_single_pass(cf = (capture_file *)0x55555563d000 <cfile>, err_framenum = (volatile guint32 *)0x7fffffffd050, err_info = (gchar **)0x7fffffffd320, err = (int *)0x7fffffffd030, max_write_packet_count = (int)0, max_byte_count = (gint64)0, max_packet_count = (int)0, pdh = (wtap_dumper *)0x0) {
                       ||||:
                       ||||: /* Local reference: int * err = 0x7fffffffd030; */
                       ||||: /* Local reference: capture_file * cf = 0x55555563d000 <cfile>; */
                       ||||: /* Local reference: gchar ** err_info = 0x7fffffffd320; */
                       3532: 
                       3533:     *err = 0;
                       3534:     while (wtap_read(cf->provider.wth, &rec, &buf, err, err_info, &data_offset)) {
                       ||||:
                       ----: }
                       at /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/tshark.c:3534

#17 0x000055555558eb90 in process_cap_file (/home/htejeda/fuzzing/wireshark/wireshark-4.0.5/build-asan/run/tshark)
                       ????: process_file_status_t process_cap_file(cf = (capture_file *)0x55555563d000 <cfile>, max_write_packet_count = (int)0, max_byte_count = (gint64)0, max_packet_count = (int)0, out_file_name_res = (gboolean)0, out_file_type = (int)0, save_file = (char *)0x0) {
                       ||||:
                       ||||: /* Local reference: pass_status_t first_pass_status = PASS_SUCCEEDED; */
                       ||||: /* Local reference: pass_status_t second_pass_status = <optimized out>; */
                       ||||: /* Local reference: wtap_dumper * pdh = 0x0; */
                       ||||: /* Local reference: capture_file * cf = 0x55555563d000 <cfile>; */
                       3744: 
                       3745:         first_pass_status = PASS_SUCCEEDED; /* There is no first pass */
                       3746:         second_pass_status = process_cap_file_single_pass(cf, pdh,
                       ||||:
                       ----: }
                       at /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/tshark.c:3746

#18 0x000055555558eb90 in main (/home/htejeda/fuzzing/wireshark/wireshark-4.0.5/build-asan/run/tshark)
                        789: int main(argc = (int)<optimized out>, argv = (char **)<optimized out>) {
                       ||||:
                       2258:         ws_debug("tshark: invoking process_cap_file() to process the packets");
                       2259:         TRY {
                       2260:             status = process_cap_file(&cfile, output_file_name, out_file_type, out_file_name_res,
                       ||||:
                       ----: }
                       at /home/htejeda/fuzzing/wireshark/wireshark-4.0.5/tshark.c:2260

Services

Penetration Testing

Proactive assessment using tactics, techniques, and procedures of actual attackers to identify security flaws, incorrect configurations, and vulnerabilities.

Learn more

Application Security Testing

Comprehensive application protection, ensuring robust security throughout the entire software development lifecycle.

Learn more

Red Team Exercises

Simulate and emulate advanced cyber attacks to pinpoint vulnerabilities and test your organization's defense mechanisms, ensuring robust resilience against real-world threats.

Learn more

Vulnerability Management

Proactive process to identify, prioritize, and address security vulnerabilities in systems and software, enhancing an organization's defense against evolving cyber threats.

Learn more