Use-after-free in post_args() - tcpreplay 4.3.0 beta1
Loginsoft-2018-18408
October 30, 2018
CVE Number
CVE-2018-18408
CWE
CWE-416: Use After Free
Product Details
tcpflow is an open source program which is used to capture the data transmitted as part of TCP connections, it also stores the data for the protocol analysis and for debugging issue
URL:https://github.com/simsong/tcpflow/wiki
Vulnerable Versions
4.3.0-beta1 branch
Vulnerability Details
A use-after-free was discovered in the tcpbridge binary of Tcpreplay 4.3.0 beta1. The issue gets triggered in the function post_args() at tcpbridge.c, causing a denial of service or possibly unspecified other impact.
Synopsis
In condition if (memcmp(options.intf1_mac, "\00\00\00\00\00\00", ETHER_ADDR_LEN) == 0)
.The options.intf1_mac
has the value of {0,0,0,0,0,0} and ETHER_ADDR_LEN
is '0', which satisfies the condition and checks for the interface accessibility by comparing the packet value (sp) with NULL , if the packet value is NULL then there is problem with the interface and gives out the error. The same it checks for the MAC in the packet, if eth_buff value is NULL then it gives out an error. If the above two conditions are satisfied then the packet is sent to the function sendpacket_close()
where it closes the packet by freeing the memory where the packet is been stored by using the function safe_free()
from program "send_packets.c" which itself call the other function _our_safe_free()
from "utils.c". In section memcpy(options.intf1_mac, eth_buff, ETHER_ADDR_LEN)
the value of "eth_buff" is copied to "options.intf1_mac". Eth_buff is used to get mac from the packet using function sendpacket_get_hwaddr()
. When a packet is sent to the binary tcpbinary which doesnt contain a valid MAC, the function memcpy(options.intf1_mac, eth_buff, ETHER_ADDR_LEN)
memcpy tries to access "eth_buff" which in turn calls the function sendpacket_get_hwaddr()
which uses "sp" where the memory was freed, and tries to access it which resulted in a heap use-after-free vulnerability.
Analysis
219 memcpy(options.intf1_mac, eth_buff, ETHER_ADDR_LEN);
[ Legend: Modified register | Code | Heap | Stack | String ]
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- registers ----
$eax : 0x0
$ebx : 0xbffff700 -> 0x00000000
$ecx : 0x3d
$edx : 0x3c
$esp : 0xbffff1f0 -> 0x080aa480 -> 0xb50001f0 -> 0x316f6e65 -> 0x00000000
$ebp : 0xbffff6a8 -> 0xbffff6e8 -> 0x00000000
$esi : 0x0809fc20 -> 0x004d0028 ("("?)
$edi : 0xbffff690 -> 0xbffff6e8 -> 0x00000000
$eip : 0x0804e67b -> mov ebx, DWORD PTR [ebp-0x47c]
$eflags: [carry PARITY adjust zero SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0073 $ss: 0x007b $ds: 0x007b $es: 0x007b $fs: 0x0000 $gs: 0x0033
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ stack ----
0xbffff1f0|+0x0000: 0x080aa480 -> 0xb50001f0 -> 0x316f6e65 -> 0x00000000 0x41b58ab3
0xbffff204|+0x0014: 0xbffff230 -> 0x41b58ab3
0xbffff208|+0x0018: 0xbffff690 -> 0xbffff6e8 -> 0x00000000
0xbffff20c|+0x001c: 0xbffff79c -> 0x00000000
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ code:x86:32 ----
0x804e66d push DWORD PTR [ebp-0x480]
0x804e673 call 0x807f0a3
0x804e678 add esp, 0x10
-> 0x804e67b mov ebx, DWORD PTR [ebp-0x47c]
0x804e681 mov eax, ebx
0x804e683 shr eax, 0x3
0x804e686 add eax, 0x20000000
0x804e68b movzx edx, BYTE PTR [eax]
0x804e68e test dl, dl
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- source:tcpbridge.c+219 ----
214 if ((eth_buff = sendpacket_get_hwaddr(sp)) == NULL) {
215 warnx("Unable to get MAC address: %s", sendpacket_geterr(sp));
216 err(-1, "Please consult the man page for using the -M option.");
217 }
218 sendpacket_close(sp);
// eth_buff=0xbffff22c -> [...] -> 0x6d3acab8
-> 219 memcpy(options.intf1_mac, eth_buff, ETHER_ADDR_LEN);
220 }
221
222 if (memcmp(options.intf2_mac, "\00\00\00\00\00\00", ETHER_ADDR_LEN) == 0) {
223 if ((sp = sendpacket_open(options.intf2, ebuf, TCPR_DIR_S2C, SP_TYPE_NONE, NULL)) == NULL)
224 errx(-1, "Unable to open interface %s: %s", options.intf2, ebuf);
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- threads ----
[#0] Id 1, Name: "tcpbridge", stopped, reason: SINGLE STEP
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ trace ----
[#0] 0x804e67b->post_args(argc=0x0, argv=0xbffff79c)
[#1] 0x804d48b->main(argc=0x0, argv=0xbffff79c)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
gef> p sp
$6 = (sendpacket_t *) 0xb4203680
gef> x sp
0xb4203680: 2
gef> p/d options.intf1_mac
$7 = {0, 0, 0, 0, 0, 0}
gef> ptype eth_buff
type = struct tcpr_ether_addr {
uint8_t ether_addr_octet[6];
} *
gef> x/9i $pc
=> 0x804e67b : mov ebx,DWORD PTR [ebp-0x47c]
0x804e681 : mov eax,ebx
0x804e683 : shr eax,0x3
0x804e686 : add eax,0x20000000
0x804e68b : movzx edx,BYTE PTR [eax]
0x804e68e : test dl,dl
0x804e690 : setne cl
0x804e693 : mov eax,ebx
0x804e695 : and eax,0x7
gef> i r
eax 0x0 0x0
ecx 0x3d 0x3d
edx 0x3c 0x3c
ebx 0xbffff700 0xbffff700
esp 0xbffff1f0 0xbffff1f0
ebp 0xbffff6a8 0xbffff6a8
esi 0x809fc20 0x809fc20
edi 0xbffff690 0xbffff690
eip 0x804e67b 0x804e67b
eflags 0x286 [ PF SF IF ]
cs 0x73 0x73
ss 0x7b 0x7b
ds 0x7b 0x7b
es 0x7b 0x7b
fs 0x0 0x0
gs 0x33 0x33
}
ASAN Output
==11084==ERROR: AddressSanitizer: heap-use-after-free on address 0xb4203b38 at pc 0x0804e6e3 bp 0xbffff1d8 sp 0xbffff1c8
READ of size 6 at 0xb4203b38 thread T0
#0 0x804e6e2 in post_args /home/ACETEAM/tcpreplay/src/tcpbridge.c:219
#1 0x804d48a in main /home/ACETEAM/tcpreplay/src/tcpbridge.c:72
#2 0xb7832636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)
#3 0x804a955 (/usr/local/bin/tcpbridge+0x804a955)
0xb4203b38 is located 1208 bytes inside of 1240-byte region [0xb4203680,0xb4203b58)
freed by thread T0 here:
#0 0xb7acda84 in free (/usr/lib/i386-linux-gnu/libasan.so.2+0x96a84)
-> #1 0x807b714 in _our_safe_free /home/ACETEAM/tcpreplay/src/common/utils.c:118
#2 0x807f34e in sendpacket_close /home/ACETEAM/tcpreplay/src/common/sendpacket.c:636
#3 0x804e677 in post_args /home/ACETEAM/tcpreplay/src/tcpbridge.c:218
#4 0x804d48a in main /home/ACETEAM/tcpreplay/src/tcpbridge.c:72
#5 0xb7832636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)
previously allocated by thread T0 here:
#0 0xb7acddee in malloc (/usr/lib/i386-linux-gnu/libasan.so.2+0x96dee)
#1 0x807b4b0 in _our_safe_malloc /home/ACETEAM/tcpreplay/src/common/utils.c:50
#2 0x807ff10 in sendpacket_open_pf /home/ACETEAM/tcpreplay/src/common/sendpacket.c:956
#3 0x807e932 in sendpacket_open /home/ACETEAM/tcpreplay/src/common/sendpacket.c:523
#4 0x804e4f3 in post_args /home/ACETEAM/tcpreplay/src/tcpbridge.c:211
#5 0x804d48a in main /home/ACETEAM/tcpreplay/src/tcpbridge.c:72
#6 0xb7832636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)
SUMMARY: AddressSanitizer: heap-use-after-free /home/ACETEAM/tcpreplay/src/tcpbridge.c:219 post_args
Shadow bytes around the buggy address:
0x36840710: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x36840720: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x36840730: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x36840740: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x36840750: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x36840760: fd fd fd fd fd fd fd[fd]fd fd fd fa fa fa fa fa
0x36840770: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x36840780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x36840790: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x368407a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x368407b0: 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
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
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
==11084==ABORTING
Proof of Concept
tcpbridge --intf1=NETWORKINTERFACE
--inft1 = Primary interface (listen in uni-directional mode). This option may appear up to 1 times.
Timeline
Vendor Disclosure: 2018-10-02
Public Disclosure: 2018-10-03
Credit
Discovered by ACE Team - Loginsoft