HTTPS: Is your URL string secure over SSL?

Given the sensitivity of the customer data stored in Gemfury, security is always on our mind. And with a renewed community focus on Rails security, I hope that our new Gemfury Security Series of articles will help ease your mind about using and building cloud services.

Since we've introduced the Secure-Token-URL as the private Gem source, we've heard concerns about the security of putting a secret in the URL. Some have stated that our attempt at claiming "security" is bogus, and that your account can be easily exposed by sniffing the connection URL despite SSL. This is not true!

Everything except IPs and ports are encrypted when doing HTTP over SSL.

  https://gem.fury.io/452f6E403CDph10714e41/me/

The basis of this statement lies in the layered manner HTTP connections are built. These layers are logically isolated, and when two computers connect, each layer communicates with the corresponding layer in the other computer without the awareness of the other layers. And to describe HTTPS in terms of layers, SSL is done at a layer preceding HTTP.

Here's how a HTTPS connection is built:

  1. The client uses the host portion gem.fury.io of the URL to look up the IP of the server via a DNS request. This is not encrypted.

  2. The client intitates a TCP connection by contacting the server by its IP, specifying the connection port. The two parties acknowledge each other's intent to connect and thus establish a TCP connection. TCP provides the concept of a connection insuring that all packets are received as intended. This is not encrypted.

  3. By connecting to a secure port, the client has implicitly indicated to the server the need for SSL. At this point, the two parties negotiate a shared secret used to encrypt the connection. This negotiation is done via public/private key cryptography and also allows both parties to verify each other's identities via certificates. Everything past this point is encrypted and secure.

  4. The client initiates the HTTP request by sending the path and query portion of the URL, the headers (cookies, user agent, etc), and the optional request body (like your Gem file).

  5. The server replies with its HTTP response and terminates the connection.

As you can see, once a client connects to a server, SSL session is established before the HTTP handshake takes place, ensuring that everything secret stays secret.

Notes

To focus on the basics, I intentionaly overlooked a few things (keep-alive connections, etc). In those situations, the security principles still hold.

Although URLs are secure over the wire, there is no convention of keeping them secure once they've reached the server. If you are not careful, those URLs can leak to your server logs and external analytics providers. To further ensure security of your users' credentials, use cookies and POST bodies for browser clients, and Authorization header (basic auth, OAuth, etc) for APIs.

Another vulnerability is the Referrer header for subsequent requests. The secret URL will be sent as the referrer to any asset (image, script, etc), iframe, or clicked link that's included in that page. If that request is non-SSL or if it is sent to a third-party, the secret-URL will be revealed. (Thanks @hyperair).