Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Security 中间人攻击与SSL攻击_Security_Ssl_Openssl_Ssl Certificate_Man In The Middle - Fatal编程技术网

Security 中间人攻击与SSL攻击

Security 中间人攻击与SSL攻击,security,ssl,openssl,ssl-certificate,man-in-the-middle,Security,Ssl,Openssl,Ssl Certificate,Man In The Middle,我正在使用OpenSSL通过HTTPS连接到我的一台服务器。然而,我似乎无法让服务器验证在客户端工作。从我所了解的,不验证证书让我对中间人开放的攻击,但证书验证基本上是寻找证书内的IP地址和域名匹配。(我说了很多错话,只是为了得到一些完整详细的回答:)) 所以,如果它是我的服务器,我知道它的域名和ip地址,并且我正在使用SSL,我应该担心吗?然后,中间的人不能解密我的SSL数据,插入恶意代码,重新加密,然后转发我的服务器的证书吗? 最后,如果MITM攻击是一个问题,那么如果我先用另一个库检查证书

我正在使用OpenSSL通过HTTPS连接到我的一台服务器。然而,我似乎无法让服务器验证在客户端工作。从我所了解的,不验证证书让我对中间人开放的攻击,但证书验证基本上是寻找证书内的IP地址和域名匹配。(我说了很多错话,只是为了得到一些完整详细的回答:))

所以,如果它是我的服务器,我知道它的域名和ip地址,并且我正在使用SSL,我应该担心吗?然后,中间的人不能解密我的SSL数据,插入恶意代码,重新加密,然后转发我的服务器的证书吗? 最后,如果MITM攻击是一个问题,那么如果我先用另一个库检查证书以进行验证,然后不使用OpenSSL进行验证,该怎么办


是否还有其他可能发生的攻击?

基本上,Https有两种验证:

i) 对服务器/客户端提供的证书进行相互验证信任存储。 为此,您必须为服务器/客户端实例实现密钥库/信任库,并将您的证书添加到密钥库,将受信任的证书添加到信任库。这将完成证书验证

供参考:

另一方面,HTTPS将进行主机名验证,以防止中间人攻击。基本上,如果https url中指定的ip与证书提供的CommonName匹配,则此验证方法将返回“true”。如果您知道要信任哪个ip,则可以重写此验证方法。
仅供参考:

基本上,Https有两种验证:

i) 对服务器/客户端提供的证书进行相互验证信任存储。 为此,您必须为服务器/客户端实例实现密钥库/信任库,并将您的证书添加到密钥库,将受信任的证书添加到信任库。这将完成证书验证

供参考:

另一方面,HTTPS将进行主机名验证,以防止中间人攻击。基本上,如果https url中指定的ip与证书提供的CommonName匹配,则此验证方法将返回“true”。如果您知道要信任哪个ip,则可以重写此验证方法。 供参考:

但证书验证基本上是在证书中查找ip地址和域名以匹配

证书将公钥绑定到实体(个人或组织等身份)。绑定通过来自权威机构的签名进行。验证确保签名存在,并且出示证书的实体就是他们所说的实体

识别对等方的方式是通过DNS名称。如果DNS被破坏,或者主机名检查被忽略,那么系统就会崩溃

因此,您需要同时信任证书颁发机构和DNS。DNS不提供真实性保证(或者更正确地说,客户端不使用安全机制),因此您应该将DNS视为不可信的输入。
然而,我似乎无法让服务器验证在客户端工作

使用OpenSSL,您需要在客户机中完成三件事。首先,您需要确保服务器提供证书。其次,您需要验证链。第三,您需要执行主机名匹配,因为OpenSSL不作为链验证的一部分进行匹配

服务器证书

您需要验证服务器是否有证书,因为某些协议和密码套件不需要证书。您可以通过以下方式实现:

X509* cert = SSL_get_peer_certificate(ssl);
if(cert) { X509_free(cert); }
if(NULL == cert) handleFailure();
链验证

如果您有一个自定义验证回调,但它可以与内置于OpenSSL中的标准验证和自定义验证回调一起工作,则这一点适用。要从链验证中获得验证结果,请执行以下操作:

long res = SSL_get_verify_result(ssl);
if(!(X509_V_OK == res)) handleFailure();
主机名验证

1.0.2之前的OpenSSL不验证主机名。您必须从服务器的证书中提取主机名,并确保其位于您访问的站点。如果您想借用代码,请查看源文件
ssluse.c
中的验证过程

如果要根据规范执行手动验证,请参阅RFC 6125

为完整起见,下面介绍如何获取证书的
使用者备用名称(SAN)中存在的DNS名称。您可以通过类似于SSL\u get\u peer\u certificate的函数获取
X509*

void print_san_name(X509* const cert)
{
    GENERAL_NAMES* names = NULL;
    unsigned char* utf8 = NULL;

    do
    {
        if(!cert) break; /* failed */

        names = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0 );
        if(!names) break;

        int i = 0, count = sk_GENERAL_NAME_num(names);
        if(!count) break; /* failed */

        for( i = 0; i < count; ++i )
        {
            GENERAL_NAME* entry = sk_GENERAL_NAME_value(names, i);
            if(!entry) continue;

            if(GEN_DNS == entry->type)
            {
                int len1 = 0, len2 = -1;

                len1 = ASN1_STRING_to_UTF8(&utf8, entry->d.dNSName);
                if(!utf8) continue;
                len2 = (int)strlen((const char*)utf8);

                /* If there's a problem with string lengths, then     */
                /* we skip the candidate and move on to the next.     */
                /* Another policy would be to fail since it probably  */
                /* indicates the client is under attack.              */
                if(len1 != len2) {
                    fprintf(stderr, "Strlen and ASN1_STRING size do not match
                            "(embedded null?): %d vs %d\n", len2, len1);

                    /* Potential problem with the DNS name. Skip it */
                    /* TODO: test against IDNs                      */
                    OPENSSL_free(utf8), utf8 = NULL;

                    continue;
                }

                /* Perform matching here */
                fprintf(stdout, "  SAN: %s\n", utf8);

                OPENSSL_free(utf8), utf8 = NULL;
            }
            else
            {
                fprintf(stderr, "  Unknown GENERAL_NAME type: %d\n", entry->type);
            }
        }

    } while (0);

    if(names)
        GENERAL_NAMES_free(names);

    if(utf8)
        OPENSSL_free(utf8);    
}
void print\u san\u name(X509*常数证书)
{
通用名称*名称=空;
无符号字符*utf8=NULL;
做
{
如果(!cert)中断;/*失败*/
name=X509\u get\u ext\u d2i(证书,NID\u主题\u alt\u名称,0,0);
如果(!name)中断;
int i=0,count=sk\u GENERAL\u NAME\u num(名称);
如果(!count)中断;/*失败*/
对于(i=0;i类型)
{
int len1=0,len2=-1;
len1=ASN1\u字符串到\u UTF8(&UTF8,条目->d.dNSName);
如果(!utf8)继续;
len2=(int)strlen((const char*)utf8);
/*如果字符串长度有问题,那么*/
/*我们跳过这个候选人,继续下一个*/
/*另一个政策是失败,因为它可能*/
/*表示客户端受到攻击*/
if(len1!=len2){
fprintf(标准字符),标准字符和ASN1_字符串大小不匹配
“(嵌入的空值?)%d对%d\n”,len2,len1);
/*DNS名称可能存在问题。请跳过它*/
/*TODO:针对IDN的测试*/
OPENSSL_free(utf8),utf8=NU