appneta/tcpreplay

[Bug] tcprewrite SEGV in src/tcpedit/plugins/dlt_utils.c:58 function tcpedit_dlt_getplugin

CCyb3rN1nj4 opened this issue · 2 comments

Describe the bug

tcprewrite SEGV in src/tcpedit/plugins/dlt_utils.c:58 function tcpedit_dlt_getplugin.

To Reproduce

Steps to reproduce the behavior:
1.Get the Tcpreplay source code and compile it.

git clone https://github.com/appneta/tcpreplay.git

export CFLAGS="-g -O0 -lpthread -fsanitize=address"
export CXXFLAGS="-g -O0 -lpthread -fsanitize=address"
export LDFLAGS="-fsanitize=address -fPIE"

./configure --disable-shared 
make -j8
cd bin

2.Run Command:
POC:https://github.com/GGb0ndQAQ/POC/blob/main/tcpreplay/tcprewrite/poc1

./tcprewrite --dlt=enet  --enet-dmac=00:12:13:14:15:16,00:22:33:44:55:66 --enet-smac=00:12:13:14:15:16,00:22:33:44:55:66   -i ./poc1 -o /dev/null
AddressSanitizer:DEADLYSIGNAL
=================================================================
==763996==ERROR: AddressSanitizer: SEGV on unknown address 0x161514131208 (pc 0x55578a79a153 bp 0x7fffe92d3a80 sp 0x7fffe92d3a60 T0)
==763996==The signal is caused by a READ memory access.
    #0 0x55578a79a153 in tcpedit_dlt_getplugin plugins/dlt_utils.c:58
    #1 0x55578a799609 in tcpedit_dlt_proto plugins/dlt_plugins.c:326
    #2 0x55578a7abc32 in dlt_jnpr_ether_proto plugins/dlt_jnpr_ether/jnpr_ether.c:309
    #3 0x55578a7996b1 in tcpedit_dlt_proto plugins/dlt_plugins.c:331
    #4 0x55578a7871ae in tcpedit_packet /home/lzy/CarpetFuzz/oss/tcpreplay/src/tcpedit/tcpedit.c:96
    #5 0x55578a786673 in rewrite_packets /home/lzy/CarpetFuzz/oss/tcpreplay/src/tcprewrite.c:293
    #6 0x55578a785d24 in main /home/lzy/CarpetFuzz/oss/tcpreplay/src/tcprewrite.c:137
    #7 0x7f766e203564 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x28564)
    #8 0x55578a78322d in _start (/home/lzy/CarpetFuzz/oss/tcpreplay/build-g/bin/tcprewrite+0x1d22d)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV plugins/dlt_utils.c:58 in tcpedit_dlt_getplugin
==763996==ABORTING

gdbinfo

$ gdb --args ./tcprewrite --dlt=enet  --enet-dmac=00:12:13:14:15:16,00:22:33:44:55:66 --enet-smac=00:12:13:14:15:16,00:22:33:44:55:66   -i ./poc1  -o /dev/null
(gdb) r
Starting program: /home/lzy/CarpetFuzz/oss/tcpreplay/build-g/bin/tcprewrite --dlt=enet --enet-dmac=00:12:13:14:15:16,00:22:33:44:55:66 --enet-smac=00:12:13:14:15:16,00:22:33:44:55:66 -i ../../build/bin/poc1 -o /dev/null
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x0000555555588153 in tcpedit_dlt_getplugin (ctx=0x161514131200, dlt=1) at plugins/dlt_utils.c:58
58          ptr = ctx->plugins;
(gdb) bt
#0  0x0000555555588153 in tcpedit_dlt_getplugin (ctx=0x161514131200, dlt=1) at plugins/dlt_utils.c:58
#1  0x000055555558760a in tcpedit_dlt_proto (ctx=0x161514131200, dlt=1, packet=0x7ffff3fbea42 "", pktlen=-504) at plugins/dlt_plugins.c:326
#2  0x0000555555599c33 in dlt_jnpr_ether_proto (ctx=0x60b0000000f0, packet=0x7ffff3fbe800 "", pktlen=74) at plugins/dlt_jnpr_ether/jnpr_ether.c:309
#3  0x00005555555876b2 in tcpedit_dlt_proto (ctx=0x60b0000000f0, dlt=178, packet=0x7ffff3fbe800 "", pktlen=74) at plugins/dlt_plugins.c:331
#4  0x00005555555751af in tcpedit_packet (tcpedit=0x61d000000a80, pkthdr=0x7fffffffe020, pktdata=0x55555560d960 <pktdata_buff>, direction=TCPR_DIR_C2S) at tcpedit.c:96
#5  0x0000555555574674 in rewrite_packets (tcpedit_ctx=0x61d000000a80, pin=0x617000000080, pout=0x615000000300) at tcprewrite.c:293
#6  0x0000555555573d25 in main (argc=0, argv=0x7fffffffe228) at tcprewrite.c:137

     53  {
     54      tcpeditdlt_plugin_t *ptr;
     55  
     56      assert(ctx);
     57  
             // ctx=0x00007fffffffdd18  →  0x0000161514131200, ptr=0x00007fffffffdd28  →  [...]  →  0x000c00220000ac55
 →   58      ptr = ctx->plugins;
     59      if (ptr == NULL)
     60          return NULL;
     61  
     62      while (ptr->dlt != dlt && ptr->next != NULL) {
     63          ptr = ptr->next;
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "tcprewrite", stopped 0x555555588153 in tcpedit_dlt_getplugin (), reason: SIGSEGV
────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x555555588153 → tcpedit_dlt_getplugin(ctx=0x161514131200, dlt=0x1)
[#1] 0x55555558760a → tcpedit_dlt_proto(ctx=0x161514131200, dlt=0x1, packet=0x7ffff3fbea42 "", pktlen=0xfffffe08)
[#2] 0x555555599c33 → dlt_jnpr_ether_proto(ctx=0x60b0000000f0, packet=0x7ffff3fbe800 "", pktlen=0x4a)
[#3] 0x5555555876b2 → tcpedit_dlt_proto(ctx=0x60b0000000f0, dlt=0xb2, packet=0x7ffff3fbe800 "", pktlen=0x4a)
[#4] 0x5555555751af → tcpedit_packet(tcpedit=0x61d000000a80, pkthdr=0x7fffffffe040, pktdata=0x55555560d960 <pktdata_buff>, direction=TCPR_DIR_C2S)
[#5] 0x555555574674 → rewrite_packets(tcpedit_ctx=0x61d000000a80, pin=0x617000000080, pout=0x615000000300)
[#6] 0x555555573d25 → main(argc=0x0, argv=0x7fffffffe248)
─────────────────────────────────────────────────────────────────────────────────────────
gef➤  print ctx->plugins
Cannot access memory at address 0x161514131208

Code in function src/tcpedit/plugins/dlt_utils.c:58

/*
 * find a given plugin struct in the context for a given DLT.  Returns NULL on failure
 */
tcpeditdlt_plugin_t *
tcpedit_dlt_getplugin(tcpeditdlt_t *ctx, int dlt)
{
    tcpeditdlt_plugin_t *ptr;

    assert(ctx);

    ptr = ctx->plugins;        <-------------- line 58
    if (ptr == NULL)
        return NULL;

    while (ptr->dlt != dlt && ptr->next != NULL) {
        ptr = ptr->next;
    }

    if (ptr->dlt == dlt)
        return ptr;

    return NULL;
}

Environment

OS: Ubuntu 20.04.5 LTS
Compiler: gcc version 9.4.0
Tcpreplay Version: master commit 43693c4a92dda227a5134ae5e71a7247ae345323

IMPACT

Potentially causing DoS or Arbitrary Read

Fixed in PR #872