The VPN software tinc is affected by a buffer overflow in a protocol parser, which results in a memory corruption and possibly a code execution. An attacker might trigger this vulnerability from a remote side via the network. Triggering this vulnerability requires being a known and authenticated peer in order to speak the so-called meta protocol.
CVE-2013-1428 was assigned to this vulnerability.
The vulnerability is known to be present in tinc version 1.1-pre6 and 1.0.19. Other versions might be affected as well. Version 1.0.19 is the default version on Ubuntu Linux 12.10 and is available in the FreeBSD ports collection.
The vulnerability is fixed in tinc versions 1.0.21 and 1.1pre7. It is recommended to upgrade existing installations.
In net_packet.c, the function receive_tcppacket()
declares a stack-local structure and this structure contains a buffer of 1661 elements. The function uses memcpy()
to copy data from a helper buffer. This helper buffer contains network data and might become larger than the destination buffer. If an attacker sends a specially crafted packet, he might overwrite memory beyond the buffer boundaries.
Net.h:
typedef struct vpn_packet_t { length_t len; /* the actual number of bytes in the `data' field */ int priority; /* priority or TOS */ uint32_t seqno; /* 32 bits sequence number (network byte order of course) */ uint8_t data[MAXSIZE]; // auditor remark: MAXSIZE == 1661 } vpn_packet_t;
Net_packet.c:
void receive_tcppacket(connection_t *c, const char *buffer, int len) { vpn_packet_t outpkt; outpkt.len = len; if(c->options & OPTION_TCPONLY) outpkt.priority = 0; else outpkt.priority = -1; // auditor remark: len > outpkt.data[MAXSIZE] ? memcpy(outpkt.data, buffer, len); receive_packet(c->node, &outpkt); }
Meta.c:
bool receive_meta(connection_t *c) { int inlen; char inbuf[MAXBUFSIZE]; // MAXSIZE +128 char *bufp = inbuf, *endp; [...] inlen = recv(c->socket, inbuf, sizeof inbuf - c->inbuf.len, 0); [...] do { [...] while(c->inbuf.len) { /* Are we receiving a TCPpacket? */ if(c->tcplen) { char *tcpbuffer = buffer_read(&c->inbuf, c->tcplen); if(!tcpbuffer) break; if(!c->node) { [...] } else { if(c->allow_request == ALL) { receive_tcppacket(c, tcpbuffer, c->tcplen); } [...] } c->tcplen = 0; } [...] } } while(inlen); return true; }
According to receive_meta()
, it is required that all meta protocol commands are enabled for a client in order to call receive_tcppacket()
. These commands are enabled, if the is client successfully authenticated.
This python script mocks the authentication procedure and overflows the buffer afterwards, which results in a memory corruption as shown below.
Linux:
$ sudo /usr/sbin/tincd -D -d 5 -c /usr/local/etc/tinc/testnet/ tincd 1.0.19 (Jun 29 2012 14:10:44) starting, debug level 1 /dev/net/tun is a Linux tun/tap device (tun mode) Unconfigured tinc-up script, please edit! Listening on 0.0.0.0 port 655 Listening on :: port 655 Ready Connection from 10.0.0.123 port 44645 Connection with testnode2 (10.0.0.123 port 44645) activated *** buffer overflow detected ***: /usr/sbin/tincd terminated ======= Backtrace: ========= /lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x65)[0xb749f065] /lib/i386-linux-gnu/libc.so.6(+0x102e1a)[0xb749de1a] /usr/sbin/tincd[0x804f42b] /usr/sbin/tincd[0x804e12f] /usr/sbin/tincd[0x804ec22] /usr/sbin/tincd[0x804b71c] /lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb73b44d3] /usr/sbin/tincd[0x804b8b9] ======= Memory map: ======== 08048000-08069000 r-xp 00000000 08:01 308865 /usr/sbin/tincd 08069000-0806a000 r--p 00020000 08:01 308865 /usr/sbin/tincd 0806a000-0806b000 rw-p 00021000 08:01 308865 /usr/sbin/tincd 0806b000-080dc000 rw-p 00000000 00:00 0 096c6000-096e7000 rw-p 00000000 00:00 0 [heap] b7369000-b7385000 r-xp 00000000 08:01 132074 /lib/i386-linux-gnu/libgcc_s.so.1 b7385000-b7386000 r--p 0001b000 08:01 132074 /lib/i386-linux-gnu/libgcc_s.so.1 b7386000-b7387000 rw-p 0001c000 08:01 132074 /lib/i386-linux-gnu/libgcc_s.so.1 b739a000-b739b000 rw-p 00000000 00:00 0 b739b000-b753e000 r-xp 00000000 08:01 132049 /lib/i386-linux-gnu/libc-2.15.so b753e000-b753f000 ---p 001a3000 08:01 132049 /lib/i386-linux-gnu/libc-2.15.so b753f000-b7541000 r--p 001a3000 08:01 132049 /lib/i386-linux-gnu/libc-2.15.so b7541000-b7542000 rw-p 001a5000 08:01 132049 /lib/i386-linux-gnu/libc-2.15.so b7542000-b7545000 rw-p 00000000 00:00 0 b7545000-b7548000 r-xp 00000000 08:01 132064 /lib/i386-linux-gnu/libdl-2.15.so b7548000-b7549000 r--p 00002000 08:01 132064 /lib/i386-linux-gnu/libdl-2.15.so b7549000-b754a000 rw-p 00003000 08:01 132064 /lib/i386-linux-gnu/libdl-2.15.so b754a000-b756b000 r-xp 00000000 08:01 304244 /usr/lib/i386-linux-gnu/liblzo2.so.2.0.0 b756b000-b756c000 r--p 00020000 08:01 304244 /usr/lib/i386-linux-gnu/liblzo2.so.2.0.0 b756c000-b756d000 rw-p 00021000 08:01 304244 /usr/lib/i386-linux-gnu/liblzo2.so.2.0.0 b756d000-b756e000 rw-p 00000000 00:00 0 b756e000-b7585000 r-xp 00000000 08:01 132183 /lib/i386-linux-gnu/libz.so.1.2.7 b7585000-b7586000 r--p 00016000 08:01 132183 /lib/i386-linux-gnu/libz.so.1.2.7 b7586000-b7587000 rw-p 00017000 08:01 132183 /lib/i386-linux-gnu/libz.so.1.2.7 b7587000-b7719000 r-xp 00000000 08:01 182182 /lib/i386-linux-gnu/libcrypto.so.1.0.0 b7719000-b7728000 r--p 00192000 08:01 182182 /lib/i386-linux-gnu/libcrypto.so.1.0.0 b7728000-b772f000 rw-p 001a1000 08:01 182182 /lib/i386-linux-gnu/libcrypto.so.1.0.0 b772f000-b7732000 rw-p 00000000 00:00 0 b7744000-b7747000 rw-p 00000000 00:00 0 b7747000-b7748000 r-xp 00000000 00:00 0 [vdso] b7748000-b7768000 r-xp 00000000 08:01 132027 /lib/i386-linux-gnu/ld-2.15.so b7768000-b7769000 r--p 0001f000 08:01 132027 /lib/i386-linux-gnu/ld-2.15.so b7769000-b776a000 rw-p 00020000 08:01 132027 /lib/i386-linux-gnu/ld-2.15.so bfded000-bfe0e000 rw-p 00000000 00:00 0 [stack]
FreeBSD:
root@freebsd:/root # tincd -D -d 5 -c /usr/local/etc/tinc/ tincd 1.0.19 (Apr 2 2013 18:11:46) starting, debug level 1 Cannot open config file /usr/local/etc/tinc//hosts/testnode3: No such file or directory /dev/tun0 is a Generic BSD tun device Listening on :: port 655 Listening on 0.0.0.0 port 655 Ready Connection from 10.0.0.123 port 48949 Connection with testnode2 (10.0.0.123 port 48949) activated Got fatal signal 10 (Bus error: 10) Not restarting.
Many thanks to Guus Sliepen and the Debian Security Team for fixing and coordinating this issue.
Martin Schobert schobert@sitsec.net
Over at Pentagrid, we provide pentesting services.