diff --git a/MITMsmtp/SMTPHandler.py b/MITMsmtp/SMTPHandler.py index bccd9c1..3a5cea7 100644 --- a/MITMsmtp/SMTPHandler.py +++ b/MITMsmtp/SMTPHandler.py @@ -25,9 +25,12 @@ def init(self): """ Reads a line from TCP Stream @return: Read line """ - def readLine(self): - line = self.rfile.readline().strip() - if (self.server.printLines): + def readLine(self, skipBlank=True): + while True: + line = self.rfile.readline().strip() + if line or not skipBlank: + break + if self.server.printLines: print("C:" + line) return line @@ -180,7 +183,7 @@ def sendIntermediate(self): def readMSG(self): message = "" while True: - line = self.readLine() + line = self.readLine(skipBlank=False) if (line == '.'): self.message.setMessage(message) return diff --git a/MITMsmtp/SMTPServer.py b/MITMsmtp/SMTPServer.py index b873735..cc355c2 100644 --- a/MITMsmtp/SMTPServer.py +++ b/MITMsmtp/SMTPServer.py @@ -6,7 +6,7 @@ """ SMTPServer wrapper class for TCPServer """ -class SMTPServer(TCPServer): +class SMTPServer(ThreadingMixIn, TCPServer): """ Creates a new SMTPServer object @param server_address: The address to listen on @type server_address: str @@ -79,11 +79,10 @@ def get_request(self): @return: Returns encrypted connection """ def wrapSSL(self, socket): - connstream = ssl.wrap_socket(socket, - server_side=True, - certfile = self.certfile, - keyfile = self.keyfile, - ssl_version = self.ssl_version) + context = ssl.SSLContext(self.ssl_version) + if self.certfile: + context.load_cert_chain(certfile=self.certfile, keyfile=self.keyfile) + connstream = context.wrap_socket(socket, server_side=True) + return connstream -class SMTPServer(ThreadingMixIn, SMTPServer): pass diff --git a/MITMsmtp/__main__.py b/MITMsmtp/__main__.py index 331806d..f5cfa0f 100644 --- a/MITMsmtp/__main__.py +++ b/MITMsmtp/__main__.py @@ -52,7 +52,7 @@ def loginCallback(self, message, username, password): @type message: Message """ def messageCallback(self, message): - output = """=== Complete Message ===%s\nIP : %s\n\nUsername : %s\nPassword : %s\nClient : %s\nSender : %s\n""" % (message.clientIP, + output = """=== Complete Message ===\nIP : %s\n\nUsername : %s\nPassword : %s\nClient : %s\nSender : %s\n""" % (message.clientIP, message.username, message.password, message.client_name, @@ -72,7 +72,7 @@ def messageCallback(self, message): log.write(output + "\n\n") log.write(message.message) -def main(args=None): +def main(): # Parse arguments parser=argparse.ArgumentParser(description="MITMsmtp is an Evil SMTP Server for pentesting SMTP clients to catch login credentials and mails sent over plain or SSL encrypted connections.") parser.add_argument('--server_address', default="0.0.0.0", help='IP Address to listen on (default: all)') @@ -118,3 +118,6 @@ def main(args=None): except KeyboardInterrupt: pass server.stop() #Stop SMTPServer + +if __name__ == "__main__": + main() diff --git a/MITMsmtp/auth/authLogin.py b/MITMsmtp/auth/authLogin.py index 19d2601..d5c2741 100644 --- a/MITMsmtp/auth/authLogin.py +++ b/MITMsmtp/auth/authLogin.py @@ -17,10 +17,10 @@ class authLogin (authMethod): @returns: The authMethods name """ def __init__(self, SMTPHandler, authLine): + super().__init__(SMTPHandler, authLine) + self.SMTPHandler = SMTPHandler self.authLine = authLine - self.username = None - self.password = None self.requestUsername() self.readUsername() diff --git a/MITMsmtp/auth/authMethod.py b/MITMsmtp/auth/authMethod.py index 18e639b..e367fd4 100644 --- a/MITMsmtp/auth/authMethod.py +++ b/MITMsmtp/auth/authMethod.py @@ -18,6 +18,9 @@ class authMethod(ABC): def __init__(self, SMTPHandler, authLine): super().__init__() + self.username = None + self.password = None + """ Returns the authMethods name Has to be overwritten, otherwise authentication method can't be advertised to client! diff --git a/MITMsmtp/auth/authPlain.py b/MITMsmtp/auth/authPlain.py index 51ec77d..63ae668 100644 --- a/MITMsmtp/auth/authPlain.py +++ b/MITMsmtp/auth/authPlain.py @@ -17,10 +17,10 @@ class authPlain(authMethod): @returns: The authMethods name """ def __init__(self, SMTPHandler, authLine): + super().__init__(SMTPHandler, authLine) + self.SMTPHandler = SMTPHandler self.authLine = authLine - self.username = None - self.password = None match = re.match("AUTH PLAIN$", authLine) if (match != None): @@ -85,7 +85,6 @@ def auth(self): self.authSuccess() self.username = auth[-2] self.password = auth[-1] - authSuccess() """ Sends success reply diff --git a/README.md b/README.md index 3813fb0..07b9a0d 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ MITMsmtp supports the following login methods: Challenge-Response based authentication methods like CRAM-MD5, NTLM or Kerberos can't be supported as these methods require the server to know the cleartext password. ## Setup -MITMsmtp requires Python3 and setuptools. You might want to install git as well. Use the following command on Debian: +MITMsmtp requires at least Python 3.6. You might want to install git and setuptools as well. Use the following command on Debian: `apt install python3 python3-setuptools git` @@ -28,16 +28,24 @@ Now just clone the MITMsmtp repository: `git clone https://github.com/RobinMeis/MITMsmtp.git` -Change into MITMsmtp directory and start the installation: +Change into MITMsmtp directory. From there you can run the program as a module with: -`sudo python3 setup.py install` +`python -m MITMsmtp` -That's it! +or install it with setuptools by running: + +`pip install .` + +After installation, you will be able to use the `MITMsmtp` command directly from your terminal. ### Updating -`git pull` -`sudo python3 setup.py install` +From within the MITMsmtp directory run: + +``` +git pull` +pip install . +``` ## Usage *MITMsmtp can be used as standalone command line application and offers an easy to use Python3 API to integrate in your own project* diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..648a2cc --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,25 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "MITMsmtp" +version = "0.0.3-dev" +authors = [ + {name = "Robin Meis", email = "blog@smartnoob.de"}, +] +description = "An evil SMTP Server for client pentesting" +readme = "README.md" +license = "GPL-3.0-only" +license-files = ["LICENSE"] +requires-python = ">= 3.6" +classifiers = [ + "Programming Language :: Python :: 3", + "Topic :: Security" +] + +[project.urls] +GitHub = "https://github.com/RobinMeis/MITMsmtp" + +[project.scripts] +MITMsmtp = "MITMsmtp.__main__:main" diff --git a/setup.py b/setup.py deleted file mode 100644 index 7530d98..0000000 --- a/setup.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 - -import setuptools -import os - -with open("README.md", "r") as fh: - long_description = fh.read() - -setuptools.setup( - name="MITMsmtp", - version="0.0.3-dev", - author="Robin Meis", - author_email="blog@smartnoob.de", - description="An evil SMTP Server for client pentesting", - long_description=long_description, - long_description_content_type="text/markdown", - url="https://github.com/RobinMeis/MITMsmtp", - packages=setuptools.find_packages(), - classifiers=[ - "Programming Language :: Python :: 3", - ], - entry_points={ - 'console_scripts': [ - 'MITMsmtp = MITMsmtp.__main__:main' - ] - }, - include_package_data=True, -)