中间人攻击和SSL [英] Man In the Middle Attacks and SSL

查看:119
本文介绍了中间人攻击和SSL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用OpenSSL通过HTTPS连接到我的一台服务器.但是,我似乎无法让服务器验证在客户端上起作用.据我了解,不验证证书会使我容易受到中间人攻击"的影响,但证书验证基本上是在寻找证书中要匹配的IP地址和域名. (我说很多事情都是错误的,只是为了得到一些完整的详细答复:))

I am using OpenSSL to connect over HTTPS to one of my servers. However I cannot seem to get server verification to work on the client side. From what I understand, not verifying the certificate leaves me open to Man In the Middle attacks, but the certificate verification is basically looking for the ip address and domain name within the certificate to match. (I am saying a lot of things wrong just to get some full detailed responses :) )

因此,如果它是我的服务器,我知道它的域名和ip地址,并且我正在使用SSL,是否应该担心?再说一次,中间的人还是不能解密我的ssl数据,插入恶意代码,重新加密,然后再将服务器的证书转发给我吗?

So if it's my server, I know its domain name and ip address, and I am using SSL, should I be worried? Then again, couldn't the man in the middle decrypt my ssl data, insert malicious code, re-encrypt, and then forward me my server's certificate anyway?

最后,如果是MITM攻击,那么如果我先与另一个库检查证书以进行验证,然后仅不进行验证就使用OpenSSL怎么办?

Lastly, if MITM attacks are an issue, what if I check the certificate with another library first to verify, and then use OpenSSL just not with verification?

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

Are there any other attacks that could happen?

推荐答案

但是证书验证基本上是在证书中寻找要匹配的IP地址和域名

but the certificate verification is basically looking for the ip address and domain name within the certificate to match

证书将公钥绑定到实体(诸如个人或组织之类的身份).绑定是通过授权机构的签名进行的.验证可确保存在签名,并且出示证书的实体就是他们所说的身份.

A certificate binds a public key to an entity (an identity like a person or organization). The binding occurs via a signature from an authority. Validation ensures the signature is present, and the entity presenting the certificate is who they say they are.

识别对等方的方法是通过DNS名称.如果DNS受到威胁,或者省略了主机名检查,则系统崩溃.

The way you identify the peer is through DNS names. If DNS is compromised, or the hostname checks are omitted, then the system crumbles.

所以您需要同时信任证书颁发机构和DNS . DNS不提供真实性保证(或更正确地说,客户端不使用安全机制),因此您应将DNS视为不受信任的输入.

So you need to trust both the certification authority and DNS. DNS does not provide authenticity assurances (or more correctly, clients don't use the security mechanisms), so you should consider DNS as untrusted input.

但是,我似乎无法在客户端进行服务器验证.

However I cannot seem to get server verification to work on the client side.

使用OpenSSL,您需要在客户端中执行三件事.首先,您需要确保服务器出示证书.其次,您需要验证链.第三,您需要执行主机名匹配,因为OpenSSL不会将其作为链验证的一部分.

With OpenSSL, you need to do three things in the client. First, you need to ensure the server presents a certificate. Second, you need to verify the chain. Third, you need to perform hostname matching because OpenSSL doe not do it as part of chain verification.

服务器证书

您需要验证服务器是否具有证书,因为某些协议和密码套件不需要证书.您可以执行以下操作:

You need to verify the server has a certificate because some of the protocols and cipher suites don't require a certificate. You can do that with:

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

链验证

如果您有一个自定义的验证回调,则适用此方法,但它同时适用于OpenSSL内置的标准验证和一个自定义的验证回调.要从链验证中获取验证结果,请执行:

This applies if you have a custom verify callback, but it works with both the standard verification built into OpenSSL and a custom verify callback. To get the verify result from chain verification, perform:

long res = SSL_get_verify_result(ssl);
if(!(X509_V_OK == res)) handleFailure();

主机名验证

1.0.2之前的OpenSSL 验证主机名.您将必须从服务器的证书中提取主机名,并确保其访问了您的站点.如果您想借用代码,请查看 libcurl 以及源文件.

OpenSSL prior to 1.0.2 does not verify hostnames. You will have to extract the hostnames from the server's certificate and ensure its the site you visited. If you want to borrow the code, take a look at libcurl and the verification procedure in source file ssluse.c.

如果您要针对某个规范执行手动验证,请参见RFC 6125,域的表示和验证-传输层安全性(TLS)上下文中使用X.509(PKIX)证书的Internet公钥基础结构中的基本应用程序服务身份.

If you want to perform the manual verification against a spec, see RFC 6125, Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS).

出于完整性考虑,以下是获取证书的Subject Alternate Names(SAN)中存在的DNS名称的方法.您可以从SSL_get_peer_certificate之类的函数中获取X509*.

For completeness, here's how to fetch the DNS names present in the Subject Alternate Names (SAN) of a certificate. You can get the X509* from a function like SSL_get_peer_certificate.

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);    
}


OpenSSL Wiki上有一个示例程序,位于 TLS客户端.它涵盖了服务器证书和链验证.您将必须提供用于主机名验证的代码.


There's a sample program on the OpenSSL wiki at TLS Client. It covers the Server Certificate and Chain Verification. You will have to provide the code for Hostname Verification.

据我了解,不验证证书会使我容易受到中间人攻击

From what I understand, not verifying the certificate leaves me open to Man In the Middle attacks

如果不执行验证,则最好保存周期并选择ADH之类的匿名方案.

If you don't perform validation, you might as well save the cycles and choose an anonymous scheme like ADH.

因此,如果它是我的服务器,我知道它的域名和ip地址,并且我正在使用SSL,我应该担心吗? ...如果出现MITM攻击,如果我先与另一个库检查证书以进行验证,然后仅不进行验证就使用OpenSSL,该怎么办? ...还有其他可能发生的攻击吗?

So if it's my server, I know its domain name and ip address, and I am using SSL, should I be worried? ... if MITM attacks are an issue, what if I check the certificate with another library first to verify, and then use OpenSSL just not with verification? ... Are there any other attacks that could happen?

有很多东西,而且没有一个答案.由于您正在建立了解服务器先验的客户端,因此请考虑采用固定方案,以便您可以放弃对CA和DNS的信任.例如,请参阅OWASP的证书和公钥固定.

There's a lot to it, and there's no single answer. Since you are building clients that know the server a priori, consider moving to a pinning scheme so you can forgo trusting CAs and DNS. See for example, OWASP's Certificate and Public Key Pinning.

此外,请阅读Peter Guttman的工程安全.本书很大一部分讨论了PKI,SSL,TLS和人类行为方面的系统性缺陷.以及如何改善安全状况.

Also, read Peter Guttman's Engineering Security. A significant portion of the book discusses the systemic defects in PKI, SSL, TLS and human behavior; and how you can improve your security posture.

这篇关于中间人攻击和SSL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆