Coverage for /root/GitHubProjects/impacket/impacket/examples/ntlmrelayx/clients/smtprelayclient.py : 26%

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# SMTP Protocol Client
8#
9# Author:
10# Dirk-jan Mollema (@_dirkjan) / Fox-IT (https://www.fox-it.com)
11# Alberto Solino (@agsolino)
12#
13# Description:
14# SMTP client for relaying NTLMSSP authentication to mailservers, for example Exchange
15#
16import smtplib
17import base64
18from struct import unpack
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
26PROTOCOL_CLIENT_CLASSES = ["SMTPRelayClient"]
28class SMTPRelayClient(ProtocolClient):
29 PLUGIN_NAME = "SMTP"
31 def __init__(self, serverConfig, target, targetPort = 25, extendedSecurity=True ):
32 ProtocolClient.__init__(self, serverConfig, target, targetPort, extendedSecurity)
34 def initConnection(self):
35 self.session = smtplib.SMTP(self.targetHost,self.targetPort)
36 # Turn on to debug SMTP messages
37 # self.session.debuglevel = 3
38 self.session.ehlo()
40 if 'AUTH NTLM' not in self.session.ehlo_resp:
41 LOG.error('SMTP server does not support NTLM authentication!')
42 return False
43 return True
45 def sendNegotiate(self,negotiateMessage):
46 negotiate = base64.b64encode(negotiateMessage)
47 self.session.putcmd('AUTH NTLM')
48 code, resp = self.session.getreply()
49 if code != 334:
50 LOG.error('SMTP Client error, expected 334 NTLM supported, got %d %s ' % (code, resp))
51 return False
52 else:
53 self.session.putcmd(negotiate)
54 try:
55 code, serverChallengeBase64 = self.session.getreply()
56 serverChallenge = base64.b64decode(serverChallengeBase64)
57 challenge = NTLMAuthChallenge()
58 challenge.fromString(serverChallenge)
59 return challenge
60 except (IndexError, KeyError, AttributeError):
61 LOG.error('No NTLM challenge returned from SMTP server')
62 raise
64 def sendAuth(self, authenticateMessageBlob, serverChallenge=None):
65 if unpack('B', authenticateMessageBlob[:1])[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP:
66 respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob)
67 token = respToken2['ResponseToken']
68 else:
69 token = authenticateMessageBlob
70 auth = base64.b64encode(token)
71 self.session.putcmd(auth)
72 typ, data = self.session.getreply()
73 if typ == 235:
74 self.session.state = 'AUTH'
75 return None, STATUS_SUCCESS
76 else:
77 LOG.error('SMTP: %s' % ''.join(data))
78 return None, STATUS_ACCESS_DENIED
80 def killConnection(self):
81 if self.session is not None:
82 self.session.close()
83 self.session = None
85 def keepAlive(self):
86 # Send a NOOP
87 self.session.noop()