Python - request.exceptions.SSLError - dh key is too small

I am clearing some internal pages using Python and queries. I have disabled SSL checks and warnings.

requests.packages.urllib3.disable_warnings() page = requests.get(url, verify=False) 

On some servers, I get an SSL error that I cannot go through with.

 Traceback (most recent call last): File "scraper.py", line 6, in <module> page = requests.get(url, verify=False) File "/cygdrive/c/Users/jfeocco/VirtualEnv/scraping/lib/python3.4/site-packages/requests/api.py", line 71, in get return request('get', url, params=params, **kwargs) File "/cygdrive/c/Users/jfeocco/VirtualEnv/scraping/lib/python3.4/site-packages/requests/api.py", line 57, in request return session.request(method=method, url=url, **kwargs) File "/cygdrive/c/Users/jfeocco/VirtualEnv/scraping/lib/python3.4/site-packages/requests/sessions.py", line 475, in request resp = self.send(prep, **send_kwargs) File "/cygdrive/c/Users/jfeocco/VirtualEnv/scraping/lib/python3.4/site-packages/requests/sessions.py", line 585, in send r = adapter.send(request, **kwargs) File "/cygdrive/c/Users/jfeocco/VirtualEnv/scraping/lib/python3.4/site-packages/requests/adapters.py", line 477, in send raise SSLError(e, request=request) requests.exceptions.SSLError: [SSL: SSL_NEGATIVE_LENGTH] dh key too small (_ssl.c:600) 

This happens both to / from Cygwin, and on Windows and OSX. My research hinted at legacy OpenSSL on the server. I am looking for the perfect client side ideally.

Edit: I was able to solve this using a cipher suite

 import requests requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += 'HIGH:!DH:!aNULL' try: requests.packages.urllib3.contrib.pyopenssl.DEFAULT_SSL_CIPHER_LIST += 'HIGH:!DH:!aNULL' except AttributeError: # no pyopenssl support used / needed / available pass page = requests.get(url, verify=False) 
+7
source share
3 answers

Disabling alerts or verifying a certificate will not help. The main problem is the weak DH key used by the server, which may be misused in a log attack .

To get around this, you need to select a cipher that does not use the Diffie Hellman key exchange and therefore does not affect the weak DH key. And this cipher must be supported by the server. It is not known what the server supports, but you can try it using AES128-SHA encryption or the cipher suite HIGH:!DH:!aNULL

Using queries with your own cipher suite is complex. See Why do Python queries ignore the validation parameter? for example.

+4
source

this is not an additional answer, just try combining the solution code with the question with additional information so that others can copy it directly without additional verification.

These are not only server-side DH issues, but many different libraries are not compatible in python modules.

The code segment below is used to ignore these security issues because it cannot be resolved on the server side. For example, if it is an internal old server, no one wants to update it.

In addition to the hacked string for 'HIGH:!DH:!aNULL' , the urllib3 module can be imported to disable the warning if it has

 import requests import urllib3 requests.packages.urllib3.disable_warnings() requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += 'HIGH:!DH:!aNULL' try: requests.packages.urllib3.contrib.pyopenssl.DEFAULT_SSL_CIPHER_LIST += 'HIGH:!DH:!aNULL' except AttributeError: # no pyopenssl support used / needed / available pass page = requests.get(url, verify=False) 
+4
source

I will pack my decision here. I had to change the Python SSL library, which was possible since I was executing my code in the dock container, but this is something you probably don't want to do.

  1. Get the supported cipher for your server. In my case, there was a third-party mail server, and I used the described script, enter the link description here

check_supported_ciphers.sh

 #!/usr/bin/env bash # OpenSSL requires the port number. SERVER=$1 DELAY=1 ciphers=$(openssl ciphers 'ALL:eNULL' | sed -e 's/:/ /g') echo Obtaining cipher list from $(openssl version). for cipher in ${ciphers[@]} do echo -n Testing $cipher... result=$(echo -n | openssl s_client -cipher "$cipher" -connect $SERVER 2>&1) if [[ "$result" =~ ":error:" ]] ; then error=$(echo -n $result | cut -d':' -f6) echo NO \($error\) else if [[ "$result" =~ "Cipher is ${cipher}" || "$result" =~ "Cipher :" ]] ; then echo YES else echo UNKNOWN RESPONSE echo $result fi fi sleep $DELAY done 

Give him permission:

 chmod +x check_supported_ciphers.sh 

And execute this:

 ./check_supported_ciphers.sh myremoteserver.example.com | grep OK 

After a few seconds, you will see output similar to:

 Testing AES128-SHA...YES (AES128-SHA_set_cipher_list) 

So we will use " AES128-SHA " as the SSL cipher.

  1. Forced error in your code:

    Tracing (the last call was the last): file "my_custom_script.py", line 52, in the file imap = IMAP4_SSL (imap_host) "/usr/lib/python2.7/imaplib.py", line 1169, in init IMAP4. File init (self, host, port) "/usr/lib/python2.7/imaplib.py", line 174, in file init self.open (host, port) "/usr/lib/python2.7/imaplib. py ", line 1181, in the open file self.sslobj = ssl.wrap_socket (self.sock, self.keyfile, self.certfile) File" /usr/lib/python2.7/ssl.py ", line 931, in ciphers wrap_socket = ciphers) File "/usr/lib/python2.7/ssl.py", line 599, in init self.do_handshake () File "/usr/lib/python2.7/ssl.py", line 828, in do_handshake self._sslobj.do_handshake () ssl.SSLError: [SSL: DH_KEY_TOO_SMALL] dh key too small (_ssl.c: 727)

  2. Get the Python Python library path used, in this case:

    /usr/lib/python2.7/ssl.py

  3. Edit this:

    cp / usr / lib / python2.7 / ssl.py / usr / lib / python2.7 / ssl.py.bak

    vim / usr / lib / python2.7 / ssl.py

And replace:

 _DEFAULT_CIPHERS = ( 'ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20:ECDH+AES256:DH+AES256:' 'ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:RSA+AESGCM:RSA+AES:RSA+HIGH:' '!aNULL:!eNULL:!MD5:!3DES' ) 

From:

 _DEFAULT_CIPHERS = ( 'AES128-SHA' ) 
0
source

All Articles