Link to home
Start Free TrialLog in
Avatar of Andrew Angell
Andrew AngellFlag for United States of America

asked on

POODLE SSLv3 Vulnerability and PHP cURL Confusion..??

I've been dealing with web service API's for years now using PHP and cURL for HTTP requests.  I've never had to think about too much when it comes to that until now with this POODLE vulnerability that has come to light recently, and now everybody (ie. web service providers) is officially disabling SSLv3 on their servers, which wound up causing some of my PHP products that are communicating with these services to fail.

I first noticed the problem when PayPal disabled SSLv3 on their sandbox servers, so all of my API calls were resulting in a curl_error() getting returned:

"error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure"

All of the research I found says to use TLS instead of SSL, and I was instructed by many different guides (including PayPal's) to set my cURL options to use TLSv1.  As such, I updated my PHP solutions so that cURL is setup with these options.

curl_setopt($curl, CURLOPT_VERBOSE, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_CIPHER_LIST, 'TLSv1');
curl_setopt($curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
curl_setopt($curl, CURLOPT_TIMEOUT, 30);
curl_setopt($curl, CURLOPT_URL, $this->EndPointURL);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $Request);

Open in new window


This worked for me on my server, so I pushed an update to my tools, and lots of clients began updating their websites.  Unfortunately, the fix doesn't seem to be working for everybody, and I can't get a handle on it.

I came across this thread which explains that TLS didn't work in cURL until version 7.36.0.  I am indeed running 7.36.0 on my server, and I did have some people on previous versions get in touch with me about the fact that the update was not working for them.  

I've been telling people that they need to have at least 7.36.0 of cURL, but now that's not always working.  I just now had somebody on 7.38.0 that was getting this error with the TLS options included in the cURL setup:  "Unknown cipher in list: TLSv1"

I simply removed the new TLS options I had added in cURL, and now it's working fine from his server.  

So at this point I'm extremely confused and I have no idea what I'm supposed to do to get this working for everybody regardless of what version of cURL they're running.  I've seen a wide range of cURL versions in the short period of time I've been trying to deal with this.

Any information on this would be greatly appreciated.  Thanks!
Avatar of Dave Baldwin
Dave Baldwin
Flag of United States of America image

When one host I was using changed the SSL/TLS changeover, I ended up using this line:

curl_setopt($ch, CURLOPT_SSLVERSION, 1);  // which is CURL_SSLVERSION_TLSv1

I am not using CURLOPT_SSL_CIPHER_LIST.

Just to note, this is in the BAM compiler which uses PHP4.  TLS has been around a long time.  It's using...

libcurl/7.14.0 OpenSSL/0.9.8a zlib/1.2.3

http://php.net/manual/en/function.curl-setopt.php
Avatar of Andrew Angell

ASKER

See, that's part of what confuses me.  None of the guides I saw for making this change mentioned the CURLOPT_SSL_CIPHER_LIST option, however, when I first made the change on my test server it was not working until I added it, which I did after finding the answer on this thread.

So again, that's yet another variable in the mix that seems to sometimes be necessary and sometimes not.  

So far I've had people on cURL 7.24.0, and that didn't seem to work with the TLS options.  I've had people update from that to 7.36.0 which seems to fix it, and then others who update and it doesn't fix it.  I've had people on 7.38.0 where they had to use numbers instead of the constants values for CURLOPT_SSLVERSION.  

I don't know how I'm supposed to handle all of these different scenarios from within my code..??  I can pull the cURL version from within code and set the curl options accordingly, but I can't come up with any logic that seems to be concrete for any given cURL version.  

The holiday season is just around the corner, and PayPal is officially disabling SSLv3 on their server on 12/3/14.  My PayPal for WooCommerce users are going to be very upset and I'm not going to know what to tell them, especially when some of the hosting companies are refusing to update cURL for people.  

It seems like a huge mess, but at the same I feel like I must be doing something wrong because I don't see any other developers freaking out about it like I am...??
The only items I have in my Paypal code (which is based on the Version 95 code from the PDFs) is this.
	// Turn off the server and peer verification (TrustManager Concept).
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

Open in new window


curl_setopt($ch, CURLOPT_SSLVERSION, 1); isn't in there at all and it's been working for a couple of years on several versions of PHP from 5.2.17 to 5.4.34.  That is several different versions of PHP cURL too.
Right, that's the thing, though.  As of about a month ago SSLv3, which is what cURL typically defaults to, was found to be vulnerable and PayPal (as well as pretty much everybody) is disabling it on their servers.  

Last week, before I added the TLS options to my code, the PayPal sandbox began rejecting all of my API calls with that error about he SSLv3 handshake.  When I added the TLS options that fixed it.  They're disabling it on their live servers on 12/3/14.  

What makes things even more confusing is that now, as of yesterday, PayPal's sandbox is once again accepting my API calls without the TLS options, so they're making it very tough for me to troubleshoot and figure all of this out.  

I have a call with my PayPal partner manager today at 4:00 pm CST. I'll try to get this all worked out and update here after that call.

Have you tried your stuff against the Sandbox in the past few weeks?
No, I haven't tried the Sandbox in a couple of years now.  I was thinking about it as a result of this conversation.  curl_setopt($ch, CURLOPT_SSLVERSION, 0) which is the 'default' is supposed to use the 'default' but I don't actually know what that means.
ASKER CERTIFIED SOLUTION
Avatar of gheist
gheist
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
After some long talks with PayPal it came down to basically what gheist is saying here.  Their "merchant response guide" was very misleading.  Basically, I didn't need to do anything at all with my stuff.  The only people who will have a problem are people on very old environments like gheist mentioned.
So it sounds like I should try the Sandbox code to see if I need to change my live code to ensure that TLSv1 is used?
Dave, yes, I would test your stuff against the sandbox, and as long as you get a good response back then you know you're good, because they have already disabled SSLv3 on their sandbox servers.

Basically, the only time this would be a problem is if you're using a version of OpenSSL prior to 0.9.8, which was released in 1999, so if you are still on that, it'd be recommended to update anyway.
I have two sites using OpenSSL/1.0.1e .
But my Godaddy sites are using NSS/3.14.0.0 for SSL/TLS.
My personal site uses OpenSSL/0.9.8k which is where I would test the Sandbox.
Yeah, probably should get those tested.  Just need to make sure TLS is available.
Ok.  One thing I ran into yesterday on a question about command line cURL was that I had to add the option to not 'CURLOPT_SSL_VERIFYPEER' to make it work.  I think that's what my PHP curl options are set to also as shown in my post above.  I have almost always had to turn that off.
Yeah, I've always turned that off, too.  Here's what I use.

      function CURLRequest($Request = "", $APIName = "", $APIOperation = "", $PrintHeaders = false)
      {
            $curl = curl_init();
                        // curl_setopt($curl, CURLOPT_HEADER,TRUE);
                        curl_setopt($curl, CURLOPT_VERBOSE, 1);
                        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
                        curl_setopt($curl, CURLOPT_TIMEOUT, 30);
                        curl_setopt($curl, CURLOPT_URL, $this->EndPointURL);
                        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
                        curl_setopt($curl, CURLOPT_POSTFIELDS, $Request);
                        
            if($this->APIMode == 'Certificate')
            {
                  curl_setopt($curl, CURLOPT_SSLCERT, $this->PathToCertKeyPEM);
            }
            
            $Response = curl_exec($curl);
            
            /*
             * If a cURL error occurs, output it for review.
             */
            if($this->Sandbox)
            {
                  if(curl_error($curl))
                  {
                        echo curl_error($curl).'<br /><br />';      
                  }
            }
                        
            curl_close($curl);
            return $Response;      
      }
Thanks.  Don't you have to have your own server to use curl_setopt($curl, CURLOPT_SSLCERT, $this->PathToCertKeyPEM); ?
Yes, you don't need to worry about that.  When PayPal first released their API's the only form of authentication they had was a local certificate.  Then they introduced the API un/pw/sig to make it a lot easier, but some people are still using the certificate method, so my libraries provide the option.
Ok, thanks.  How long have you been doing this??
10+ years.
Then you have bigger experience than their phone helpdesk....
Just take care to upgrade openssl to make sure it does not use SSL3.
Since Paypal is splitting from eBay to be a separate company, I'm wondering how that will affect us 'developers'.
If you sell on ebay khm khm you will become a proud double developer...