在python的请求lib中禁用SSL证书验证是否安全?

时间:2017-01-19 11:11:00

标签: python python-requests pyopenssl

我很清楚,一般来说,事实并非如此。但在我的特殊情况下,我正在编写一个简单的python web-scraper,它将每小时作为一个cron作业运行,我想确保忽略验证不存在风险通过将verify设置为False来获取SSL证书。

P.S。 我设置禁用此功能的原因是因为在尝试发出请求时response = requests.get('url')它会引发SSLError并且我不知道如何处理它。

编辑:

好的,在sigmavirus24和其他人的帮助下,我终于设法解决了这个问题。以下是我如何做到的解释:

  • 我在https://ssllabs.com/进行了测试,根据SSLLabs提供的报告,由于"不完整的证书链"而导致SSL错误上升。问题(有关证书验证如何工作的更多详细信息,请阅读sigmaviruses24'答案)。

就我而言,其中一名中间人失踪了。

  • 我使用谷歌搜索其指纹并以.pem格式下载。
  • 然后我用了#34; certifi" (它是一个用于提供Mozilla的CA Bundle的python包。如果你没有它,你可以用sudo pip install certifi安装它)来找到根证书(再次通过它的指纹) 。这可以按如下方式完成:

    $ ipython
    In [1]: import certifi
    In [2]: certifi.where()
    Out[2]: /usr/lib/python3.6/site-packages/certifi/cacert.pem
    In [3]: quit
    
    $ emacs -nw /usr/lib/python3.6/site-packages/certifi/cacert.pem
    

或者在bash中,您可以发出$ emacs -nw $(python -m certifi)来打开cacert.pem文件。

  • 在一个文件中将两个证书合并在一起,然后提供其验证参数的路径。

另一种(更简单但并非总是可行)的方法是从SSLLabs下载整个链,就在"附加证书(如果提供)和#34;之前。那里的" Downlaod服务器链"按钮。单击它,将链保存在.pem文件中,并在调用请求的get方法时,提供验证参数的文件路径。

3 个答案:

答案 0 :(得分:2)

这可能更适合https://security.stackexchange.com/

实际上它只比使用HTTP而不是HTTPS更好地略微。所以几乎所有(除了没有服务器证书,有人必须积极做某事)的HTTP风险都适用。

基本上可以看到中间人攻击中发送和接收的数据......或者即使该网站被盗用并且证书被盗了。如果您正在为该网站存储cookie,那么如果您使用用户名和密码登录,那么这些cookie将被泄露(例如,如果facebook.com然后会话令牌被盗),那么它也可能被盗。

检索后,您对该数据做了什么?你下载任何可执行代码?您是否正在下载某些内容(您存储在网络服务器上的图像?),熟练的攻击者(甚至通过修改路由器上的DNS设置等操作)可能会强制您下载文件(“news.php”)并存储在你的网络服务器可以变成可执行的(.php脚本而不是网页)?

答案 1 :(得分:2)

这里的正确答案是“它取决于”。

你给我们的信息很少,所以我会做一些假设并在下面列出(如果其中任何一个不匹配,那么你应该重新考虑你的选择):

  1. 您经常连接到CRON工作中的同一网站
  2. 您对网站了如指掌并确定与证书相关的错误是良性的
  3. 您没有向网站发送敏感数据以便抓取(例如登录和用户名)
  4. 如果是这种情况(我猜它是这样的话)那么它通常应该是无害的。也就是说,它是否“安全”取决于您在两台计算机通过互联网相互交谈的情况下对该词的定义。

    正如其他人所说,请求不会尝试呈现HTML,解析XML或执行JavaScript。因为它只是检索您的数据,所以您运行的最大风险是没有从您认为来自的服务器接收可以验证的数据。但是,如果您将请求与执行上述操作的请求结合使用,则会有大量潜在的攻击,中间的恶意攻击者可能会使用这些攻击。

    还有一些选项意味着您无需放弃验证。例如,如果服务器使用自签名证书,您可以获得PEM格式的证书,将其保存到文件中,并将该文件的路径提供给verify参数。然后,请求将能够为您验证证书。

    所以,正如我所说,这取决于。

    根据Albert的回复更新

    所以似乎正在发生的是有问题的网站只发送有效的叶子证书。本网站依赖于浏览器行为,目前的工作原理如下:

    浏览器连接到网站,并注意到该网站未发送完整的证书链。然后它会检索中介,验证它们并完成连接。但是,请求使用OpenSSL进行验证,OpenSSL不包含任何此类行为。由于验证逻辑几乎完全在OpenSSL中,因此在这种情况下,Requests无法模拟浏览器。

    此外,安全工具(例如,SSLLabs)已开始根据网站的安全性排名计算此配置。越来越多的人认为网站应该发送整个链条。如果您遇到没有的网站,请与他们联系并告知他们这是最好的前进方向。

    如果网站拒绝更新其证书链,则请求用户可以检索PEM编码的中间证书并将其粘贴到.pem文件中,然后将其提供给verify参数。目前,请求仅在其信任库中包含根证书(与每个浏览器一样)。它永远不会发送中间证书,因为它太多了。因此,将中间人包含在根证书包中将允许您验证网站的证书。 OpenSSL将有一个PEM编码文件,其中包含链中的每个链接,并且能够验证根证书。

答案 2 :(得分:1)

来自文档:

  

如果将verify设置为False,请求也可以忽略验证SSL证书。

     
    

requests.get('https://kennethreitz.com',verify = False)     

  

如果您未在请求中使用敏感信息,则“安全”。

你不能把病毒放在HTML本身(据我所知),Javascript可能是一个漏洞,因此Python不会处理它。

总而言之,你应该是安全的