Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if a website is using SSL using CURL

Tags:

php

curl

ssl

I'm building a script that will check if a website is using SSL or not. For example, we use "http://www.google.com/" it will be redirected to "https://www.google.com/". How can I check that? I'm using the following cURL codes to get headers of a website.

<?php
$url = 'https://www.google.com';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url); // set url
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6"); // set browser/user agent
curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header'); // get header
curl_exec($ch);

function read_header($ch, $string) {
    print "Received header: $string";
    return strlen($string);
}
?>

Output:

HTTP/1.1 302 Found 
Cache-Control: private 
Content-Type: text/html; charset=UTF-8 
Location: https://www.google.co.in/?gfe_rd=cr&ei=YEAkV7SEFrTv8wexyy0 
Content-Length: 259 
Date: Sat, 30 Apr 2016 05:19:28 GMT 
Alternate-Protocol: 443:quic 
Alt-Svc: quic=":443"; ma=2592000; v="33,32,31,30,29,28,27,26,25" 
like image 643
Gijo Varghese Avatar asked Apr 30 '16 04:04

Gijo Varghese


People also ask

Does curl check SSL certificate?

curl performs peer SSL certificate validation by default. This is done using a certificate store that the SSL library can use to make sure the peer's server certificate is valid.

Does curl use SSL?

Curl will automatically establish an SSL connection with the server. When Curl sends a request to an HTTPS URL, it checks the SSL certificate against the certificate store of the local CA.

Does curl use HTTP or HTTPS?

The client, curl, sends an HTTP request. The request contains a method (like GET, POST, HEAD etc), a number of request headers and sometimes a request body.

Does curl use HTTPS by default?

curl defaults to HTTP/1.1 for HTTP servers but if you connect to HTTPS and you have a curl that has HTTP/2 abilities built-in, it attempts to negotiate HTTP/2 automatically or falls back to 1.1 in case the negotiation failed. Non-HTTP/2 capable curls get 1.1 over HTTPS by default.


2 Answers

PHP - cURL

I think using cURL is an overkill but anyways here you go.

<?php
function ignoreHeader( $curl, $headerStr ) {
  return strlen( $headerStr );
}

$curl = curl_init( "https://example.com/" );
curl_setopt( $curl, CURLOPT_NOBODY, TRUE );
curl_setopt( $curl, CURL_HEADERFUNCTION, 'ignoreHeader' );
curl_exec( $curl );

$result = false;
if ( curl_errno($curl) == 0 ) {
  $info = curl_getinfo( $curl );
  if ( $info['http_code'] == 200 ) {
    $result = true;
  }
}
?>

PHP - without cURL

If you want to check if a website has an SSL certificate. You can just open a stream and check for SSL certificate parameter.

<?php
// Create a stream context
$stream = stream_context_create ( array( "ssl" => array( "capture_peer_cert" => true ) ) );

// Bind the resource 'https://www.example.com' to $stream
$read   = fopen( "https://www.example.com", "rb", false, $stream );

// Get stream parameters
$params  = stream_context_get_params( $read );

// Check that SSL certificate is not null
// $cert should be for example "resource(4) of type (OpenSSL X.509)" 
$cert   = $params["options"]["ssl"]["peer_certificate"];
$result = ( !is_null( $cert ) ) ? true : false;
?>

If you want to check if a host accepts a connection on 443 port, you can use fsockopen to initiate a socket connection with the host.

<?php
// Set host and port. 
$host   = 'example.com';
$port   = 443;

// Initiate a socket connection with 'example.com' and check the result. 
$fp     = fsockopen('ssl://'. $host, $port, $errno, $errstr, 30);
$result = ( !is_null( $fp ) ) ? true : false;
?>
like image 199
Shivam Mathur Avatar answered Sep 17 '22 20:09

Shivam Mathur


In order to satisfy the requirement "is this site using SSL" we need to first understand what "using SSL" actually means.

In the context of an HTTP client, it typically means that the server is at least listening on the standard SSL port (port 443) for HTTP requests. So a good first check could be to simply try initiating a TCP connection to remote server on that port. If the remote host accepts the connection we at least know whether or not to try and if it doesn't we know it's not listening on the standard SSL port.

For this cURL is a little too high level. So instead we can try with fsockopen which makes it possible to simply open this internet connection on the specified port and get enough information back to know what we need. Does the remote host even listen on this port or accept connections there?

function connect($host, $port, $timeOut = 5) {
    $fp = fsockopen($host, $port, $errno, $errstr, $timeOut);
    if (!$fp) {
        printf("It looks like the host '%s' does not accept connections on port %d - error #%d [%s]\n", $host, $port, $errno, $errstr);
        return true;
    } else {
        fclose($fp); // we know it's listening
        printf("It looks like the host '%s' does accept connections on port %d\n", $host, $port);
        return false;
    }
}

$host = "www.google.com";
$port = 443;
connect($host, $port);

This doesn't actually confirm whether or not the remote host is in fact using SSL to communicate, but it does at least tell you whether or not it's worth trying to talk to the server on the standard SSL port. It's a cheap way to do it because we don't attempt to send a request over SSL first. If you want to attempt further sending a request over https from there and confirming that the response is successful via curl, you can certainly do that as well.

Though based on your question I think you're assuming that just because the server sends a location header over HTTP that this somehow concludes the site is using SSL. This is not true. The remote host can accept traffic over both ports, and often does. The remote host also may not redirect all traffic over the standard HTTP port to the SSL port (i.e. by attempting to redirect to https from http). The remote host, in fact, may not be listening on port 80 at all. It might be relying on something like HSTS or HTTP Strict Transport Security.

In all cases, the only way to confirm for sure that a remote host is using SSL transport via HTTP is actually successfully establish the connection. The fact that an https request via curl successfully produces a response would conclude that to some extent, assuming you're going through all the proper SSL channels like verifying the peer certificate and remote identity.

like image 26
Sherif Avatar answered Sep 21 '22 20:09

Sherif