【问题标题】:Preventing spoofing of remote server with PHP & cURL使用 PHP 和 cURL 防止远程服务器的欺骗
【发布时间】:2012-10-17 17:21:52
【问题描述】:

我正在编写从远程服务器请求机密数据的 php 脚本。 我正在使用 cURL 来获取远程服务器的证书信息(请在下面查看其输出)。

我需要检查哪些数组键来验证证书的有效性,这样没有人可以欺骗它们?

例如,密钥 [certinfo][0][Subject][CN] 可以被自签名证书欺骗。

我可以只检查我在客户端使用的 ca-bundle 文件的 md5 文件哈希,但是当服务器的证书到期时,我需要相应地替换 ca-bundle 文件,并在 php 脚本中更新 md5 文件哈希 -这对我来说是不可接受的。唯一的默认是替换 ca-bundle 文件而不更新 php 脚本。为此,我需要验证服务器证书的属性,这些属性在未来的证书重新生成过程中保持不变,并且不能被不法分子欺骗。

print_r(curl_getinfo($ch)):

[url] => https://remoteserver.com
[content_type] => text/html
[http_code] => 200
[header_size] => 148
[request_size] => 79
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 0.374
[namelookup_time] => 0
[connect_time] => 0.062
[pretransfer_time] => 0.203
[size_upload] => 0
[size_download] => 20618
[speed_download] => 55128
[speed_upload] => 0
[download_content_length] => -1
[upload_content_length] => 0
[starttransfer_time] => 0.281
[redirect_time] => 0
[certinfo] => Array
    (
        [0] => Array
            (
                [Subject] => Array
                    (
                        [OU] => Globe Standard SSL
                        [CN] => www.remoteserver.com
                    )

                [Issuer] => Array
                    (
                        [C] => US
                        [O] => Globe Hosting, Inc.
                        [OU] => GlobeSSL DV Certification Authority
                        [CN] => GlobeSSL CA
                    )

                [Version] => 2
                [Signature Algorithm] => sha1WithRSAEncryption
                [Start date] => 2011-09-30 00:00:00 GMT
                [Expire date] => 2014-09-30 23:59:59 GMT
                [Public Key Algorithm] => rsaEncryption
                [RSA Public Key] => 2048
                [rsa(n)] => d7:c0:0b:3f:f3:3e:d6:ed:92:56:22:12:64:c1:c4:00:d7:c9:a1:1e:..cut..
                [rsa(e)] => 01:00:01:
                [X509v3 Authority Key Identifier] => keyid:C3:AB:A0:02:F0:9B:F5:66:7F:28:15:92:22:95:DB:B8:4E:D3:93:08
                [X509v3 Subject Key Identifier] => 13:1B:B2:52:14:3C:70:1C:B2:93:F1:C5:04:06:86:60:8A:D4:E5:5C
                [X509v3 Key Usage] => DigitalSignature,KeyEncipherment
                [X509v3 Basic Constraints] => CA:FALSE
                [X509v3 Extended Key Usage] => TLSWebServerAuthentication,TLSWebClientAuthentication
                [X509v3 Certificate Policies] => Policy:1.3.6.1.4.1.6449.1.2.2.27, CPS:http://www.globessl.com/docs/GlobeSSL_CPS.pdf
                [X509v3 CRL Distribution Points] => URI:http://crl.globessl.com/GlobeSSLDVCertificationAuthority.crl
                [Authority Information Access] => CAIssuers-URI:http://crt.globessl.com/GlobeSSLDVCertificationAuthority.crt, OCSP-URI:http://ocsp.globessl.com
                [X509v3 Subject Alternative Name] => DNS:www.remoteserver.com,DNS:remoteserver.com
                [Signature] => 61:38:06:d4:30:9c:14:a4:e5:1e:b2:c8:c4:..cut..
                [Cert] => -----BEGIN CERTIFICATE-----cut-----END CERTIFICATE-----

            )

        [1] => Array
            (
                [Subject] => Array
                    (
                        [C] => US
                        [O] => Globe Hosting, Inc.
                        [OU] => GlobeSSL DV Certification Authority
                        [CN] => GlobeSSL CA
                    )

                [Issuer] => Array
                    (
                        [C] => SE
                        [O] => AddTrust AB
                        [OU] => AddTrust External TTP Network
                        [CN] => AddTrust External CA Root
                    )

                [Version] => 2
                [Signature Algorithm] => sha1WithRSAEncryption
                [Start date] => 2010-06-22 00:00:00 GMT
                [Expire date] => 2020-05-30 10:48:38 GMT
                [Public Key Algorithm] => rsaEncryption
                [RSA Public Key] => 2048
                [rsa(n)] => a0:47:04:ce:a8:33:ab:..cut..
                [rsa(e)] => 01:00:01:
                [X509v3 Authority Key Identifier] => keyid:AD:BD:98:7A:34:B4:26:F7:FA:C4:26:54:EF:03:BD:E0:24:CB:54:1A
                [X509v3 Subject Key Identifier] => C3:AB:A0:02:F0:9B:F5:66:7F:28:15:92:22:95:DB:B8:4E:D3:93:08
                [X509v3 Key Usage] => CertificateSign,CRLSign
                [X509v3 Basic Constraints] => CA:TRUE,pathlen:0
                [X509v3 Certificate Policies] => Policy:1.3.6.1.4.1.6449.1.2.2.27
                [X509v3 CRL Distribution Points] => URI:http://crl.usertrust.com/AddTrustExternalCARoot.crl
                [Authority Information Access] => CAIssuers-URI:http://crt.usertrust.com/AddTrustExternalCARoot.p7c, CAIssuers-URI:http://crt.usertrust.com/AddTrustUTNSGCCA.crt, OCSP-URI:http://ocsp.usertrust.com
                [Signature] => 66:9c:13:6d:d2:7e:2c:..cut..
                [Cert] => -----BEGIN CERTIFICATE-----cut-----END CERTIFICATE-----

            )

    )

感谢您的帮助。

【问题讨论】:

  • 我们可以找一些security people 来调查一下吗?
  • 为您的证书制作 ca 并将其添加到运行 curl 的机器上,因此如果使用其他证书,您总是会收到错误
  • 添加到@eicto,Facebook 已经在使用 FB SDK 进行此操作。你可能想看看...
  • @Christian FB 在做什么?欺骗 ssl 证书?
  • @eicto 不,FB SDK 中有一些证书可能用于确保 FB 响应有效。

标签: php ssl curl spoofing


【解决方案1】:
$ch=curl_init("https://default_cert");
curl_setopt($ch, CURLOPT_CAINFO, getcwd().'mydefault.cert');
curl_setopt ($ch,CURLOPT_CERTINFO,1);
curl_setopt ($ch,CURLOPT_VERBOSE,1);
curl_exec($ch) or die;
print_r( curl_getinfo($ch) );

在这种情况下,如果 mydefault.cert 包含不正确的 CN,curl exec 将失败,否则证书将被 中间的人欺骗

mydefault.cert 应该包含远程主机的证书。您必须使用受信任的渠道获取它(或者当您确定此时远程主机是受信任的时,至少使用CURLOPT_SSL_VERIFYPEER,FALSE 下载一次)。

一些理论:

  • selfsignednot selfsigned 证书的区别如下 - selfsigned 是人为自己签发的,它有密钥和证书部分,而 非自签名 也由您信任的人签名。它可以是证书中心,也可以是您最好的朋友,也可以是您的老板。如果您最好的朋友签发自签名证书并且您通过授权方式获得证书(他在磁盘上给您,或者使用自己的 pgp 密钥用它签署一封信,或者他从证书中间告诉它的 20 个字符),您可以使用它作为 CA 的证书。
  • 证书本身就是一个公钥的加密对,key就是那个对的私钥。因此,网站执行以下操作 - 它使用 私钥 以电子方式 签署 自己的内容,在另一端客户端 crypt 使用 的内容公钥。与使用 PGP 时相同。
  • 从服务器到客户端的数据使用加密算法之一加密,例如 ES、3DES、 Blowfish、CAST128 或 Arcfour,在客户端授权主机为受信任后由客户端初始化的算法密钥,该密钥由服务器的 公钥 加密(在 https 的情况下为证书)在来自客户端的数据之后到服务器也被该算法加密,如使用上述方案完成的密钥交换。

更多信息在google

您可以使用此架构来欺骗服务器发送给客户端的任何数据吗?

【讨论】:

  • 这不是仅依赖 ca-bundle 的选项,因为它可以简单地被另一个自签名证书替换。在这种情况下,您必须验证 ca-bundle 是真实的,但如果没有将文件的哈希硬编码到脚本,这是不可能的。
  • 主机证书如果是一次,是不能被其他证书替代的,学习ssl认证的数学部分,如果你觉得可以,就试试吧。
  • 我可以使用salt,但是如果要解码1个文件,这个salt可以用于其他文件。由于需要此代码的文件数量众多,因此无法为每个文件选择唯一的盐。
  • @AlexanderMalygin 你对密码学一无所知。
  • 带有封闭密钥的简单示例:2k 长度密钥,它知道服务器和客户端,说客户端想要向服务器发送加密信息,它发送随机字符串 -salt(也说 2k 长度)和数据由 xor(salt,md5sum(key,salt)) 进行异或,在每 100k 的数据客户端和服务器通过更改 salt 重新握手后,该算法不如 ssl 好,因为密钥是固定的,但密钥本身在传输过程中从未恢复,并且很难解密它。如果您想要真正的安全性 - 使用 ssl
【解决方案2】:

没有太多方法可以完全防止欺骗,但是,就像浏览器一样,您可以尝试验证证书的真实性。有关 SSL 证书如何工作的一些有用信息,请点击以下链接:

How are ssl certificates verified?

现在,您可以做一些事情来确保您正在与正确的机器通信,即使没有完全验证证书,但它们将要求您有权访问远程机器。最简单的事情之一就是使用加盐变量进行各种简单的握手。

例如,调用远程计算机上生成唯一哈希的文件,例如,用您选择的单词加盐的时间戳,以及到目前为止您握手的次数。您的计算机将该哈希值与预期值匹配,并使用不同的盐执行相同的操作,将其发送回远程计算机,指示握手已完成,并且两台计算机都会增加它们的计数,以便下次哈希值不同。

【讨论】:

  • 我有固定数量的文件,这些文件要求机密数据,不能被欺骗。在您的情况下,如果有人解码 1 个文件,他将能够使用其他文件的哈希来伪造此握手,因为他会知道生成此盐的逻辑。为每个文件制作唯一的盐可以解决这个问题,但这也不是一个选择。
  • 首先,要指出的是,有人欺骗经过验证的 SSL 证书的能力非常非常小。如果您使用的是自签名证书,那么是的,您仍然有问题,但这对于您确实需要保护并且您不想针对手动添加的证书进行验证的数据来说不是一个好主意。也就是说,像 SHA1 这样的散列的意义在于,尤其是在加盐时,它不是可以解密的东西。换句话说,不,第三方无法通过“解码”逻辑来伪造握手,除非你他们盐。
猜你喜欢
  • 1970-01-01
  • 2011-03-03
  • 2017-01-12
  • 2017-05-14
  • 2017-01-08
  • 1970-01-01
  • 2018-04-14
  • 2017-11-21
  • 2013-06-21
相关资源
最近更新 更多