2

I am trying to send simple GET request with curl using my certificate and private keys:

$curl = curl_init();

curl_setopt_array($curl, array(
    CURLOPT_URL => 'https://example.com',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_SSLCERT => '/path_to/cert.pem',
    CURLOPT_SSLKEY => '/path_to/key.pem',
));

curl_exec($curl);
$error = curl_error($curl);
curl_close($curl);

var_dump($error);
die();

the equivalent command in terminal would be:

curl -GET --key key.pem --cert cert.pem https://example.com

Running this curl i get this error - could not load PEM client certificate, OpenSSL error error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak, (no key found, wrong pass phrase, or wrong file format?)

From my understanding, this is caused because the certificate that i am using is signed with md5 hash. (How to fix SSL issue SSL_CTX_use_certificate : ca md too weak on Python Zeep)

I cant re-create these keys, so the solution i found is to lower the ssl security level (https://askubuntu.com/questions/1233186/ubuntu-20-04-how-to-set-lower-ssl-security-level), to do so i need to edit my /etc/ssl/openssl.cnf file, specifically this part - CipherString = DEFAULT@SECLEVEL=1 (set from SECLEVEL=2, to SECLEVEL=1).

After editing my openssl.cnf, if i run my curl command in terminal - it works. However the problem still remains if i run it in PHP.

I tried setting up different curl options, but nothing seem to work. Here are the curl options that i tried:

CURLOPT_SSL_VERIFYHOST => false
CURLOPT_SSL_VERIFYPEER => false
CURLOPT_SSL_CIPHER_LIST => 'TLSv1'
CURLOPT_SSL_CIPHER_LIST => 'DEFAULT@SECLEVEL=1'

Is there a way to fix this without editing openssl.cnf file by just setting some curl options?

Chris Haas
  • 53,986
  • 12
  • 141
  • 274
Edgar
  • 1,113
  • 3
  • 16
  • 30
  • Having the same issue with a site hosted with 1and1/IONOS. Have no control over certificate so need to change certificate level in cURL request. Seems to ignore changing CURLOPT_SSL_CIPHER_LIST though – BIOSTALL Jul 30 '21 at 08:53

1 Answers1

1

I found out that you can pass custom openssl config to php cli and came up with one possible (ugly) solution to this problem:

  1. Create a separate openssl.cnf file with lowered security settings somewhere in your project:
openssl_conf = default_conf
[ default_conf ]
ssl_conf = ssl_sect
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
MinProtocol = TLSv1.2
CipherString = DEFAULT:@SECLEVEL=1
  1. Create a separate php example.php file that will make a curl request:
$curl = curl_init();

curl_setopt_array($curl, array(
    CURLOPT_URL => 'https://example.com',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_SSLCERT => 'cert.pem',
    CURLOPT_SSLKEY => 'key.pem',
));

$response = curl_exec($curl);
$error = curl_error($curl);
curl_close($curl);
  1. Now call this file and pass the custom openssl config with php cli in your main code via shell_exec:

$cmd = shell_exec("OPENSSL_CONF=openssl.cnf php example.php");

This way you dont need to lower your openssl version/security for your whole project, instead it will be lowered only on this one request. Curl file can be modified to be more dynamic (custom url, query params, keys etc).

Edgar
  • 1,113
  • 3
  • 16
  • 30