Stop disabling SSL protection with cURL
2011-09-21Background
Several months ago when I was working on FoursquareNotifier, I was made aware of a fairly significant issue with using SSL through cURL. API calls to Foursquare require SSL, which is perfectly fine and a good idea for many API-driven applications. However, all the common examples for how to make API calls to Foursquare (including the PHP classes recommended by Foursquare itself), included setting some innocent-looking, poorly-explained, and potentially dangerous settings. Namely, curl_setopt(CURLOPT_SSL_VERIFYPEER, false)
. This tells cURL to stop caring who answers its request, as long as they use SSL, breaking one of the basic cryptography assumptions that SSL is supposed to provide.
Cryptography advantages
Here's an extremely brief overview of what cryptography is supposed to provide, and what they mean. I'll do a full post on cryptography in PHP later.
- Confidentiality - unintended users cannot read your data
- Integrity - data is not modified in transit
- Authentication - the user is who they say they are. This is lost with the wrong cURL setup
- Non-repudiation - if you receive a cryptographically sign message from someone, they can't deny they sent it
Risks
If you disable SSL verification, all you are asking SSL to do is ensure that the machine on the other end of your call supports SSL and has a certificate. It no longer requires that the certificate/host receiving your request is the one you think it is. All it takes to hijack your data in this case is bad DNS, a compromised hosts file, or any other cause of a man-in-the-middle attack.
The fix
- Tell cURL to verify the certificate it is presented with is recognized by a certificate authority
- Tell cURL to verify the certificate it is presented with is issued to the site it says it is
- Tell cURL where your local certs are kept so it can do this verification. This is the hardest step because I can't just tell you where they are on your local system, but see the two blog posts linked below for discussions on this. The short answer is you need to either export a .pem file from your browser or download one from a trusted source.
You owe it to yourself and your users, whether you're providing or consuming APIs via cURL (or higher-level libraries that rely on cURL) to set those SSL options properly, and provide cURL with your local certificates cache so it can verify that the certificate used to sign your data is known and valid.
Resources
- Foursquare API docs: https://developer.foursquare.com/docs/
- Documentation for using cURL in PHP: http://us3.php.net/curl_setopt
- Overview of certificate verification in cURL: http://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/
- Here's some more info with a certificate grabber you can use: http://artur.ejsmont.org/blog/content/how-to-properly-secure-remote-api-calls-from-php-application