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

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

## 91 statements

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#

16 import re

17 import ssl

18 try:

19 from http.client import HTTPConnection, HTTPSConnection, ResponseNotReady

20 except ImportError:

21 from httplib import HTTPConnection, HTTPSConnection, ResponseNotReady

22 import base64

23

24 from struct import unpack

25 from impacket import LOG

26 from impacket.examples.ntlmrelayx.clients import ProtocolClient

27 from impacket.nt_errors import STATUS_SUCCESS, STATUS_ACCESS_DENIED

28 from impacket.ntlm import NTLMAuthChallenge

29 from impacket.spnego import SPNEGO_NegTokenResp

30

31 PROTOCOL_CLIENT_CLASSES = ["HTTPRelayClient","HTTPSRelayClient"]

32

33 class HTTPRelayClient(ProtocolClient):

34 PLUGIN_NAME = "HTTP"

35

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

42

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

51

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

66

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

81

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

99

100 def killConnection(self):

101 if self.session is not None:

102 self.session.close()

103 self.session = None

104

105 def keepAlive(self):

106 # Do a HEAD for favicon.ico

107 self.session.request('HEAD','/favicon.ico')

108 self.session.getresponse()

109

110 class HTTPSRelayClient(HTTPRelayClient):

111 PLUGIN_NAME = "HTTPS"

112

113 def __init__(self, serverConfig, target, targetPort = 443, extendedSecurity=True ):

114 HTTPRelayClient.__init__(self, serverConfig, target, targetPort, extendedSecurity)

115

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