-
-
Notifications
You must be signed in to change notification settings - Fork 31.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[security] smtplib multiple CRLF injection #87290
Comments
// reported via PSRT email (see timeline; last contact: Alex/PSRT) cve: # Vulnerability Note ## Summary
Two CR-LF injection points have been discovered in the Python standard library for The root cause of this is likely to be found in the design of the It is recommended to reject or encode ## Details ### Description The root cause of this (and probably also some earlier reported CR-LF injections) is the method def putcmd(self, cmd, args=""):
"""Send a command to the server."""
if args == "":
str = '%s%s' % (cmd, CRLF)
else:
str = '%s %s%s' % (cmd, args, CRLF)
self.send(str) However, the issue was initially found in self.putcmd("mail", "FROM:%s%s" % (quoteaddr(sender), optionlist)) A similar issue was found with Here's a snipped of def helo(self, name=''):
"""SMTP 'helo' command.
Hostname to send for this command defaults to the FQDN of the local
host.
"""
self.putcmd("helo", name or self.local_hostname)
(code, msg) = self.getreply()
self.helo_resp = msg
return (code, msg) We highly recommend, fixing this issue once and for all directly in ## Proof of Concept
import smtplib
server = smtplib.SMTP('localhost', 10001, "hi\nX-INJECTED") # localhostname CRLF injection
server.set_debuglevel(1)
server.sendmail("hi@me.com", "you@me.com", "wazzuuup\nlinetwo")
server.mail("hi@me.com",["X-OPTION\nX-INJECTED-1","X-OPTION2\nX-INJECTED-2"]) # options CRLF injection
### Proposed Fix
diff --git a/Lib/smtplib.py b/Lib/smtplib.py
index e2dbbbc..9c16e7d 100755
--- a/Lib/smtplib.py
+++ b/Lib/smtplib.py
@@ -365,10 +365,10 @@ class SMTP:
def putcmd(self, cmd, args=""):
"""Send a command to the server."""
if args == "":
- str = '%s%s' % (cmd, CRLF)
+ str = cmd
else:
- str = '%s %s%s' % (cmd, args, CRLF)
- self.send(str)
+ str = '%s %s' % (cmd, args)
+ self.send('%s%s' % (str.replace('\n','\\n'), CRLF)) ## Vendor Response Vendor response: gone silent ### Timeline
## References
|
Deferred the blocker to a regular release due to lack of activity in time for the current expedited releases. |
Still in "deferred blocker" status awaiting a PR from someone |
If there's no one working on it I'd be happy to prepare a fix. |
There is no sign of anyone currently working on it, so please feel free to dig in! |
Thanks for the PR! Can someone from the email team take a look at it, please? |
This bug report starts with "a malicious user with direct access to `smtplib.SMTP(..., local_hostname, ..)", which is a senseless supposition. Anyone with "access to" the SMTP object could just as well be talking directly to the SMTP server and do anything they want that SMTP itself allows. The concern here is that data a program might obtain *from unsanitized user input* could be used to do header injection. The "proof of concept" does not address this at all. We'd need to see a scenario under which data that could reasonably be derived from user input ends up being passed as arguments to an smtplib method that calls putcmd with arguments. So, I would rate this as *very* low impact issue, unless someone has an *actual example* of code using smtplib that passes user input through to smtplib commands in an exploitable way. That said, it is perfectly reasonable to be proactive here and prevent scenarios we haven't yet thought of, by doing as recommended (and a bit more) by raising a ValueError if 'args' in the putcmd call contain either \n or \r characters. I don't think we need to check 'cmd', because I can't see any scenario in which the SMTP command would be derived from user input. If you want to be *really* paranoid you could check cmd too, and since it will always be a short string the additional performance impact will be minor. |
s/header injection/command injection/ |
Let's not argue about the phrasing and settle on the fact that I am not a native English speaker which might be the root cause of the confusion. The core of the issue is that this *unexpected side-effect* may be security-relevant. Fixing it probably takes less time than arguing about phrasing, severity, or spending time describing exploitation scenarios for a general-purpose library that should protect the underlying protocol from injections. Be kind, I come in peace. |
My apologies, I did not think about the possibility of an English issue. I was reacting to the "security report speak", which I find often makes a security issue sound worse than it is :) Thank you for reporting this problem, and I do think we should fix it. My posting was directed at the severity of the issue, since it was potentially holding up a release. My point about the example is that without an example of code that could reasonably be expected to use user input in a call that could inject newlines, we can treat this as a low priority issue. If we had a proposed example of such code, then the priority would be higher. If it was an example of such code "in the wild", then it would be quite high :) The reason I'm saying we should have an example in order to consider it higher priority is that I cannot see *any* likelihood that this would be a problem in practice. Let me explain. putcmd is an *internal* interface. If we look at the commands that call putcmd or docmd, the only ones that pass extra data that aren't pretty obviously safe (ie: not clearly sanitized data) are rcpt and mail[]. In both cases the item of concern is optionslist. optionslist is a list of *SMTP server options. This is not data that is reasonably taken from user input, it is data provided *by the programmer*. [*] I did double check to make sure that email.utils.parseaddr sanitizes both \r and \r, just to be sure :) Therefore this is *not* a significant security issue. But as I said, we should take the "defense in depth" approach and apply the check in putcmd as you recommend. I just don't think it needs to hold up a release. |
Thanks, Martin! ✨ 🍰 ✨ |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: