Optimistic assumptions about STARTTLS upgrade and passwords [security]
Categories
(MailNews Core :: Networking: SMTP, defect, P1)
Tracking
(Not tracked)
People
(Reporter: BenB, Assigned: rnons)
Details
(Keywords: leave-open)
Attachments
(2 files)
Situation: We're connecting to a malicious server (due to MITM, DNS poisoning, IP level attacks etc.), and the server is trying a downgrade attack, forcing Thunderbird to not use TLS, then listening on the connection, including the emails, and possibly including the password.
- SmtpClient.jsm function
_actionSTARTTLS()
has:
this._secureTransport = true;
this.socket.upgradeToSecure();
The order should be reversed, because the upgrade can fail.
Let's say the server deliberately lets the STARTTLS upgrade fail. this._secureTransport
would be set to true, and other code later on then depends on that value to decide whether the connection is fine, e.g.
function _actionEHLO()
if (!this._secureTransport && this.options.alwaysSTARTTLS) {
... fail
... else continue ...
-
I assume here that upgradeToSecure() would throw an error in case the upgrade failed, but that also needs to be checked.
-
There are likely other conditions that are problematic. The code also in other parts of SmtpClient.jsm seems to make sunny assumptions and needs to better consider a malicious server that deliberately makes the code fail. A more dedicated and detailed security analysis of this code for error scenarios in the SSL and encrypted passwords options is recommended.
Reporter | ||
Updated•2 years ago
|
Reporter | ||
Updated•2 years ago
|
Assignee | ||
Comment 1•2 years ago
|
||
(In reply to Ben Bucksch (:BenB) from comment #0)
- SmtpClient.jsm function
_actionSTARTTLS()
has:this._secureTransport = true; this.socket.upgradeToSecure();
The order should be reversed, because the upgrade can fail.
Let's say the server deliberately lets the STARTTLS upgrade fail.
this._secureTransport
would be set to true, and other code later on then depends on that value to decide whether the connection is fine, e.g.
I think the order doesn't matter a lot as long as upgradeToSecure
do the right thing. I will reverse it later anyway.
- I assume here that upgradeToSecure() would throw an error in case the upgrade failed, but that also needs to be checked.
This indeed seems to be a problem. Seems to me we should check the rv of https://searchfox.org/mozilla-central/rev/5ad2b9480ab6809c28d64ff56918ceb394642c72/dom/network/TCPSocket.cpp#316, and throw if failed. :valentin: what do you think? I will send a patch later today.
Reporter | ||
Comment 2•2 years ago
•
|
||
Hi Ping, thanks for handling this!
as long as upgradeToSecure() do the right thing
That's the problem: What if a malicious server makes it fail deliberately? Then secureConnection is already true, and later code makes assumptions that the link is secure. Such failure cases must be handled, otherwise there's the risk for security holes.
Assignee | ||
Comment 3•2 years ago
|
||
Assignee | ||
Comment 4•2 years ago
|
||
(In reply to Ben Bucksch (:BenB) from comment #2)
as long as upgradeToSecure() do the right thing
That's the problem: What if a malicious server makes it fail deliberately? Then secureConnection is already true, and later code makes assumptions that the link is secure. Such failure cases must be handled, otherwise there's the risk for security holes.
If upgradeToSecure fails and throws, the socket is disconnected, the value of _secureConnection
doesn't matter.
If upgradeToSecure fails silently, changing the order doesn't help. So I don't need to reverse it.
Reporter | ||
Comment 6•2 years ago
|
||
Re Problem 2:
Thanks for finding and fixing the bug in TCPSocket!
Re Problem 1:
I don't need to reverse it.
I'm glad that the reversed order (Problem 1) is not an actual bug currently.
However, the current logic is making assumptions about the behavior of another component. The API of upgradeToSecure()
does not promise to abort the connection in case the upgrade fails. If could also just throw and leave the connection open, and would still adhere to the API. Thus, it would be safer to reverse the order of the 2 statements, and is trivial to do.
Re Problem 3:
It would be good to security-reviewed the entire file with an attitude of being fail-safe, particularly in light of unforseen circumstances and deliberate attemps to exploit it.
Assignee | ||
Comment 7•2 years ago
|
||
Assignee | ||
Comment 8•2 years ago
|
||
The API of upgradeToSecure() does not promise to abort the connection in case the upgrade fails.
We already have code to close socket in the onerror handler. My patch just now moves the quit/close to the beginning of onerror.
Assignee | ||
Updated•2 years ago
|
Assignee | ||
Comment 9•2 years ago
|
||
Only D137261 is the patch for c-c and needs checkin, thanks
Reporter | ||
Comment 10•2 years ago
|
||
Patch: Send QUIT or close TCPSocket immediately in onerror handler
@rnons: Thank you!
Comment 11•2 years ago
|
||
Pushed by mkmelin@iki.fi:
https://hg.mozilla.org/comm-central/rev/cb73a6c8eb85
Send QUIT or close TCPSocket immediately in onerror handler. r=mkmelin
Comment 12•2 years ago
|
||
Gene, Magnus,
Any ideas why the test doesn't work?
Updated•1 year ago
|
Comment 14•9 months ago
|
||
Hey, how are we proceeding with this from here?
Also, the severity is set at S1 - how is this a release blocker or a work blocker?
Description
•