[HN Gopher] Why TLS is better without STARTTLS (2021)
___________________________________________________________________
Why TLS is better without STARTTLS (2021)
Author : Tomte
Score : 68 points
Date : 2023-02-10 06:41 UTC (16 hours ago)
(HTM) web link (nostarttls.secvuln.info)
(TXT) w3m dump (nostarttls.secvuln.info)
| dlandau wrote:
| "Meddler-in-the-middle", I hope this catches on.
| markonen wrote:
| I've been trying to shoehorn mTLS into existing infrastructure of
| Postgres clients and servers. This would be trivial if Postgres
| used straight-up TLS; as it is, though, you need sidecars that
| understand the Postgres wire protocol and that limits your
| choices to things like pgbouncer (which will add not-
| insignificant overhead) or Envoy (where the Postgres wire
| protocol support seems alpha quality or so).
| philsnow wrote:
| > This would be trivial if Postgres used straight-up TLS
|
| ... does it not? (I really don't know, I've never had to admin
| postgres myself)
|
| from https://www.postgresql.org/docs/current/ssl-tcp.html#SSL-
| SET...
|
| > With SSL support compiled in, the PostgreSQL server can be
| started with support for encrypted connections using TLS
| protocols enabled by setting the parameter ssl to on in
| postgresql.conf. The server will listen for both normal and SSL
| connections on the same TCP port, and will negotiate with any
| connecting client on whether to use SSL. _By default, this is
| at the client 's option_
|
| wait so.. if it uses the same port for TLS, does it use
| STARTTLS?
|
| from https://www.postgresql.org/docs/current/protocol-
| flow.html#i...
|
| > To initiate an SSL-encrypted connection, the frontend
| initially sends an SSLRequest message rather than a
| StartupMessage. The server then responds with a single byte
| containing S or N, indicating that it is willing or unwilling
| to perform SSL, respectively. The frontend might close the
| connection at this point if it is dissatisfied with the
| response. To continue after S, perform an SSL startup handshake
| (not described here, part of the SSL specification) with the
| server. If this is successful, continue with sending the usual
| StartupMessage. In this case the StartupMessage and all
| subsequent data will be SSL-encrypted. To continue after N,
| send the usual StartupMessage and proceed without encryption.
|
| and also from that section
|
| > While the protocol itself does not provide a way for the
| server to force SSL encryption, the administrator can configure
| the server to reject unencrypted sessions as a byproduct of
| authentication checking.
|
| .... that is not great. I mean _zero_ disrespect to the
| postgres dev team, but why do this? I know (m)TLS has issues,
| but why would anybody want to have to trust /verify two
| codebases (the postgres bits before the handoff to
| openssl/boringssl/whatever) instead of just one (only
| openssl/boringssl), just to bootstrap to a secure client-server
| connection?
|
| (this is my complaint about _all_ upgrade-to-TLS schemes)
| tinus_hn wrote:
| This is like DECT where they are all about the 'thousands of
| security codes', but if the base station (or an imposter)
| suddenly says 'I don't do encryption' the handset just stops
| doing encryption.
| gmac wrote:
| The Postgres devs are discussing eliminating that speedbump,
| and having an encrypted connection start with an ordinary TLS
| Client Hello: https://www.postgresql.org/message-
| id/flat/CAM-w4HOEAzxyY01Z...
| rbut wrote:
| We run an LDAP service attached to our SaaS application.
|
| A couple of years ago we were alerted to the fact that iOS
| devices no longer connected to our LDAPS server running on port
| 636. macOS still seemed to connect fine..
|
| After some digging, it seemed Apple updated iOS to only accept
| connecting over STARTTLS on port 389. So we had to run a STARTTLS
| server also to make iOS devices work.
|
| At the time, it seemed STARTTLS over 389 was the "standard",
| maybe that's why Apple changed it, but looking just now it seems
| that is being challenged [1][2], and rightly so.
|
| [1] https://unix.stackexchange.com/questions/607560/why-is-
| ldap-...
|
| [2] https://lists.openldap.org/hyperkitty/list/openldap-
| technica...
| billpg wrote:
| I'm writing a POP3 service (http://billpg.com/POP3/) and I
| stumbled upon this as a bit of a forehead-slapping moment.
|
| Once I read about it, I tried attacking my own server by sending
| in "STLS\r\nCAPA\r\n" in a single TCP package and it responded to
| CAPA after the encrypted channel had been established because
| those bytes were still in the buffer.
|
| One hasty bugfix to clear the buffers after establishing TLS
| later and I thought about how to exploit this bug. The only thing
| you can do at this point is log in and an attacker isn't going to
| know the user's credentials. (If they do, you don't need to
| exploit the bug.)
|
| Despite this, I wonder about what what if HTTP had a STARTTLS
| command instead of using port 443 and handing over directly to
| TLS. SNI (identifying the names host the client wishes to connect
| to prior to certificate exchange) took years to get established,
| mostly (I think) because it was inside the black-box of TLS. If
| the certificate exchange happened with HTTP before handing over
| to TLS, the request might have looked like: GET
| /.well-known/tls-cert HTTP/1.1 Host: the-actual-hostname
| Accept: certificate/format, et/c
|
| When the hand-over to TLS (in this parallel universe) takes
| place, the certificate exchange has already happened. TLS's job
| is now to confirm the cert is valid (or not) and exchange session
| keys.
| tsimionescu wrote:
| That needlessly ties the session layer (TLS) with the
| application layer (HTTP). The much better solution is the one
| taken by QUIC, moving encryption itself at the transport layer
| (well, or it would be if QUIC itself weren't piggybacking on
| UDP).
|
| It's an unfortunate accident of history that encryption was
| tied to some application protocols, and is not part of the
| standard TCP/IP stack provided at the OS level entirely. This
| same accident led to bad ideas like STARTTLS, unfortunately.
| daneel_w wrote:
| I never could understand why POP3 service providers don't just
| insist on enforcing POP3S. We're no longer in the early 2000s.
|
| https://github.com/stolendata/little-peepo/blob/master/littl...
| lbriner wrote:
| My understanding is that it is always historical. There are
| still people out there who are "I built my own email tools"
| or "this was setup in 1992 and still works" etc. These aren't
| a tiny fringe group but asizeable number of sometimes very
| influential people.
|
| As soon as you make a serious breaking change, it brings out
| all the complaints of "centralisation" of "being forced into
| something" into "I don't need tls whatever you say" etc.
|
| Google try these sorts of things occasionally but although in
| most cases it is short-term pain for long-term gain, it
| rarely goes that way.
| daneel_w wrote:
| The case of POP3 and STARTTLS vs POP3S is different,
| because practically all POP3 providers these days _require_
| encryption before the e-mail client is allowed to transact.
| It 's the same encryption method/protocol and the same
| requirement, it's just that POP3S goes straight for the TLS
| handshake while STARTTLS (with the security concerns
| detailed in the article) begins talking on an unencrypted
| channel before getting on with the mandatory handshake.
| hannob wrote:
| How to exploit: For imap or smtp one can construct commands
| that will lead to a mail with the login credentials being sent
| to the attacker (assuming the attacker has an account on the
| same server). For POP3 we were unable to come up with such an
| attack, as it has no way of storing or sending mails.
| billpg wrote:
| Yep. While I did fix the bug as soon as I found it, I
| consider myself fortunate I chose POP3 to write my first
| server.
| [deleted]
| knome wrote:
| >One hasty bugfix to clear the buffers after establishing TLS
|
| Discarding bytes seems like the wrong thing to do as well. If
| your starttls just takes the socket and no "initial bytes", as
| I would expect, you would need to either read off the socket a
| byte at a time til then or better to use MSG_PEEK to not read
| past the next \r\n.
| billpg wrote:
| I thought about that but I didn't want to be stuffing bytes
| back into the incoming stream and I didn't want to be reading
| the stream byte-by-byte either unless I really had to. I had
| a nice bit of code that read blocks of bytes and looked for
| the CRLF separating lines - even handling the case where the
| CR is one block and the LF is in the next one - and I didn't
| want to dismantle that.
|
| I read the relevant RFC and there was a clear exception to
| the rules of PIPELINING that meant a conforming client
| doesn't send the "ClientHello" until the server has responded
| to the STLS command. I felt justified in clearing the buffer
| at that point.
| hannob wrote:
| Hi, one of the authors here. Happy to answer any questions.
| billpg wrote:
| I'm writing (as a side project) a game with a client-server
| system.
|
| For the server, I'm using dot-net's SslStream (in TLS mode) and
| it needs to know which TLS cert to use prior to handing over
| control of the connection.
|
| For this reason, I've designed the protocol for the client to
| announce who they are and what they want as a single line of
| JSON before letting SslStream negotiate TLS. Once the
| connection is secured, the client repeats that first line of
| JSON. If the server detects any difference between the two it
| closes down the connection. (I also made sure to clear the
| buffers after reading that first line of JSON.)
|
| I don't like doing that but the only other way is to "roll my
| own crypto" which I understand is a bad thing.
| d-z-m wrote:
| Sniffing the SNI from the underlying TCP connection is the
| proper way to do this.
|
| a couple examples I know of(only know go ones of the top of
| my head):
|
| https://github.com/fabiolb/fabio/blob/master/proxy/tcp/tls_c.
| .. https://github.com/FiloSottile/mostly-
| harmless/blob/main/tal...
|
| > I don't like doing that but the only other way is to "roll
| my own crypto" which I understand is a bad thing.
|
| You would not be rolling your own cryptographic primitive, or
| combining existing ones in strange and speculative ways. This
| is what most people, most of the time mean when they admonish
| against rolling your own crypto.
|
| All you'd have to do is parse the ClientHello to retrieve the
| SNI. you're in a memory safe language, so parsing bugs result
| in a crash, not a buffer overflow. I'd say you're on pretty
| firm ground.
| hannob wrote:
| > it needs to know which TLS cert to use prior to handing
| over control of the connection
|
| It is a bit unclear here what that means. I mean TLS has a
| mechanism to choose the certificate based on the hostname
| (SNI). Other than that - why would a different user get a
| different certificate? After all the certificate's job is to
| identify the server.
| billpg wrote:
| That's a flaw in dot-net's SslStream library. You don't get
| an opportunity to know what host the client is expecting
| before selecting the cert for this session. Reading
| discussions around this issue usually settle on reading and
| parsing the "ClientHello" to extract the SNI name, and then
| hacking the ClientHello back into the incoming stream so
| TLS code can read it.
| hannob wrote:
| According to this
| https://github.com/dotnet/corefx/pull/28278 SNI support
| has been added in 2018.
| billpg wrote:
| It is very possible my information is out of date or I
| was using an older version of dot-net. Thank you!
| ttul wrote:
| The proper long term solution to this problem is DANE [2], but
| since migrating everyone to DNSSEC will take a long time, Google
| and a few others in the email ecosystem created MTA-STS, which is
| far better than nothing [1].
|
| All this being said, another idea (not standardized yet as far as
| I know) would be to publish a new DNS record, MXS (for example),
| that would imply the use of the SSL email port 465. I think it
| would be a worthy standardization effort to go in this direction
| and finally banish STARTTLS.
|
| [1] https://dmarcian.com/mta-sts/ [2] https://www.rfc-
| editor.org/rfc/rfc7671.html
| tsimionescu wrote:
| How would any of these fix vulnerabilities in the handling of
| STARTTLS? And why is any of them required in place of just
| using TLS as part of the initial connection, HTTPS style?
| ttul wrote:
| You can't fix STARTTLS unless receivers stop advertising it.
| That will take until the end of time. Meanwhile, DANE can
| assure that domains can assert their SSL certificate in the
| DNS securely. And MTA-STS can allow DNS to do so, just
| without the assurance of DNSSEC, which implies that
| sophisticated man-in-the-middle attacks can still occur, if
| DNS can be intercepted and modified.
___________________________________________________________________
(page generated 2023-02-10 23:02 UTC)