Bug Description

Vde (virtual distributed ethernet) is an ethernet compliant virtual network that can be spawned over a set of physical computers over the internet ... (see vde project). The vde_plug (at least on ubuntu hardy) contains a bug, that is triggered when a certain amount of encapsulated ether frame data is sent to the plug in a specially timed manner. When the input buffer is filled just with a single byte, vde_plug uses also the first byte after the end of data, thus constructing an invalid frame length. Depending on frame length, just one byte or the complete buffer content is discarded, thus leading to lost single byte or complete frame content. Code from vde_plug.c:

... void splitpacket(const unsigned char *buf,int size,VDECONN *conn) { .... while (size > 0) { rnx=(buf[0]<<8)+buf[1]; size-=2;

Trivial but Useless Exploitation

The bug can be trivially exploited when sending ether frames to the plug (data), but this case is not very interesting :

_vdeTest_switchDir="$(mktemp -d)/sock" vde_switch -sock "${_vdeTest_switchDir}" -mod 0600 -tap vdetesttap < /dev/null & socat TCP4-LISTEN:5555,reuseaddr=1,fork=1 "EXEC:vde_plug -m 0600 ${_vdeTest_switchDir}" & ip link set vdetesttap up ip addr add 10.255.254.1/24 dev vdetesttap (while true; do cat Simple3FrameExample; sleep 1; done) | socat TCP4:127.0.0.1:5555 -

Simple3FrameExample just contains 3 ethernet frames, but due to loss of one byte, the 3rd frame is misinterpreted and splitted into two other frames. Result:

# tcpdump -i vdetesttap -ee -nn -s0 -vv 19:07:32.711804 01:23:45:67:89:ab > ff:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 1022: IP0 bad-hlen 0 19:07:32.720253 01:23:45:67:89:ab > ff:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 1021: IP0 bad-hlen 0 19:07:32.726796 23:45:67:89:ab:08 > ff:ff:ff:ff:ff:01, 802.3, length 256: LLC, dsap Null (0x00) Individual, ssap Null (0x00) Command, ctrl 0x0000: Information, send seq 0, rcv seq 0, Flags [Command], length 242 19:07:32.727414 41:41:41:41:41:41 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: arp who-has 10.255.254.2 tell 10.255.254.1

The test data is composed in such a way, that the first 2 frames fill up 0x7ff bytes of the 0x800 byte buffer. The byte at 0x7ff is the first length byte of the 3rd frame. When the test data is sent in one rush, the first two frames are read correctly, the first length byte is combined with one byte after the buffer (buffer overread) and discarded. The second length byte of the 3rd frame is then combined with the first byte of the destination mac address and used as length of the injected frames 3 and 4 (frame shift error). In my opinion, this usecase is not very interesting, since one would have to have access to the vde link first, so one can send any packet anyway.

Complex Exploitation

Of much greater use would be exploitation from inside a virtualized host or even via network just by sending packets, but that until now I did not manage to complete a POC. The idea: Try to send packets that have a sum size of 0x7ff bytes and add another packet that contains a spacer plus the encoded vde ether frames. The spacer can be composed of zeros only, which will make vde_plug skip the data in 2-byte groups until reaching a valid length. The program UdpSendTest.c tries to create such data, but does not succeed. I have not checked the cause of failure, but it might be one of the following:

References

Last modified 20171228
Contact e-mail: me (%) halfdog.net