2014-02-23 72 views
1

我正在使用OpenSSL通过HTTPS连接到我的一台服务器。不过,我似乎无法获得服务器验证在客户端工作。从我所了解的情况来看,没有验证证书让我打开Man In The Middle攻击,但证书验证基本上是寻找证书中的IP地址和域名进行匹配。 (我说很多东西只是为了得到一些详细的回应:))Man in the Middle Attacks and SSL

所以,如果它是我的服务器,我知道它的域名和IP地址,我使用SSL,我应该担心吗?然后,中间的人不能解密我的SSL数据,插入恶意代码,重新加密,然后转发我的服务器证书吗?

最后,如果MITM攻击是一个问题,如果我先用另一个库检查证书来验证,然后使用OpenSSL而不是验证呢?

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

+0

您需要了解公钥和签名。 http://en.wikipedia.org/wiki/Public_key_infrastructure – SLaks

+0

[SSL和中间人误解]的可能重复(http://stackoverflow.com/questions/14907581/ssl-and-man-in-中间误解)和http://stackoverflow.com/questions/11760901/ssl-and-man-in-the-middle-attack?rq=1 – PeeHaa

回答

3

但证书验证基本上是寻找证书中的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(); 

主机名验证

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

如果要针对规范执行手动验证,请参阅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*

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

附近的那家TLS Client OpenSSL的维基的示例程序。它涵盖了服务器证书和链式验证。您必须提供主机名验证的代码。


从我个人理解,不验证证书让我开到中间人攻击

如果不进行验证,你还不如保存周期和选择一个匿名计划,如ADH


所以,如果这是我的服务器,我知道它的域名和IP地址,我使用SSL,我应该担心吗? ......如果MITM攻击是一个问题,如果我先用另一个库检查证书来验证,然后使用OpenSSL而不是验证,那该怎么办? ...有没有可能发生的其他攻击?

它有很多,并没有一个单一的答案。由于您正在构建知道服务器先验的客户端,因此请考虑转向固定方案,以便您可以放弃信任CA和DNS。例如参见OWASP的Certificate and Public Key Pinning

另外,请阅读Peter Guttman的Engineering Security。本书的重要部分讨论了PKI,SSL,TLS和人类行为中的系统性缺陷;以及如何改善您的安全状况。

1

基本上有两种验证对HTTPS:通过服务器/客户端对对方提供

I)进行身份验证证书信任存储。 为此,您必须为服务器/客户端实例实施密钥库/信任库,并将证书添加到密钥库和可信证书以信任商店。这将完成证书验证。

FYI:Keystore and truststore

II)在另一方面HTTPS会做主机名验证以防止中间人攻击。基本上,如果https URL中指定的IP与证书颁发的CommonName匹配,此验证方法将返回“true”。如果您知道哪个ip要信任,则可以覆盖此验证方法。 FYI:Hostname verification

+1

'通用名称'已弃用。 DNS名称应存在于“主题备用名称”(SAN)中。 – jww

+0

是的,它已被弃用,但仍广泛使用。更好的方法是首先检查SAN,如果它不存在,然后去CN。 – Razz

+1

如果CN存在,那么它也必须列在SAN中。请参见[公开信托证书颁发和管理的基准要求](https://cabforum.org/wp-content/uploads/Baseline_Requirements_V1_1_6.pdf)。它也可能出现在[RFC 6125](http://tools.ietf.org/html/rfc6125)中(但我没有检查)。 – jww

相关问题