扭曲的HTTPS请求检查证书

时间:2015-04-30 12:16:39

标签: python ssl https twisted twisted.web

在我扭曲的应用程序中,我想向Akismet发出异步请求来检查垃圾邮件。 Akismet合理地使用HTTPS,因此我一直在关注文档中的web client guide on SSL。但是这部分令我担心:

  

以下是一个示例,说明如何使用Agent来请求没有证书验证的HTTPS URL。

我非常希望证书验证能够防止中间人攻击。那么我该如何添加呢?

我的测试代码没有验证是这样的:

from twisted.internet import reactor
from twisted.web.client import Agent
from twisted.internet.ssl import ClientContextFactory

class WebClientContextFactory(ClientContextFactory):
    def getContext(self, hostname, port):
        print( "getting context for {}:{}".format( hostname, port ) )
        # FIXME: no attempt to verify certificates!
        return ClientContextFactory.getContext(self)

agent = Agent( reactor, WebClientContextFactory() )

def success( response ):
    print( "connected!" )
def failure( failure ):
    print( "failure: {}".format( failure ) )
def stop( ignored ):
    reactor.stop()

agent.request( "GET", "https://www.pcwebshop.co.uk/" )\ # uses self-signed cert
.addCallbacks( success, failure )\
.addBoth( stop )

reactor.run()

我希望由于无法验证证书而导致失败。

2 个答案:

答案 0 :(得分:4)

我使用的是Twisted 15.1.0。

实际上,Agent的默认初始化函数将作为contextFactory传入BrowserLikePolicyForHTTPS,并且具有验证服务器证书的能力。

只需使用:

agent = Agent( reactor )

将产生以下错误:

failure: [Failure instance: Traceback (failure with no frames):     
<class 'twisted.web._newclient.ResponseNeverReceived'>:
[<twisted.python.failure.Failure <class 'OpenSSL.SSL.Error'>>]]

确保使用pip安装了service_identity包。

如果您需要自定义证书验证,可以通过传递pem来创建自定义策略,如here所述:

customPolicy = BrowserLikePolicyForHTTPS(
    Certificate.loadPEM(FilePath("your-trust-root.pem").getContent())
)
agent = Agent(reactor, customPolicy)

答案 1 :(得分:2)

感谢您指出这一点。这似乎是文档中的一个错误。在14.0版之前,它是准确的; Twisted不会验证HTTPS,这是一个大问题。但是,正如您在the release notes for that version中看到的,Twisted(至少在版本14.0及更高版本中)确实在使用Agent进行的HTTPS连接上验证TLS。 (对于getPage,旧的,坏的HTTP客户端,它仍然没有这样做;不要使用getPage。)

我已提交this bug来跟踪修复文档的准确性。