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