diff --git a/lib/attacks/intel_me/__init__.py b/lib/attacks/intel_me/__init__.py new file mode 100644 index 0000000..8f98586 --- /dev/null +++ b/lib/attacks/intel_me/__init__.py @@ -0,0 +1,67 @@ +import re +import socket + +import lib.settings + + +BANNER_REGEX = re.compile("{} {}".format(lib.settings.AMT_SERVER_REGEX, lib.settings.AMT_BANNER_REGEX)) + + +def _is_vuln(response): + if BANNER_REGEX.search(response) is not None: + return True + return False + + +def create_connection(host, port, proxy=None, resp_size=1024): + send_data = "GET / HTTP/1.1\r\n\r\n" + conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + conn.settimeout(10) + + #if proxy is None: + conn.connect((host, int(port))) + #else: + # data_list = proxy.split("://") + # conn.connect(()) + + conn.send(send_data) + response = conn.recv(resp_size) + conn.close() + return response + + +def intel_amt_main(host, proxy=None, verbose=False): + if proxy is not None: + lib.settings.logger.warning(lib.settings.set_color( + "proxies are not implemented yet, you will not be connected through your proxy...", level=30 + )) + + ip_address = socket.gethostbyname(host) + lib.settings.logger.info(lib.settings.set_color( + "checking for Intel ME AMT exploit on host '{}' IP address '{}'...".format(host, ip_address) + )) + for port in lib.settings.AMT_PORTS: + if verbose: + lib.settings.logger.debug(lib.settings.set_color( + "checking port '{}'...".format(port), level=10 + )) + + try: + resp = create_connection(ip_address, port, proxy=proxy) + + if _is_vuln(resp): + lib.settings.logger.info(lib.settings.set_color( + "host '{}' appears to be vulnerable to AMT exploit on port '{}'...".format(host, port) + )) + except socket.timeout: + lib.settings.logger.warning(lib.settings.set_color( + "host '{}' timed out on port {}, assuming not vulnerable and proceeding...".format(host, port), level=30 + )) + pass + except Exception as e: + lib.settings.logger.exception(lib.settings.set_color( + "caught exception '{}', assuming not vulnerable and proceeding...".format(e), level=50 + )) + + + diff --git a/lib/settings.py b/lib/settings.py index 74b25e4..2bd2da8 100644 --- a/lib/settings.py +++ b/lib/settings.py @@ -17,7 +17,7 @@ import bin.unzip_gecko # clone link CLONE = "https://github.com/ekultek/zeus-scanner.git" # current version -VERSION = "1.0.9.0dd" +VERSION = "1.0.10" # colors to output depending on the version VERSION_TYPE_COLORS = {"dev": 33, "stable": 92, "other": 30} # version string formatting @@ -46,6 +46,21 @@ DEFAULT_USER_AGENT = "Zeus-Scanner(v{})::Python->v{}.{}".format( URL_QUERY_REGEX = re.compile(r"(.*)[?|#](.*){1}\=(.*)") # regex to recognize a URL URL_REGEX = re.compile(r"((https?):((//)|(\\\\))+([\w\d:#@%/;$()~_?\+-=\\\.&](#!)?)*)") +AMT_SERVER_REGEX = re.compile("Server: Intel\(R\) Active Management Technology") +AMT_BANNER_REGEX = re.compile( + "((11\.(6\.(2(7\.(3(2(6[0-3]|[0-5][0-9])|[01][0-9]{2})|" + "[0-2]?[0-9]?[0-9]?[0-9])|[0-6])|[01]?[0-9])|5|0\.(2(5\." + "(3000|[0-2]?[0-9]?[0-9]?[0-9])|[0-4])|[01]?[0-9]))|10\.0\." + "(5(5\.[0-2]?[0-9]?[0-9]?[0-9]|[0-4])|[0-4]?[0-9])|9\.(5" + "\.(6(1\.(30(1[01]|0?[0-9])|[0-2]?[0-9]?[0-9]?[0-9])|0)|" + "[0-5]?[0-9])|1\.(4(1\.(30(2[0-3]|[01][0-9])|[0-2]?[0-9]?" + "[0-9]?[0-9])|0)|[0-3]?[0-9])|0)|8\.(1\.(7(1\.(3(60[0-7]|" + "[0-5][0-9]{2})|[0-2]?[0-9]?[0-9]?[0-9])|0)|[0-6]?[0-9])|0)" + "|7\.(1\.(9(1\.(3(2(7[01]|[0-6][0-9])|[01][0-9]{2})|[0-2]?" + "[0-9]?[0-9]?[0-9])|0)|[0-8]?[0-9])|0)|6\.(2\.(6(1\.(3(5(3[0-4]|" + "[0-2][[0-9])|[0-4][0-9]{2})|[0-2]?[0-9]?[0-9]?[0-9])|0)|[0-5]?" + "[0-9])|[01])))" +) # log path for the URL's that are found URL_LOG_PATH = "{}/log/url-log".format(os.getcwd()) # log path for port scans @@ -54,6 +69,8 @@ PORT_SCAN_LOG_PATH = "{}/log/scanner-log".format(os.getcwd()) SPIDER_LOG_PATH = "{}/log/blackwidow-log".format(os.getcwd()) # the current log file being used CURRENT_LOG_FILE_PATH = "{}/log".format(os.getcwd()) +# intel me amt ports +AMT_PORTS = (16992, 16993, 16994, 16995, 623, 664) # search engines that the application can use AUTHORIZED_SEARCH_ENGINES = { "aol": "http://aol.com", diff --git a/zeus.py b/zeus.py index 33b4942..da78548 100644 --- a/zeus.py +++ b/zeus.py @@ -13,7 +13,8 @@ from lib.attacks.sqlmap_scan.sqlmap_opts import SQLMAP_API_OPTIONS from lib.errors import InvalidInputProvided from lib.attacks import ( nmap_scan, - sqlmap_scan + sqlmap_scan, + intel_me ) from lib.settings import ( setup, @@ -62,6 +63,8 @@ if __name__ == "__main__": help="Run a Sqlmap SQLi scan on the discovered URL's") attacks.add_option("-p", "--port-scan", dest="runPortScan", action="store_true", help="Run a Nmap port scan on the discovered URL's") + attacks.add_option("-i", "--intel-check", dest="intelCheck", action="store_true", + help="Check if a URL's host is exploitable via Intel ME AMT (CVE-2017-5689)") attacks.add_option("--sqlmap-args", dest="sqlmapArguments", metavar="SQLMAP-ARGS", help="Pass the arguments to send to the sqlmap API within quotes & " "separated by a comma. IE 'dbms mysql, verbose 3, level 5'") @@ -258,7 +261,10 @@ if __name__ == "__main__": return retval - def __run_attacks(url, sqlmap=False, verbose=False, nmap=False, given_path=None, auto=False, batch=False): + def __run_attacks( + url, sqlmap=False, verbose=False, nmap=False, + intel=False, given_path=None, auto=False, batch=False + ): """ run the attacks if any are requested """ @@ -276,6 +282,9 @@ if __name__ == "__main__": elif nmap: url_ip_address = replace_http(url.strip()) return nmap_scan.perform_port_scan(url_ip_address, verbose=verbose) + elif intel: + url_ip_address = replace_http(url.strip()) + return intel_me.intel_amt_main(url_ip_address, proxy=proxy_to_use, verbose=verbose) else: pass else: @@ -305,11 +314,11 @@ if __name__ == "__main__": pass urls_to_use = get_latest_log_file(URL_LOG_PATH) - if opt.runSqliScan or opt.runPortScan: + if opt.runSqliScan or opt.runPortScan or opt.intelCheck: with open(urls_to_use) as urls: for url in urls.readlines(): - __run_attacks(url.strip(), sqlmap=opt.runSqliScan, nmap=opt.runPortScan, - given_path=opt.givenSearchPath, auto=opt.autoStartSqlmap, + __run_attacks(url.strip(), sqlmap=opt.runSqliScan, nmap=opt.runPortScan, intel=opt.intelCheck, + given_path=opt.givenSearchPath, auto=opt.autoStartSqlmap, verbose=opt.runInVerbose, batch=opt.runInBatch) # use a file full of dorks as the queries @@ -332,11 +341,11 @@ if __name__ == "__main__": pass urls_to_use = get_latest_log_file(URL_LOG_PATH) - if opt.runSqliScan or opt.runPortScan: + if opt.runSqliScan or opt.runPortScan or opt.intelCheck: with open(urls_to_use) as urls: for url in urls.readlines(): - __run_attacks(url.strip(), sqlmap=opt.runSqliScan, nmap=opt.runPortScan, - given_path=opt.givenSearchPath, auto=opt.autoStartSqlmap, + __run_attacks(url.strip(), sqlmap=opt.runSqliScan, nmap=opt.runPortScan, intel=opt.intelCheck, + given_path=opt.givenSearchPath, auto=opt.autoStartSqlmap, verbose=opt.runInVerbose, batch=opt.runInBatch) # use a random dork as the query @@ -355,11 +364,11 @@ if __name__ == "__main__": proxy=proxy_to_use, agent=agent_to_use ) urls_to_use = get_latest_log_file(URL_LOG_PATH) - if opt.runSqliScan or opt.runPortScan: + if opt.runSqliScan or opt.runPortScan or opt.intelCheck: with open(urls_to_use) as urls: for url in urls.readlines(): - __run_attacks(url.strip(), sqlmap=opt.runSqliScan, nmap=opt.runPortScan, - given_path=opt.givenSearchPath, auto=opt.autoStartSqlmap, + __run_attacks(url.strip(), sqlmap=opt.runSqliScan, nmap=opt.runPortScan, intel=opt.intelCheck, + given_path=opt.givenSearchPath, auto=opt.autoStartSqlmap, verbose=opt.runInVerbose, batch=opt.runInBatch) except Exception as e: logger.exception(set_color( @@ -386,11 +395,11 @@ if __name__ == "__main__": blackwidow.blackwidow_main(opt.spiderWebSite, agent=agent_to_use, proxy=proxy_to_use, verbose=opt.runInVerbose) urls_to_use = get_latest_log_file(SPIDER_LOG_PATH) - if opt.runSqliScan or opt.runPortScan: + if opt.runSqliScan or opt.runPortScan or opt.intelCheck: with open(urls_to_use) as urls: for url in urls.readlines(): - __run_attacks(url.strip(), sqlmap=opt.runSqliScan, nmap=opt.runPortScan, - given_path=opt.givenSearchPath, auto=opt.autoStartSqlmap, + __run_attacks(url.strip(), sqlmap=opt.runSqliScan, nmap=opt.runPortScan, intel=opt.intelCheck, + given_path=opt.givenSearchPath, auto=opt.autoStartSqlmap, verbose=opt.runInVerbose, batch=opt.runInBatch) else: