web-dev-qa-db-fra.com

Pourquoi les requêtes Python ignorent-elles le paramètre verify?

Le problème

J'ai essayé d'utiliser le paquet de requêtes de Python pour télécharger l'URL suivante:

https://service.isracard.co.il/I_logon.jsp

Dans Chrome, le certificat semble valide:

 enter image description here

Cependant, en Python, la requête échoue avec SSLV3_ALERT_HANDSHAKE_FAILURE, même si en utilisant l'indicateur verify qui ignore les certificats erronés:

Les demandes peuvent également ignorer la vérification du certificat SSL si vous définissez vérifier à False

Trace de la pile

>>> requests.__version__
'2.7.0'
>>> LOGIN_URL = 'https://service.isracard.co.il/I_logon.jsp'
>>> requests.get(LOGIN_URL, verify=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/private/tmp/sslenv/lib/python2.7/site-packages/requests/api.py", line 69, in get
    return request('get', url, params=params, **kwargs)
  File "/private/tmp/sslenv/lib/python2.7/site-packages/requests/api.py", line 50, in request
    response = session.request(method=method, url=url, **kwargs)
  File "/private/tmp/sslenv/lib/python2.7/site-packages/requests/sessions.py", line 465, in request
    resp = self.send(prep, **send_kwargs)
  File "/private/tmp/sslenv/lib/python2.7/site-packages/requests/sessions.py", line 573, in send
    r = adapter.send(request, **kwargs)
  File "/private/tmp/sslenv/lib/python2.7/site-packages/requests/adapters.py", line 431, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:590)

Environnement

OS et packages

J'utilise les demandes 2.7.0 et Python 2.7.10 dans un environnement virtuel sous OSX.

cURL

l'appel de cURL à la même URL sur la même machine fonctionne bien:

 $ curl -I https://service.isracard.co.il/I_logon.jsp
HTTP/1.1 200 OK
Date: Fri, 18 Sep 2015 11:37:27 GMT
Server: IBM_HTTP_Server
X-Powered-By: Servlet/3.0
Set-Cookie: JSESSIONID=0000R90MxFKBVxBMV665syGfjnh:-1; Path=/; HttpOnly
Expires: Thu, 01 Dec 1994 16:00:00 GMT
Cache-Control: no-cache="set-cookie, set-cookie2"
Set-Cookie: Alt50_ZLinuxPrd=94742720.30755.0000; expires=Fri, 18-Sep-2015 12:07:19 GMT; path=/
Content-Type: text/html; charset=ISO-8859-8
Content-Language: iw-IL
Set-Cookie: ServiceP=53323968.20480.0000; path=/
10
Adam Matan

La validation du certificat n'a pas échoué, l'argument verify ne s'applique donc pas ici. Ce qui a échoué est la négociation de chiffrement; aucun des chiffrements requests ne veut utiliser une correspondance avec ceux que le serveur est prêt à utiliser.

Si vous exécutez votre commande curl avec le commutateur -v, vous verrez quelle suite de chiffrement a été négociée par curl pour la connexion établie:

$ curl -v -I https://service.isracard.co.il/I_logon.jsp
* Hostname was NOT found in DNS cache
*   Trying 192.118.12.8...
* Connected to service.isracard.co.il (192.118.12.8) port 443 (#0)
* TLS 1.2 connection using TLS_RSA_WITH_RC4_128_SHA
[ .... ]

C'est le chiffre RC4-SHA, qui a quelques problèmes de sécurité plutôt gênants et qui ne devrait pas vraiment être utilisé; il n'offre aucun secret de transfert par exemple. Le package urllib3 (fourni avec requests) par défaut exclut ce chiffrement des chiffrements par défaut. Vous pouvez le rajouter avec:

import requests

requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':RC4-SHA'
try:
    requests.packages.urllib3.contrib.pyopenssl.DEFAULT_SSL_CIPHER_LIST += ':RC4-SHA'
except AttributeError:
    # no pyopenssl support used / needed / available
    pass

et votre demande fonctionne:

>>> import requests
>>> requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':RC4-SHA'
>>> requests.get('https://service.isracard.co.il/I_logon.jsp')
<Response [200]>

Je n’ai pas installé le paquet pyOpenSSL, je ne me suis donc pas soucié de la partie gardée par try..except.

18
Martijn Pieters

Je rencontre également ce problème sur macOS Sierra, Python 2.7.9 et il est corrigé par:

Installation de pipettes Sudo - pyOpenSSL - amélioré par la version installée

C'est probablement dû au fait que le pyOpenSSL est trop vieux.

6
echo

La combinaison de la mise à niveau et de l'installation d'OpenSSL ndg-httpsclient l'a résolue pour moi

Sudo pip install ndg-httpsclient

et

Sudo pip install --ignore-installed pyOpenSSL --upgrade

0
user8716010