?
Solved

PHP: cURL over HTTPS and CURLOPT_SSL_VERIFYPEER

Posted on 2014-09-20
15
Medium Priority
?
746 Views
Last Modified: 2014-09-20
I have a couple of sites that I control.   I need to post data from site one to site two.   I don't need a response from site two, just post a couple of variables and stay on site one.   If I use https, I found I can use CURLOPT_SSL_VERIFYPEER set to false to allow the https connection.  

I assume this should be safe since I control both sites.  What needs to be added to use CURLOPT_SSL_VERIFYPEER set to true/default?
 
$url = 'https://my_other_site.com/test.php';
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_POST, 1);

 curl_setopt($ch, CURLOPT_POSTFIELDS,
          http_build_query(
              array(
                  'var1' => urlencode('abc123'),
                  'var2 => urlencode('xyz456')
              )
          )
 );

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

$response = curl_exec ($ch);


if($response) 
{
	echo  $response;
}
else
{
	echo curl_error($ch);
}
    
curl_close ($ch);

Open in new window

0
Comment
Question by:Scott Fell,  EE MVE
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 5
  • 3
  • +2
15 Comments
 
LVL 58

Accepted Solution

by:
Gary earned 2000 total points
ID: 40334408
Set it to to true
Also need if the path is different from the curl default.
curl_setopt ($ch, CURLOPT_CAINFO, "/pathto/cacert.pem");

If you don't have an up to date ca cert bundle then get it from
http://curl.haxx.se/

p.s.
curl doesn't come with a CA bundle by default anymore, so it's likely you don't have them.
0
 
LVL 11

Expert Comment

by:Radek Baranowski
ID: 40334414
In other words you need to obtain public key of site two certificate and place it on a trust store on site one for it to be able to verify if ssl connection from site two uses known and valid certificate.
0
 
LVL 53

Author Comment

by:Scott Fell, EE MVE
ID: 40334458
The path to cert from site one?
0
WordPress Tutorial 4: Recommended Plugins

Now that you have WordPress installed, understand the interface, and know how to install new parts, let’s take a look at our recommended plugins.

 
LVL 11

Expert Comment

by:Radek Baranowski
ID: 40334464
If site one had ssl up and running the best way to obtain is public key is to open its https port in browser,save the certificate and add it to trust store on site two. You might need to use opensll tools to convert it to pem format of That's what curl needs.
0
 
LVL 11

Expert Comment

by:Radek Baranowski
ID: 40334466
*openssl
0
 
LVL 58

Expert Comment

by:Gary
ID: 40334468
No the path to the certs on site one - it needs to be able to negotiate what site 2 is sending.
Since curl doesn't come with any CA certs then it doesn't negotiate a verifiable secure connection (verify peer set to false will accept any ssl certificate).
0
 
LVL 58

Expert Comment

by:Gary
ID: 40334474
Does site 2 have a real ssl cert and not a self generated one? If it's self generated then you may as well just use false, as true would never work anyway
0
 
LVL 53

Author Comment

by:Scott Fell, EE MVE
ID: 40334477
I have real certs on both sites
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 40334483
You can use cURL POST for this and you can also use fSockOpen() to make a post-method request.  A safe design for this handshake process, used by PayPal, goes something like this:

1. Site A prepares the post data and saves the post arguments in the database
2. Site A makes a post to Site B.
3. Site B makes a post back to Site A with "cmd=>verify" in the first request element, with the other request elements appended in order so that Site A can verify the data.
4. Site A looks up the post arguments in the database and if they match, makes a post back to Site B with the word "verified" and if they don't match, responds with "wrong."

If you already have the HTTPS connection, why would you be concerned about using the certificates?
0
 
LVL 53

Author Comment

by:Scott Fell, EE MVE
ID: 40334494
I looked at my authorize.net sdk.  They have a file named cert.pem and the code that access it is
 if ($this->VERIFY_PEER) {
            curl_setopt($curl_request, CURLOPT_CAINFO, dirname(dirname(__FILE__)) . '/ssl/cert.pem');
        } else {
			if ($this->_log_file) {
				file_put_contents($this->_log_file, "----Request----\nInvalid SSL option\n", FILE_APPEND);
			}
			return false;
        }

Open in new window


Would I just make a pem file of one of my certificates?
0
 
LVL 58

Expert Comment

by:Gary
ID: 40334501
So just use the full path to the ssl/cert.pem file for the CAINFO path
0
 
LVL 58

Assisted Solution

by:Gary
Gary earned 2000 total points
ID: 40334504
Not sure if you mean that is already on your server...grab them here.
http://curl.haxx.se/docs/caextract.html
0
 
LVL 53

Author Closing Comment

by:Scott Fell, EE MVE
ID: 40334552
That worked.    I downloaded http://curl.haxx.se/ca/cacert.pem and saved to my server and then used CURLOPT_CAINFO as below (windows) and worked.  

curl_setopt ($ch, CURLOPT_CAINFO, '\inetpub\vhosts\MySite\httpdocs\folder\cacert.pem');
0
 
LVL 35

Expert Comment

by:gr8gonzo
ID: 40334554
Sounds like you're already getting help with the "how" but allow me to respond to: "I assume this should be safe since I control both sites. "

That is a bad assumption. By verifying the remote certificate, you are helping avoid man-in-the-middle attacks. Basically, a malicious user can blast some specially-crafted network packets to your servers, telling your servers that they should route traffic through a different gateway. At this point, the malicious user could route traffic INTENDED for your "Site B" to his/her own server and grab the data. Of course, it's useless to them to grab encrypted data, so part of that process is to use THEIR own SSL certificate instead, so that your "Site A" is encrypting data using the malicious user's SSL public certificate (which identifies itself as "Site B"). Now, when the malicious user's server gets traffic that goes to Site B, it can decrypt the traffic and get to the real data. Optionally, it can then pass on the original request to Site B and return Site B's response back to Site A. This way, it SEEMS like everything is working fine. However, you'll have no idea that there is a server in-between Site A and Site B that is capturing all the original data and responses.

So when you tell cURL to verify the certificate of Site B, it is checking the entire certificate chain (the certificate itself and also the certificates that issued it) to make sure you're actually dealing with the Site B certificate and not some other 3rd party certificate that you're not expecting. And unless the malicious user has access to Site B's private key, they cannot use Site B's certificate to disguise themselves.

Hopefully all of that makes sense and explains why you should always verify peer certificates (even if both sites are 100% trustworthy). :)
0
 
LVL 53

Author Comment

by:Scott Fell, EE MVE
ID: 40334574
Thanks gr8gonzo, great point.  I just read that and that's why I didn't stick with setting CURLOPT_SSL_VERIFYPEER to false.  

Below is what I ended up with where cacert.pem is from http://curl.haxx.se/ca/cacert.pem 

$url = 'https://my_other_site.com/test.php';
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_POST, 1);

 curl_setopt($ch, CURLOPT_POSTFIELDS,
          http_build_query(
              array(
                  'var1' => urlencode('abc123'),
                  'var2 => urlencode('xyz456')
              )
          )
 );

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // changed to true
curl_setopt ($ch, CURLOPT_CAINFO, '\inetpub\vhosts\MySite\httpdocs\folder\cacert.pem');  //added

$response = curl_exec ($ch);


if($response) 
{
	echo  $response;
}
else
{
	echo curl_error($ch);
}
    
curl_close ($ch);

Open in new window

0

Featured Post

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Part of the Global Positioning System A geocode (https://developers.google.com/maps/documentation/geocoding/) is the major subset of a GPS coordinate (http://en.wikipedia.org/wiki/Global_Positioning_System), the other parts being the altitude and t…
Build an array called $myWeek which will hold the array elements Today, Yesterday and then builds up the rest of the week by the name of the day going back 1 week.   (CODE) (CODE) Then you just need to pass your date to the function. If i…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
Suggested Courses

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question