Open Bug 508698 Opened 10 years ago Updated 8 years ago

SSL_SecureRecv returns 0 rather than an error if the peer closes the TCP connection without sending an SSL close_notify alert

Categories

(NSS :: Libraries, defect)

3.11.14
defect
Not set

Tracking

(Not tracked)

People

(Reporter: wtc, Unassigned)

Details

Attachments

(1 file, 1 obsolete file)

Nelson, I'm intentionally not marking this bug as security-sensitive
because people usually don't feel confident removing that flag.  If you
think this bug is security-sensitive, please set the flag.

SSL_SecureRecv returns 0 rather than an error if the peer closes the
TCP connection without sending an SSL close_notify alert.  This makes
the caller potentially vulnerable to truncation attacks.

This stack trace shows where the relevant code is on the current
NSS trunk:

#0  ssl3_GatherData (ss=0xf0c67e40, gs=0xf0c68080, flags=0) at ssl3gthr.c:97
#1  0xf78880f4 in ssl3_GatherCompleteHandshake (ss=0xf0c67e40, flags=0)
    at ssl3gthr.c:195
#2  0xf7888245 in ssl3_GatherAppDataRecord (ss=0xf0c67e40, flags=0)
    at ssl3gthr.c:235
#3  0xf7896f58 in DoRecv (ss=0xf0c67e40, 
    out=0xf0c84ee0 "\220\037a*ya\002}2~F°\237*²k![Ö@6r­.x\227V\214e\006°\205^¿÷TP\177ùHnnÍó¸é¨ËÃ\020@\006óÎ\206\021õ;Çì~Ò\236®\023tÁéF$SÄ\rx@e0Ä\033bR\022\034'\212E?\225!=\207SsÎ-¬ª5±¢8\033p&\020*8µ\035Éð\034¶5\201ܳÄIÛR\025kYòUDª6dNJÔÖ$\016jªüפÄ\020FîIO\222Î+SK\033\234-çÌç«#À9m\027b\026F\205«Q\031êð\026½ò\003¸Ý\001\v®>ã\213L\226¬modW·\212\211;~\226\206ê"..., len=32768, flags=0)
    at sslsecur.c:552
#4  0xf78980f1 in ssl_SecureRecv (ss=0xf0c67e40, 
    buf=0xf0c84ee0 "\220\037a*ya\002}2~F°\237*²k![Ö@6r­.x\227V\214e\006°\205^¿÷TP\177ùHnnÍó¸é¨ËÃ\020@\006óÎ\206\021õ;Çì~Ò\236®\023tÁéF$SÄ\rx@e0Ä\033bR\022\034'\212E?\225!=\207SsÎ-¬ª5±¢8\033p&\020*8µ\035Éð\034¶5\201ܳÄIÛR\025kYòUDª6dNJÔÖ$\016jªüפÄ\020FîIO\222Î+SK\033\234-çÌç«#À9m\027b\026F\205«Q\031êð\026½ò\003¸Ý\001\v®>ã\213L\226¬modW·\212\211;~\226\206ê"..., len=32768, flags=0)
    at sslsecur.c:1123
#5  0xf7898179 in ssl_SecureRead (ss=0xf0c67e40, 
    buf=0xf0c84ee0 "\220\037a*ya\002}2~F°\237*²k![Ö@6r­.x\227V\214e\006°\205^¿÷TP\177ùHnnÍó¸é¨ËÃ\020@\006óÎ\206\021õ;Çì~Ò\236®\023tÁéF$SÄ\rx@e0Ä\033bR\022\034'\212E?\225!=\207SsÎ-¬ª5±¢8\033p&\020*8µ\035Éð\034¶5\201ܳÄIÛR\025kYòUDª6dNJÔÖ$\016jªüפÄ\020FîIO\222Î+SK\033\234-çÌç«#À9m\027b\026F\205«Q\031êð\026½ò\003¸Ý\001\v®>ã\213L\226¬modW·\212\211;~\226\206ê"..., len=32768) at sslsecur.c:1132
#6  0xf789f3a2 in ssl_Read (fd=0xf0c4bb48, buf=0xf0c84ee0, len=32768)
    at sslsock.c:1468
#7  0xf76ae854 in PR_Read (fd=0xf0c4bb48, buf=0xf0c84ee0, amount=32768)
    at ../../../../pr/src/io/priometh.c:141

The following Bonsai links show how the TCP EOF progresses through
our code:

http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ssl/ssl3gthr.c&rev=1.9&mark=90,94,97#66

http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ssl/ssl3gthr.c&rev=1.9&mark=195-198#186

http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ssl/ssl3gthr.c&rev=1.9&mark=235,238#228

http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ssl/sslsecur.c&rev=1.42&mark=552,558-563#538

http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ssl/sslsecur.c&rev=1.42&mark=1123#1078

Eventually PR_Read returns 0.
Mac OS X's Secure Transport library has two result codes so the
caller can tell if close_notify was received:

errSSLClosedGraceful  The connection closed gracefully.
errSSLClosedNoNotify  The server closed the session with no
                      notification.
Thanks, Wan-Teh.  

PSM has an error that it displays when it gets an error that reports 
truncation (that is, EOF without close notify).  Based on the number of bug
reports filed about it, we know that that error is seen somewhat frequently.
So, I take your report to mean that there are some paths in which it is 
reported and others in which it is not.  

I wonder if the path that you report is seldom used by PSM, or what other 
explanation might exist for the presence of many reports of this error 
despite the code path you're reporting.  

NSS also has two separate results for truncation attacks vs normal EOF.
PR_END_OF_FILE_ERROR on an SSL socket means "socket closed without 
close_notify alert."

If this bug were to be marked as security sensitive, I think it would be 
"sg:low".  IMO, truncation attacks are of relatively low severity, among
the attacks we've recently encountered.  But feel free to mark bugs Security
Sensitive.  I'm guick to remove that flag for NSS bugs that I believe are 
truly not sensitive.
This MXR search shows that PR_END_OF_FILE_ERROR is only
set during SSL handshake:
http://mxr.mozilla.org/security/ident?i=PR_END_OF_FILE_ERROR

For a test case, visit http://www.alaskaair.com/ and click
the "My Account" or "My Trips" link on that page.  That server
doesn't send close_notify alerts.  Its HTTP responses have
the "Connection: close" header but no "Content-Length" header
and don't use chunked encoding, so it is vulnerable to
truncation attacks.
Attached patch Patch (with questions) (obsolete) — Splinter Review
First, I'm not sure if we should fix this bug because
it'll be a behavior change.  I am submitting this patch
to wrap up my work on this bug.

I do want to note that both Microsoft's Schannel and
Apple's SecureTransport allow their users to detect if
close_notify has been received.  So as a general-purpose
SSL library, NSS is not as good.  On the other hand,
browsers ignore the lack of close_notify for site
compatibility.  (Firefox does that unknowingly because
NSS doesn't report the condition.)

This patch makes ssl_SecureRecv return SECFailure with
PR_END_OF_FILE_ERROR if we get EOF without receiving a
close_notify alert.  This patch also points out two
issues with ssl3_GatherDat that I found by code
inspection.

1. ssl3_GatherData returns 0 (EOF) whether it has read
an incomplete record or not.  So its caller can't
distinguish between
- EOF immediately following a record boundary, and
- EOF after a partial record

Both are reported as 0 (EOF).

2. We should be able to exit the for loop in ssl3_GatherData
if the SSL3 record header says the length of the following
encrypted data is 0.  This avoids asking ssl_DefRecv to read
0 bytes, which makes its return value ambiguous -- does 0
means EOF or 0 bytes?
Assignee: nelson → nobody
Status: UNCONFIRMED → NEW
Ever confirmed: true
Comment on attachment 394431 [details] [diff] [review]
Patch (with questions)

I've tested this patch with the Chromium browser.  Because of
the behavior change, the Chromium network stack needs a patch:
http://codereview.chromium.org/164542

I guess Firefox will need a patch, too, if we fix this bug.
Minor change to the conditional expression for EOF after
reading a partial record.
Attachment #394431 - Attachment is obsolete: true
Wan-Teh, I think the "What if gs->remainder is 0?" case is bug 571795.
You need to log in before you can comment on or make changes to this bug.