Coverage for /root/GitHubProjects/impacket/impacket/examples/ntlmrelayx/clients/httprelayclient.py : 23%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved.
2#
3# This software is provided under under a slightly modified version
4# of the Apache Software License. See the accompanying LICENSE file
5# for more information.
6#
7# HTTP Protocol Client
8#
9# Author:
10# Dirk-jan Mollema / Fox-IT (https://www.fox-it.com)
11# Alberto Solino (@agsolino)
12#
13# Description:
14# HTTP(s) client for relaying NTLMSSP authentication to webservers
15#
16import re
17import ssl
18try:
19 from http.client import HTTPConnection, HTTPSConnection, ResponseNotReady
20except ImportError:
21 from httplib import HTTPConnection, HTTPSConnection, ResponseNotReady
22import base64
24from struct import unpack
25from impacket import LOG
26from impacket.examples.ntlmrelayx.clients import ProtocolClient
27from impacket.nt_errors import STATUS_SUCCESS, STATUS_ACCESS_DENIED
28from impacket.ntlm import NTLMAuthChallenge
29from impacket.spnego import SPNEGO_NegTokenResp
31PROTOCOL_CLIENT_CLASSES = ["HTTPRelayClient","HTTPSRelayClient"]
33class HTTPRelayClient(ProtocolClient):
34 PLUGIN_NAME = "HTTP"
36 def __init__(self, serverConfig, target, targetPort = 80, extendedSecurity=True ):
37 ProtocolClient.__init__(self, serverConfig, target, targetPort, extendedSecurity)
38 self.extendedSecurity = extendedSecurity
39 self.negotiateMessage = None
40 self.authenticateMessageBlob = None
41 self.server = None
43 def initConnection(self):
44 self.session = HTTPConnection(self.targetHost,self.targetPort)
45 self.lastresult = None
46 if self.target.path == '':
47 self.path = '/'
48 else:
49 self.path = self.target.path
50 return True
52 def sendNegotiate(self,negotiateMessage):
53 #Check if server wants auth
54 self.session.request('GET', self.path)
55 res = self.session.getresponse()
56 res.read()
57 if res.status != 401:
58 LOG.info('Status code returned: %d. Authentication does not seem required for URL' % res.status)
59 try:
60 if 'NTLM' not in res.getheader('WWW-Authenticate'):
61 LOG.error('NTLM Auth not offered by URL, offered protocols: %s' % res.getheader('WWW-Authenticate'))
62 return False
63 except (KeyError, TypeError):
64 LOG.error('No authentication requested by the server for url %s' % self.targetHost)
65 return False
67 #Negotiate auth
68 negotiate = base64.b64encode(negotiateMessage).decode("ascii")
69 headers = {'Authorization':'NTLM %s' % negotiate}
70 self.session.request('GET', self.path ,headers=headers)
71 res = self.session.getresponse()
72 res.read()
73 try:
74 serverChallengeBase64 = re.search('NTLM ([a-zA-Z0-9+/]+={0,2})', res.getheader('WWW-Authenticate')).group(1)
75 serverChallenge = base64.b64decode(serverChallengeBase64)
76 challenge = NTLMAuthChallenge()
77 challenge.fromString(serverChallenge)
78 return challenge
79 except (IndexError, KeyError, AttributeError):
80 LOG.error('No NTLM challenge returned from server')
82 def sendAuth(self, authenticateMessageBlob, serverChallenge=None):
83 if unpack('B', authenticateMessageBlob[:1])[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP:
84 respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob)
85 token = respToken2['ResponseToken']
86 else:
87 token = authenticateMessageBlob
88 auth = base64.b64encode(token).decode("ascii")
89 headers = {'Authorization':'NTLM %s' % auth}
90 self.session.request('GET', self.path,headers=headers)
91 res = self.session.getresponse()
92 if res.status == 401:
93 return None, STATUS_ACCESS_DENIED
94 else:
95 LOG.info('HTTP server returned error code %d, treating as a successful login' % res.status)
96 #Cache this
97 self.lastresult = res.read()
98 return None, STATUS_SUCCESS
100 def killConnection(self):
101 if self.session is not None:
102 self.session.close()
103 self.session = None
105 def keepAlive(self):
106 # Do a HEAD for favicon.ico
107 self.session.request('HEAD','/favicon.ico')
108 self.session.getresponse()
110class HTTPSRelayClient(HTTPRelayClient):
111 PLUGIN_NAME = "HTTPS"
113 def __init__(self, serverConfig, target, targetPort = 443, extendedSecurity=True ):
114 HTTPRelayClient.__init__(self, serverConfig, target, targetPort, extendedSecurity)
116 def initConnection(self):
117 self.lastresult = None
118 if self.target.path == '':
119 self.path = '/'
120 else:
121 self.path = self.target.path
122 try:
123 uv_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
124 self.session = HTTPSConnection(self.targetHost,self.targetPort, context=uv_context)
125 except AttributeError:
126 self.session = HTTPSConnection(self.targetHost,self.targetPort)
127 return True