Skip to content

NTLMRelayX: Show client IP when realying successful #2012

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 26 additions & 40 deletions impacket/examples/ntlmrelayx/servers/httprelayserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,17 @@ def __init__(self,request, client_address, server):
try:
http.server.SimpleHTTPRequestHandler.__init__(self,request, client_address, server)
except Exception as e:
LOG.debug("Exception:", exc_info=True)
LOG.error(str(e))
LOG.debug("(HTTP): Exception:", exc_info=True)
LOG.error("(HTTP): %s" % str(e))

def handle_one_request(self):
try:
http.server.SimpleHTTPRequestHandler.handle_one_request(self)
except KeyboardInterrupt:
raise
except Exception as e:
LOG.debug("HTTPD(%s): Exception:" % self.server.server_address[1], exc_info=True)
LOG.error('HTTPD(%s): Exception in HTTP request handler: %s' % (self.server.server_address[1], e))
LOG.debug("(HTTP): Exception:", exc_info=True)
LOG.error('(HTTP): Exception in HTTP request handler: %s' % e)

def log_message(self, format, *args):
return
Expand Down Expand Up @@ -160,7 +160,7 @@ def strip_blob(self, proxy):
_, blob = typeX.split('NTLM')
token = base64.b64decode(blob.strip())
except Exception:
LOG.debug("Exception:", exc_info=True)
LOG.debug("(HTTP): Exception:", exc_info=True)
self.do_AUTHHEAD(message = b'NTLM', proxy=proxy)
else:
messageType = struct.unpack('<L',token[len('NTLMSSP\x00'):len('NTLMSSP\x00')+4])[0]
Expand All @@ -183,7 +183,7 @@ def do_OPTIONS(self):

def do_PROPFIND(self):

LOG.info('HTTPD(%s): Client requested path: %s' % (self.server.server_address[1], self.path.lower()))
LOG.info('(HTTP): Client requested path: %s' % self.path.lower())

proxy = False
if (".jpg" in self.path) or (".JPG" in self.path):
Expand Down Expand Up @@ -252,14 +252,14 @@ def do_GET(self):
self.do_SMBREDIRECT()
return

LOG.info('HTTPD(%s): Client requested path: %s' % (self.server.server_address[1], self.path.lower()))
LOG.info('(HTTP): Client requested path: %s' % self.path.lower())

# Serve WPAD if:
# - The client requests it
# - A WPAD host was provided in the command line options
# - The client has not exceeded the wpad_auth_num threshold yet
if self.path.lower() == '/wpad.dat' and self.server.config.serve_wpad and self.should_serve_wpad(self.client_address[0]):
LOG.info('HTTPD(%s): Serving PAC file to client %s' % (self.server.server_address[1], self.client_address[0]))
LOG.info('(HTTP): Serving PAC file to client %s' % self.client_address[0])
self.serve_wpad()
return

Expand Down Expand Up @@ -301,7 +301,7 @@ def do_ntlm_negotiate(self, token, proxy):
if self.challengeMessage is False:
return False
else:
LOG.error('Protocol Client for %s not found!' % self.target.scheme.upper())
LOG.error('(HTTP): Protocol Client for %s not found!' % self.target.scheme.upper())
return False

# Calculate auth
Expand Down Expand Up @@ -368,13 +368,11 @@ def do_local_auth(self, messageType, token, proxy):
self.server.config.target.reloadTargets(full_reload=True)
self.target = self.server.config.target.getTarget(identity=self.authUser)
else:
LOG.info("HTTPD(%s): Connection from %s@%s controlled, but there are no more targets left!" % (
self.server.server_address[1], self.authUser, self.client_address[0]))
LOG.info("(HTTP): Connection from %s@%s controlled, but there are no more targets left!" % (self.authUser, self.client_address[0]))
self.send_not_found()
return

LOG.info("HTTPD(%s): Connection from %s@%s controlled, attacking target %s://%s" % (
self.server.server_address[1], self.authUser, self.client_address[0], self.target.scheme, self.target.netloc))
LOG.info("(HTTP): Connection from %s@%s controlled, attacking target %s://%s" % (self.authUser, self.client_address[0], self.target.scheme, self.target.netloc))

self.relayToHost = True
self.do_REDIRECT()
Expand All @@ -388,31 +386,27 @@ def do_relay(self, messageType, token, proxy, content = None):
self.server.config.target.reloadTargets(full_reload=True)
self.target = self.server.config.target.getTarget(multiRelay=False)
else:
LOG.info("HTTPD(%s): Connection from %s controlled, but there are no more targets left!" % (
self.server.server_address[1], self.client_address[0]))
LOG.info("(HTTP): Connection from %s controlled, but there are no more targets left!" % self.client_address[0])
self.send_not_found()
return

LOG.info("HTTPD(%s): Connection from %s controlled, attacking target %s://%s" % (
self.server.server_address[1], self.client_address[0], self.target.scheme, self.target.netloc))
LOG.info("(HTTP): Connection from %s controlled, attacking target %s://%s" % (self.client_address[0], self.target.scheme, self.target.netloc))

try:
ntlm_negotiate_response = self.do_ntlm_negotiate(token, proxy=proxy)
except Exception as e:
LOG.error('HTTPD(%d): Exception while Negotiating NTLM with %s://%s: "%s"' % (self.server.server_address[1], self.target.scheme, self.target.netloc, str(e)))
LOG.error('(HTTP): Exception while Negotiating NTLM with %s://%s: "%s"' % (self.target.scheme, self.target.netloc, str(e)))
ntlm_negotiate_response = False

if not ntlm_negotiate_response:
# Connection failed
if self.server.config.disableMulti:
LOG.error('HTTPD(%s): Negotiating NTLM with %s://%s failed' % (self.server.server_address[1],
self.target.scheme, self.target.netloc))
LOG.error('(HTTP): Negotiating NTLM with %s://%s failed' % (self.target.scheme, self.target.netloc))
self.server.config.target.registerTarget(self.target)
self.send_not_found()
return
else:
LOG.error('HTTPD(%s): Negotiating NTLM with %s://%s failed. Skipping to next target' % (
self.server.server_address[1], self.target.scheme, self.target.netloc))
LOG.error('(HTTP): Negotiating NTLM with %s://%s failed. Skipping to next target' % (self.target.scheme, self.target.netloc))

self.server.config.target.registerTarget(self.target, gotUsername=self.authUser)
self.target = self.server.config.target.getTarget(identity=self.authUser)
Expand All @@ -422,13 +416,11 @@ def do_relay(self, messageType, token, proxy, content = None):
self.server.config.target.reloadTargets(full_reload=True)
self.target = self.server.config.target.getTarget(identity=self.authUser)
else:
LOG.info( "HTTPD(%s): Connection from %s@%s controlled, but there are no more targets left!" %
(self.server.server_address[1], self.authUser, self.client_address[0]))
LOG.info("(HTTP): Connection from %s@%s controlled, but there are no more targets left!" % (self.authUser, self.client_address[0]))
self.send_not_found()
return

LOG.info("HTTPD(%s): Connection from %s@%s controlled, attacking target %s://%s" % (self.server.server_address[1],
self.authUser, self.client_address[0], self.target.scheme, self.target.netloc))
LOG.info("(HTTP): Connection from %s@%s controlled, attacking target %s://%s" % (self.authUser, self.client_address[0], self.target.scheme, self.target.netloc))

self.do_REDIRECT()

Expand All @@ -441,8 +433,7 @@ def do_relay(self, messageType, token, proxy, content = None):
target = '%s://%s@%s' % (self.target.scheme, self.authUser.replace("/", '\\'), self.target.netloc)

if not self.do_ntlm_auth(token, authenticateMessage):
LOG.error("Authenticating against %s://%s as %s FAILED" % (self.target.scheme, self.target.netloc,
self.authUser))
LOG.error("(HTTP): Authenticating against %s://%s as %s FAILED" % (self.target.scheme, self.target.netloc, self.authUser))
if self.server.config.disableMulti:
self.send_not_found()
return
Expand All @@ -458,25 +449,22 @@ def do_relay(self, messageType, token, proxy, content = None):
self.server.config.target.reloadTargets(full_reload=True)
self.target = self.server.config.target.getTarget(identity=self.authUser)
else:
LOG.info("HTTPD(%s): Connection from %s@%s controlled, but there are no more targets left!" %
(self.server.server_address[1], self.authUser, self.client_address[0]))
LOG.info("(HTTP): Connection from %s@%s controlled, but there are no more targets left!" % (self.authUser, self.client_address[0]))
self.send_not_found()
return

self.send_not_found() # Stop relaying at first login fail, this matches the behavior of smbrelayserver

# Uncomment lines below to keep relaying after login failures
# LOG.info("HTTPD(%s): Connection from %s@%s controlled, attacking target %s://%s" % (self.server.server_address[1],
# self.authUser, self.client_address[0], self.target.scheme, self.target.netloc))
# LOG.info("(HTTP): Connection from %s@%s controlled, attacking target %s://%s" % (self.authUser, self.client_address[0], self.target.scheme, self.target.netloc))

# self.do_REDIRECT()
else:
# If it was an anonymous login, send 401
self.do_AUTHHEAD(b'NTLM', proxy=proxy)
else:
# Relay worked, do whatever we want here...
LOG.info("HTTPD(%s): Authenticating against %s://%s as %s SUCCEED" % (self.server.server_address[1],
self.target.scheme, self.target.netloc, self.authUser))
LOG.info("(HTTP): Authenticating connection from %s@%s against %s://%s SUCCEED" % (self.authUser, self.client_address[0], self.target.scheme, self.target.netloc))

ntlm_hash_data = outputToJohnFormat(self.challengeMessage['challenge'],
authenticateMessage['user_name'],
Expand All @@ -485,7 +473,7 @@ def do_relay(self, messageType, token, proxy, content = None):
self.client.sessionData['JOHN_OUTPUT'] = ntlm_hash_data

if self.server.config.dumpHashes is True:
LOG.info(ntlm_hash_data['hash_string'])
LOG.info("(HTTP): %s" % ntlm_hash_data['hash_string'])

if self.server.config.outputFile is not None:
writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'],
Expand All @@ -511,8 +499,7 @@ def do_relay(self, messageType, token, proxy, content = None):
self.server.config.target.reloadTargets(full_reload=True)
self.target = self.server.config.target.getTarget(identity=self.authUser)
else:
LOG.info("HTTPD(%s): Connection from %s@%s controlled, but there are no more targets left!" % (
self.server.server_address[1], self.authUser, self.client_address[0]))
LOG.info("(HTTP): Connection from %s@%s controlled, but there are no more targets left!" % (self.authUser, self.client_address[0]))
# Return Multi-Status status code to WebDAV servers
if self.command == "PROPFIND":
self.send_multi_status(content)
Expand All @@ -528,8 +515,7 @@ def do_relay(self, messageType, token, proxy, content = None):
return

# We have the next target, let's keep relaying...
LOG.info("HTTPD(%s): Connection from %s@%s controlled, attacking target %s://%s" % (self.server.server_address[1],
self.authUser, self.client_address[0], self.target.scheme, self.target.netloc))
LOG.info("(HTTP): Connection from %s@%s controlled, attacking target %s://%s" % (self.authUser, self.client_address[0], self.target.scheme, self.target.netloc))
self.do_REDIRECT()

def do_attack(self):
Expand All @@ -547,7 +533,7 @@ def do_attack(self):
self.authUser)
clientThread.start()
else:
LOG.error('HTTPD(%s): No attack configured for %s' % (self.server.server_address[1], self.target.scheme.upper()))
LOG.error('(HTTP): No attack configured for %s' % self.target.scheme.upper())

def __init__(self, config):
Thread.__init__(self)
Expand Down
28 changes: 14 additions & 14 deletions impacket/examples/ntlmrelayx/servers/rawrelayserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ def __init__(self, request, client_address, server):
self.server.config.target = TargetsProcessor(singleTarget='SMB://%s:445/' % client_address[0])
self.target = self.server.config.target.getTarget()
if self.target is None:
LOG.info("RAW: Received connection from %s, but there are no more targets left!" % client_address[0])
LOG.info("(RAW): Received connection from %s, but there are no more targets left!" % client_address[0])
return

LOG.info("RAW: Received connection from %s, attacking target %s://%s" % (client_address[0] ,self.target.scheme, self.target.netloc))
LOG.info("(RAW): Received connection from %s, attacking target %s://%s" % (client_address[0] ,self.target.scheme, self.target.netloc))

super().__init__(request, client_address, server)

Expand All @@ -79,7 +79,7 @@ def handle(self):

if not self.do_ntlm_negotiate(ntlm_negotiate):
# Connection failed
LOG.error('Negotiating NTLM with %s://%s failed. Skipping to next target',
LOG.error('(RAW): Negotiating NTLM with %s://%s failed. Skipping to next target',
self.target.scheme, self.target.netloc)
self.server.config.target.registerTarget(self.target)

Expand All @@ -101,12 +101,12 @@ def handle(self):
self.request.sendall(struct.pack('?', False))

if authenticateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_UNICODE:
LOG.error("Authenticating against %s://%s as %s\\%s FAILED" % (
LOG.error("(RAW): Authenticating against %s://%s as %s\\%s FAILED" % (
self.target.scheme, self.target.netloc,
authenticateMessage['domain_name'].decode('utf-16le'),
authenticateMessage['user_name'].decode('utf-16le')))
else:
LOG.error("Authenticating against %s://%s as %s\\%s FAILED" % (
LOG.error("(RAW): Authenticating against %s://%s as %s\\%s FAILED" % (
self.target.scheme, self.target.netloc,
authenticateMessage['domain_name'].decode('ascii'),
authenticateMessage['user_name'].decode('ascii')))
Expand All @@ -116,13 +116,13 @@ def handle(self):
self.request.sendall(struct.pack('?', True))

if authenticateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_UNICODE:
LOG.info("Authenticating against %s://%s as %s\\%s SUCCEED" % (
self.target.scheme, self.target.netloc, authenticateMessage['domain_name'].decode('utf-16le'),
authenticateMessage['user_name'].decode('utf-16le')))
LOG.info("(RAW): Authenticating connection from %s/%s@%s against %s://%s SUCCEED" % (
authenticateMessage['domain_name'].decode('utf-16le'), authenticateMessage['user_name'].decode('utf-16le'),
self.client_address[0], self.target.scheme, self.target.netloc))
else:
LOG.info("Authenticating against %s://%s as %s\\%s SUCCEED" % (
self.target.scheme, self.target.netloc, authenticateMessage['domain_name'].decode('ascii'),
authenticateMessage['user_name'].decode('ascii')))
LOG.info("(RAW): Authenticating connection from %s/%s@%s against %s://%s SUCCEED" % (
authenticateMessage['domain_name'].decode('ascii'), authenticateMessage['user_name'].decode('ascii'),
self.client_address[0], self.target.scheme, self.target.netloc))

ntlm_hash_data = outputToJohnFormat(self.challengeMessage['challenge'],
authenticateMessage['user_name'],
Expand All @@ -131,7 +131,7 @@ def handle(self):
self.client.sessionData['JOHN_OUTPUT'] = ntlm_hash_data

if self.server.config.dumpHashes is True:
LOG.info(ntlm_hash_data['hash_string'])
LOG.info("(RAW): %s" % ntlm_hash_data['hash_string'])

if self.server.config.outputFile is not None:
writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'],
Expand Down Expand Up @@ -162,7 +162,7 @@ def do_ntlm_negotiate(self, token):
if self.challengeMessage is False:
return False
else:
LOG.error('Protocol Client for %s not found!' % self.target.scheme.upper())
LOG.error('(RAW): Protocol Client for %s not found!' % self.target.scheme.upper())
return False

return True
Expand Down Expand Up @@ -198,7 +198,7 @@ def do_attack(self):
self.authUser)
clientThread.start()
else:
LOG.error('No attack configured for %s' % self.target.scheme.upper())
LOG.error('(RAW): No attack configured for %s' % self.target.scheme.upper())

def __init__(self, config):
Thread.__init__(self)
Expand Down
Loading