【问题标题】:PHP curl lower SSL security (ca md too weak error)PHP curl 降低 SSL 安全性(ca md too weak 错误)
【发布时间】:2021-10-04 05:06:54
【问题描述】:

我正在尝试使用我的证书和私钥通过 curl 发送简单的 GET 请求:

$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();

终端中的等效命令是:

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

运行这个 curl 我得到这个错误 - 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?)

据我了解,这是因为我使用的证书是用 md5 哈希签名的。 (How to fix SSL issue SSL_CTX_use_certificate : ca md too weak on Python Zeep)

我无法重新创建这些密钥,所以我找到的解决方案是降低 ssl 安全级别 (https://askubuntu.com/questions/1233186/ubuntu-20-04-how-to-set-lower-ssl-security-level),为此我需要编辑我的 /etc/ssl/openssl.cnf 文件,特别是这部分 - CipherString = DEFAULT@SECLEVEL=1 (设置从 SECLEVEL=2 到 SECLEVEL=1)。

编辑我的openssl.cnf 后,如果我在终端中运行我的 curl 命令 - 它可以工作。但是,如果我在 PHP 中运行它,问题仍然存在。

我尝试设置不同的 curl 选项,但似乎没有任何效果。 以下是我尝试过的 curl 选项:

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

有没有办法在不编辑 openssl.cnf 文件的情况下通过设置一些 curl 选项来解决这个问题?

【问题讨论】:

  • 使用 1and1/IONOS 托管的网站也存在同样的问题。无法控制证书,因此需要在 cURL 请求中更改证书级别。似乎忽略了更改 CURLOPT_SSL_CIPHER_LIST

标签: php ssl curl openssl php-curl


【解决方案1】:

我发现您可以将自定义 openssl 配置传递给 php cli,并提出了一种可能的(丑陋的)解决方案:

  1. 在项目中的某处创建一个单独的 openssl.cnf 文件,降低安全设置:
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. 创建一个单独的 php example.php 文件,该文件将发出 curl 请求:
$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. 现在调用此文件并通过shell_exec 在主代码中使用php cli 传递自定义openssl 配置:

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

这样你就不需要为你的整个项目降低你的 openssl 版本/安全性,相反,它只会在这个请求时降低。可以将 curl 文件修改为更具动态性(自定义 url、查询参数、键等)。

【讨论】:

    猜你喜欢
    • 2022-06-16
    • 2014-11-26
    • 2012-12-30
    • 2017-12-11
    • 2018-07-12
    • 2013-02-03
    • 2012-03-10
    • 1970-01-01
    • 2021-10-30
    相关资源
    最近更新 更多