如何使用python检索远程主机的TLS/SSL对等证书?
问题描述:
我需要扫描IP列表并从该IP上的证书检索公用名称(对于每个允许端口443连接的IP)。我已经能够成功地使用套接字和ssl模块来做到这一点。它适用于具有有效签名证书的所有IP,但不适用于自签名证书。如何使用python检索远程主机的TLS/SSL对等证书?
如果我用这个方法,它需要由我的CA-束验证的有效证书:
from socket import socket
import ssl
s = socket()
c = ssl.wrap_socket(s,cert_reqs=ssl.CERT_REQUIRED, ca_certs='ca-bundle.crt')
c.connect(('127.0.0.1', 443))
print c.getpeercert()
如果我删除cert_reqs=ssl.CERT_REQUIRED
然后它连接但没有拿到证书都没有。
如何在IP上检索证书的公用名称,而不管它是否针对ca-bundle进行验证?
答
python的ssl库似乎只是解析出你的证书,如果它有一个有效的签名。
"""Returns a formatted version of the data in the
certificate provided by the other end of the SSL channel.
Return None if no certificate was provided, {} if a
certificate was provided, but not validated."""
你仍然可以得到与ssl.get_server_certificate()
功能的服务器证书,但它在PEM格式返回。 (或者,你可以调用c.getpeercert(True)
,它返回二进制DER格式的证书,无论是验证或不。)
>>> print ssl.get_server_certificate(('server.test.com', 443))
-----BEGIN CERTIFICATE-----
MIID4zCCAsugAwIBA.....
从这里,我会用M2Crypto或OpenSSL的阅读证书,并获得价值:
# M2Crypto
cert = ssl.get_server_certificate(('www.google.com', 443))
x509 = M2Crypto.X509.load_cert_string(cert)
x509.get_subject().as_text()
# 'C=US, ST=California, L=Mountain View, O=Google Inc, CN=www.google.com'
# OpenSSL
x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
x509.get_subject().get_components()
#[('C', 'US'),
# ('ST', 'California'),
# ('L', 'Mountain View'),
# ('O', 'Google Inc'),
# ('CN', 'www.google.com')]
答
在Mac上,您需要安装痛饮和M2Crypto
在终端运行:
brew install swig
然后:
sudo pip install m2crypto
然后你可以运行上面的代码:
from socket import socket
import ssl
import M2Crypto
import OpenSSL
# M2Crypto
cert = ssl.get_server_certificate(('www.google.com', 443))
x509 = M2Crypto.X509.load_cert_string(cert)
print x509.get_subject().as_text()
# 'C=US, ST=California, L=Mountain View, O=Google Inc, CN=www.google.com'
# OpenSSL
x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
print x509.get_subject().get_components()
#[('C', 'US'),
# ('ST', 'California'),
# ('L', 'Mountain View'),
# ('O', 'Google Inc'),
# ('CN', 'www.google.com')]
另外值得注意的是,如果您通过ssl.getpeercert(True)提取证书,则需要使用OpenSSL.crypto.FILETYPE_ASN1而不是FILETYPE_PEM来加载它 –
由于SSLv3中的“Poodle”漏洞许多Web服务器已禁用它。如果您看到类似“sslv3警报握手故障”的类似信息,则可能需要将'ssl_version = ssl.PROTOCOL_TLSv1'添加到您的'get_server_certificate(..)'调用中。 –
M2Crypto调用SocketServer,它在python3下更改为socketserver。 M2Crypto将在python3下破解。 – mootmoot