In old days, websites and servers use a lot of plain HTTP, and there are countless attacks on them. Even Comcast man-in-the-middle attacked their customers to warn them of potential copyright infringement.
Thanks to the efforts of pioneers including Mozilla, Let’s Encrypt, Cloudflare and so on, the Web is almost all protected by TLS now. People would see a secure lock in the address bar and knows the website they are surfing is secure. No more random popups, and people believe they have defeated adversaries.
Not only ordinary consumers, I find most developers think HTTPS is secure and free of all kind of attacks. But it’s absolutely not true, and I’m not talking about situations when people ignore invalid certificate warnings. The baddest risk is that you don’t know it’s dangerous.
TLS 1.3 and 0-RTT
TLS 1.3 is widely supported nowadays and one of its performance improvements is called 0‑RTT (zero round‑trip time). It makes it possible to resume TLS sessions faster, by reducing the number of round trips between client and server when re‑establishing an encrypted session.
All popular web servers, proxies and CDN providers, including NGINX, HAProxy, Cloudflare, just to name a few, have added this feature as soon as its standard was finalized by IETF, some even when it was just a draft.
However, performance has tradeoffs. Cloudflare wrote the potential risks clearly in its 0-RTT launching blog post and enabled this feature for all its free customers by default.
Unlike any other requests sent over TLS, requests sent as part of 0-RTT resumption are vulnerable to what’s called a replay attack. If an attacker has access to your encrypted connection, they can take a copy of the encrypted 0-RTT data (containing your first request) and send it to the server again pretending to be you. This can result in the server seeing repeated requests from you when you only sent one.
Not all engineers understand all the tradeoffs, and they would trust the features or tools provided to them by big players at most time. Someday they would be complained by customers that their account balances dropped to zero, or their sensitive information leaked even when 0-RTT only enabled for GET requests.
With 0-RTT enabled, it’s very likely to be replay attacked, considering VPN and CDN are so overwhelming advertised.
I’m not saying 0-RTT is completely useless, just people need to be fully warned.
CDN and Proxies
There is no doubt that Cloudflare is doing a successful business, and almost 15% websites use its service as reverse proxy. More and more engineers choose some CDN services to protect their websites, even some very small blogs.
Cloudflare has contributed a lot to the Web security and performance, but it doesn’t mean they won’t do bad things. Consider Google now, its Chrome, its abusive trackers everywhere.
When you use a CDN to protect and improve your server, even if you have full strict TLS enabled, you should know that all your client and server data are now clearly and transparently passing through the CDN servers.
They are able to do all kind of man-in-the-middle attack to your service. And if they have bugs in their system or you don’t have correct configurations for their service, you may find weird things. Some unconscious attacks happen.
For example, if you protect your dynamic HTTPS API with Cloudflare and have “Always On” enabled, you may find many of your requests return 502. Or even worse, the authenticated
GET /me requests for different users will have the same response!
Besides CDN, the server side proxies, client side proxies are also pretty common in a corporate environment. Corporate security policies might contemplate the addition of custom certificates in workstations’ web browsers in order to be able to inspect encrypted traffic.
Application Layer Protection
CDN is always a good solution to improve your user experience, so I can’t stop using Cloudflare. People just need to have proper warnings in mind, and know exactly the potential risks.
With these circumstances, HTTPS is obviously not enough to protect our API, and we need to add more application layer protections.
- Request ID to ensure the response is actually for your request.
- Request ID and timestamp limit to prevent replay attack.
- Sign every request and response with application session keys.
- Besides HTTPS, use a separate certificate to authenticate.
With these application layer improvements for all endpoints, the API will be protected from MITM attacks of 0-RTT and proxies.