I know next to nothing when it comes to the how and why of https connections. Obviously, when I'm transmitting secure data like passwords or especially credit card information, https is a critical tool. What do I need to know about it, though? What are the most common mistakes you see developers making when they implement it in their projects? Are there times when https is just a bad idea? Thanks!
views:
1538answers:
9Be sure that, when on an HTTPS page, all elements on the page come from an HTTPS address. This means that elements should have relative paths (e.g. "/images/banner.jpg") so that the protocol is inherited, or that you need to do a check on every page to find the protocol, and use that for all elements.
NB: This includes all outside resources (like Google Analytics javascript files)!
The only down-side I can think of is that it adds (nearly negligible) processing time for the browser and your server. I would suggest encrypting only the transfers that need to be.
I would suggest any time any user data is stored in a database and communicated, use https. Consider this requirement even if the user data is mundane, because even many of these mundane details are used by that user to identify themselves on other websites. Consider all the random security questions your bank asks you (like what street do you live on?). This can be taken from address fields really easily. In this case, the data is not what you consider a password, but it might as well be. Furthermore, you can never anticipate what user data will be used for a security question elsewhere. You can also expect that with the intelligence of the average web user (think your grandmother) that that tidbit of information might make up part of that user's password somewhere else.
One pointer if you use https
make it so that if the user types http://www.website-that-needs-https.com/etc/yadda.php they will automatically get redirected to https://www.website-that-needs-https.com/etc/yadda.php (personal pet peeve)
However, if you're just doing a plain html webpage, that will be essentially a one-way transmission of information from the server to the user, don't worry about it.
I would say the most common mistakes when working with an SSL-enabled site are
- The site erroneously redirects users to http from a page as https
- The site doesn't automatically switch to https when it's necessary
- Images and other assets on an https page are being loading via http, which will trigger a security alert from the browser. Make sure all assets are using fully-qualified URIs that specify https.
- The security certificate only works for one subdomain (such as www) but your site actually uses multiple subdomains. Make sure to get a wildcard certificate if you will need it.
An HTTPS, or Secure Sockets Layer (SSL) certificate is served for a site, and is typically signed by a Certificate Authority (CA), which is effectively a trusted 3rd party that verifies some basic details about your site, and certifies it for use in browsers. If your browser trusts the CA, then it trusts any certificates signed by that CA (this is known as the trust chain).
Each HTTP (or HTTPS) request consists of two parts: a request, and a response. When you request something through HTTPS, there are actually a few things happening in the background:
- The client (browser) does a "handshake", where it requests the server's public key and identification.
- At this point, the browser can check for validity (does the site name match? is the date range current? is it signed by a CA it trusts?). It can even contact the CA and make sure the certificate is valid.
- The client then encrypts its request using the server's public key, and only the server can decrypt that message using it's own private key. It also sends its own public key (generated on the fly, usually).
- The server then processes the request normally, and then encrypts the response using the client's public key, and only the client can decrypt it.
Certificates and Hostnames
Certificates are assigned a Common Name (CN), which for HTTPS is the domain name. The CN has to match exactly, eg, a certificate with a CN of "domain.com" will NOT match the domain "www.domain.com", and users will get a warning in their browser.
It is not possible to host multiple domain names on one IP. Because the certificate is fetched before the client even sends the actual HTTP request, and the HTTP request contains the Host: header line that tells the server what URL to use, there is no way for the server to know what certificate to serve for a given request - therefore, each domain being secured needs its own IP address. You can serve other non-HTTPS sites on the same IP, however.
The one exception to this is with wildcard certificates. It is possible to get a certificate like ".domain.com" in which case "www.domain.com" and "foo.domain.com" will both be valid for that certificate. However, note that "domain.com" does not match ".domain.com", and neither does "foo.bar.domain.com". If you use "www.domain.com" for your certificate, you should redirect anyone at "domain.com" to the "www." site. If they request https://domain.com, unless you host it on a separate IP and have two certificates, the will get a certificate error.
Forms
Strictly speaking, if you are submitting a form, it doesn't matter if the form page itself is not encrypted, as long as the submit URL goes to an https:// URL. In reality, users have been trained (at least in theory) not to submit pages unless they see the little "lock icon", so even the form itself should be served via HTTPS to get this.
Traffic and Server Load
HTTPS traffic is much bigger than its equivalent HTTP traffic (due to encryption and certificate overhead), and it also puts a bigger strain on the server (encrypting and decrypting). If you have a heavily-loaded server, it may be desirable to be very selective about what content is served using HTTPS.
Best Practices
The site should automatically redirect between HTTPS and HTTP as required. When you are doing anything involving sensitive data (logging in, setting up users passwords, looking at any data that other people should not see) you should be using HTTPS.
Any resources on the page should come from the same scheme being used for the page. If you try to fetch images from http:// when the page is loaded with HTTPS, the user will get security warnings. You should either use fully-qualified URLs, or another easy way is to use absolute URLs that do not include the hostname (eg, src="/images/foo.png") because they work for both.
- This includes external resources (eg, Google Analytics)
Don't do POSTs (form submits) when changing from HTTPS to HTTP. Most browsers will flag this as a security warning.
All very good tip here... but I just want to add something..
Ive seen some sites that gives you a http login page and only redirect you to https after you post your username/pass.. This means the username is transmitted in the clear before the https connection is established..
In short make the page where you login from ssl, instead of posting to an ssl page.
I'm not going to go in depth on SSL in general, gregmac did a great job on that, see below ;-).
However, some of the most common (and critical) mistakes made (not specifically PHP) with regards to use of SSL/TLS:
- Allowing HTTP when you should be enforcing HTTPS
- Retrieving some resources over HTTP from an HTTPS page (e.g. images, IFRAMEs, etc)
Directing to HTTP page from HTTPS page unintentionally - note that this includes "fake" pages, such as "about:blank" (I've seen this used as IFRAME placeholders), this will needlessly and unpleasantly popup a warning.
Web server configured to support old, unsecure versions of SSL (e.g. SSL v2 is common, yet horribly broken) (okay, this isn't exactly the programmer's issue, but sometimes noone else will handle it...)
Web server configured to support unsecure cipher suites (I've seen NULL ciphers only in use, which basically provides absolutely NO encryption) (ditto)
Self-signed certificates - prevents users from verifying the site's identity.
Requesting the user's credentials from an HTTP page, even if submitting to an HTTPS page. Again, this prevents a user from validating the server's identity BEFORE giving it his password... Even if the password is transmitted encrypted, the user has no way of knowing if he's on a bogus site - or even if it WILL be encrypted.
Non-secure cookie - security-related cookies (such as sessionId, authentication token, access token, etc.) MUST be set with the "secure" attribute set. This is important! If it's not set to secure, the security cookie, e.g. SessionId, can be transmitted over HTTP (!) - and attackers can ensure this will happen - and thus allowing session hijacking etc. While you're at it (tho this is not directly related), set the HttpOnly attribute on your cookies, too (helps mitigate some XSS).
Overly permissive certificates - say you have several subdomains, but not all of them are at the same trust level. For instance, you have www.yourdomain.com, dowload.yourdomain.com, and publicaccess.yourdomain.com. So you might think about going with a wildcard certificate.... BUT you also have secure.yourdomain.com, or finance.yourdomain.com - even on a different server. publicaccess.yourdomain.com will then be able to impersonate secure.yourdomain.com.... While there may be instances where this is okay, usually you'd want some separation of privileges...
That's all I can remember right now, might re-edit it later...
As far as when is it a BAD idea to use SSL/TLS - if you have public information which is NOT intended for a specific audience (either a single user or registered members), AND you're not particular about them retrieving it specifically from the proper source (e.g. stock ticker values MUST come from an authenticated source...) - then there is no real reason to incur the overhead (and not just performance... dev/test/cert/etc).
However, if you have shared resources (e.g. same server) between your site and another MORE SENSITIVE site, then the more sensitive site should be setting the rules here.
Also, passwords (and other credentials), credit card info, etc should ALWAYS be over SSL/TLS.
I found that trying to <link>
to a non-existent style sheet also caused security warnings. When I used the correct path, the lock icon appeared.
Sorry for butting in but I would like to know too how to move from https to http without a message box appearing on the visitors browser.