Perché le richieste Python ignorano il parametro di verifica?

Il problema

Ho cercato di utilizzare il pacchetto di richieste Python per scaricare il seguente URL:

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

In Chrome, il certificato sembra valido:

inserisci la descrizione dell'immagine qui

Tuttavia, in Python, la richiesta non riesce con SSLV3_ALERT_HANDSHAKE_FAILURE , anche quando si utilizza il flag di verify che ignora i certificati errati:

Le richieste possono anche ignorare la verifica del certificato SSL se si imposta la verifica su False

Traccia dello stack

 >>> 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 "", line 1, in  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) 

Ambiente

SO e pacchetti

Sto usando le richieste 2.7.0 e Python 2.7.10 in un ambiente virtuale su OSX.

arricciare

la chiamata cURL allo stesso URL sulla stessa macchina funziona bene:

  $ 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=/ 

La convalida del certificato non ha avuto esito negativo, quindi l’argomento di verify non si applica qui. Ciò che ha fallito è la negoziazione dei codici; nessuna delle requests crittografia è disposta ad utilizzare corrispondenze con quelle che il server è disposto a utilizzare.

Se si esegue il comando di curl con l’ -v , verrà visualizzato quale pacchetto di crittografia è stato negoziato da curl per la connessione riuscita:

 $ 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 [ .... ] 

Questo è il codice RC4-SHA, che ha alcuni problemi di sicurezza piuttosto fastidiosi e non dovrebbe essere realmente utilizzato; per esempio non offre il segreto in avanti . Il pacchetto urllib3 (in bundle con le requests ) esclude per default quella cifra dalle cifrature predefinite. Puoi aggiungerlo di nuovo con:

 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 

e la tua richiesta funziona:

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

Non ho installato il pacchetto pyOpenSSL, quindi non mi sono preoccupato di try..except parte protetta.

Ci sono anche su macOS Sierra, Python 2.7.9 ed è risolto da:

sudo pip installa –ignore-installed pyOpenSSL –upgrade

Probabilmente è dovuto al fatto che pyOpenSSL è troppo vecchio.

La combinazione dell’aggiornamento OpenSSL e l’installazione di ndg-httpsclient risolto per me

sudo pip install ndg-httpsclient

e

sudo pip install --ignore-installed pyOpenSSL --upgrade