Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change/tweak Python 3.10 default SSL settings for requests - sslv3 alert handshake failure

The issue:

Python 3.10 increased the default security settings of the TLS stack. Awesome. I have a legacy application running something that theses settings do not like. I don't know what exactly. How do tweak these settings to let my request through?

The story:

I'm writing a small script to extract some information from a Jazz RTC instance running on premise. It clearly has a... problematic ssl certificate. Nothing that a "verify=False" shouldn't fix. Well, it does not. When I run the following code in python 3.10...

if __name__ == '__main__':

    headers = {'Content-Type': 'application/x-www-form-urlencoded'}

    data = {
        'j_username': username,
        'j_password': password
    }

    result = requests.post(url, data=data, headers=headers, verify=False).json

    print(result)

... i get this handshake error.

requests.exceptions.SSLError: HTTPSConnectionPool(host='...', port=...): Max retries exceeded with url: /ccm/authenticated/j_security_check (Caused by SSLError(SSLError(1, '[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:997)'))

BUT, it works without a problem on Python 3.9. Looking around for an answer, I found out about the heightened security defaults added to python 3.10, like this question... but nothing on how to tweak them to make this work with my requests.

The details:

This is what the browser developer tools report

  • As usual, this is a very limited enterprise environment. I can't do much. No admin privileges.
  • The department responsible for that host, as expected, says it can't be fixed, giving some shallow excuses.
  • "If it works on 3.9, why not use it?" - Well, several reasons. The major one being 3.10 is the version accepted for use in the company environment. If they even find out I sneaked in a conda 3.9 venv to test stuff, I'll get a mean lecture.

Any help is appreciated! o/

like image 981
Kliff Kast Avatar asked Sep 03 '25 03:09

Kliff Kast


2 Answers

@PatrickMevzek 's comment led me to other queries and this question.

Which showed me how to change the used ciphers AND security level. The following snippet from @bgoeman worked for my environment:

import requests
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'ALL:@SECLEVEL=1'

Obviously, in general THIS SHOULD NOT BE USED. This will allow for man-in-the-middle attacks and other nasty things. Be careful and mindful when changing these settings.

like image 124
Kliff Kast Avatar answered Sep 04 '25 23:09

Kliff Kast


@PatrickMevzek provided the correct answer. I'd like to provide an example for the httpx library as well.

import httpx
import ssl
cert = (
    certificate_file,
    key_file,
    password,
)

context = ssl.SSLContext()
ciphers = ":".join([
    "@SECLEVEL=1", #python 3.10 default is SECLEVEL=2 which rejects less secure ciphers
    "ALL",
])
context.set_ciphers(ciphers)

return httpx.AsyncClient(cert=cert, verify=context)
like image 35
DaManJ Avatar answered Sep 05 '25 01:09

DaManJ