Upgrade to Pro — share decks privately, control downloads, hide ads and more …

EuroPython 2018: SSLError, what now?

EuroPython 2018: SSLError, what now?

https://ep2018.europython.eu/conference/talks/sslerror-now-what
Videos: https://cheimes.fedorapeople.org/sslerror2018/

TLS/SSL is the most important and widely-used protocol for secure and encrypted communication, e.g. HTTPS. It offers more than just encryption. TLS also ensures data integrity and strong authentication with X.509 certificates. But it provides merely a false sense of security, if you use it wrong.

Have you ever encountered ssl.SSLError: [SSL: CERTIFICATEVERIFYFAILED], while connecting to a server, but you didn’t understand what is going on? Are you running production code without TLS/SSL protection or with certificate validation disabled, because you couldn’t figure out how to make it work correctly?

I’ll give you the rundown of the basic cryptographic building blocks, protocol handshake, inner structure of certificates, and PKI. You’ll learn about the best practices, debugging tools and tips how to diagnose TLS/SSL and how to deal with certificates.

Christian Heimes

July 25, 2018
Tweet

More Decks by Christian Heimes

Other Decks in Programming

Transcript

  1. SSLError, EuroPython 2018 Who am I? • from Hamburg/Germany •

    Linux user since 1997 • Python and C developer • Python core developer since 2008 • maintainer of ssl and hashlib module • Python security team • Contributor to OpenSSL
  2. SSLError, EuroPython 2018 Professional life • Senior Software Engineer at

    Red Hat • Security Engineering • FreeIPA Identity Management • Dogtag PKI • Custudia secrets management
  3. SSLError, EuroPython 2018 Agenda • History • high level view

    • Connection errors • Crypto 101, ciphers • TLS handshake • Certificates / Root CA • Hostname verification • Summary, Resources • Questions
  4. SSLError, EuroPython 2018 TLS has exactly one performance problem: it

    is not used widely enough. Everything else can be optimized. https://istlsfastyet.com/
  5. SSLError, EuroPython 2018 Troy Hunt, I wanna go fast: HTTPS'

    massive speed advantage https://www.troyhunt.com/i-wanna-go-fast-https-massive-speed-advantage/
  6. SSLError, EuroPython 2018 Troy Hunt, I wanna go fast: HTTPS'

    massive speed advantage https://www.troyhunt.com/i-wanna-go-fast-https-massive-speed-advantage/
  7. SSLError, EuroPython 2018 Secure Sockets Layer / Transport Layer Security

    • SSL 1.0 – never released • SSL 2.0 – 1995 • SSL 3.0 – 1996: complete redesign • TLS 1.0 – 1999: minor improvements, new name • TLS 1.1 – 2006: mitigation against CBC attacks, explicit IV • TLS 1.2 – 2008: AES, AEAD (GCM), better PRF (SHA-256) • TLS 1.3 – 2014, 2015, 2016, 2017, 2018?
  8. SSLError, EuroPython 2018 TLS libraries • OpenSSL • LibreSSL (OpenBSD,

    partly incompatible fork) • BoringSSL (Google, API incompatible fork) • NSS (Mozilla Firefox) • SChannel (Microsoft) • Secure Transport (Apple) • more: GnuTLS, Java JSSE, Go crypto/tls, kTLS
  9. SSLError, EuroPython 2018 Python libraries • ssl module • PyOpenSSL

    • python-nss • urllib3.contrib.securetransport • more...
  10. SSLError, EuroPython 2018 ssl module $ python3 >>> import socket,

    ssl >>> ctx = ssl.create_default_context() >>> ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) >>> ctx.load_default_certs() >>> ctx.verify_mode, ctx.check_hostname (<VerifyMode.CERT_REQUIRED: 2>, True) >>> with socket.create_connection(('www.python.org', 443)) as sock: ... with ctx.wrap_socket(sock, ... server_hostname='www.python.org') as ssock: ... ssock.sendall(b'') $ python3 >>> import socket, ssl >>> ctx = ssl.create_default_context() >>> ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) >>> ctx.load_default_certs() >>> ctx.verify_mode, ctx.check_hostname (<VerifyMode.CERT_REQUIRED: 2>, True) >>> with socket.create_connection(('www.python.org', 443)) as sock: ... with ctx.wrap_socket(sock, ... server_hostname='www.python.org') as ssock: ... ssock.sendall(b'')
  11. SSLError, EuroPython 2018 Wikipedia definition Transport Layer Security (TLS) –

    and its predecessor, Secure Sockets Layer (SSL) – are cryptographic protocols that provide communications security over a computer network. The TLS protocol aims primarily to provide privacy and data integrity between two communicating computer applications.
  12. SSLError, EuroPython 2018 TLS core features • encrypted transport stream

    • application protocol agnostic • integrity check • replay attack protection • strong authentication of server • strong authentication of client (optional) • extensible protocol
  13. SSLError, EuroPython 2018 TLS standard • IETF standard (Internet engineering

    task force) • IANA (Internet assigned number authority) • TLS (TCP) / DTLS (UDP) • ASN.1 • PKI with X.509 certificates
  14. SSLError, EuroPython 2018 Why is TLS/SSL hard • networking (DNS,

    routing, IPv4, IPv6, TCP) • complex protocol • cryptography • ASN.1 • PKI / certificates
  15. SSLError, EuroPython 2018 TLS handshake DNS lookup TCP handshake ClientHello

    ServerHello ... ... Finish ... ... Finish ... HTTP GET ...
  16. SSLError, EuroPython 2018 Connection issues • socket.gaierror: [Errno -2] Name

    or service not known • ConnectionRefusedError: [Errno 111] Connection refused • [SSL: WRONG_ssl.c:8VERSION_ssl.c:8NUMBER] wrong version number • OSError: [Errno 0] Error • connection blocks / timeout
  17. SSLError, EuroPython 2018 DNS $ host www.python.org www.python.org is an

    alias for dualstack.python.map.fastly.net. dualstack.python.map.fastly.net has address 151.101.36.223 dualstack.python.map.fastly.net has IPv6 address 2a04:4e42:9::223 $ dig www.python.org $ host www.python.org www.python.org is an alias for dualstack.python.map.fastly.net. dualstack.python.map.fastly.net has address 151.101.36.223 dualstack.python.map.fastly.net has IPv6 address 2a04:4e42:9::223 $ dig www.python.org
  18. SSLError, EuroPython 2018 ping / traceroute $ ping www.python.org PING

    www.python.org(2a04:4e42:9::223 (2a04:4e42:9::223)) 56 data bytes 64 bytes from 2a04:4e42:9::223 (2a04:4e42:9::223): icmp_seq=1 ttl=57 time=16.5 ms 64 bytes from 2a04:4e42:9::223 (2a04:4e42:9::223): icmp_seq=2 ttl=57 time=15.5 ms $ traceroute www.python.org traceroute to www.python.org (151.101.36.223), 30 hops max, 60 byte packets 1 gateway (192.168.7.1) 0.390 ms 0.491 ms 0.663 ms 2 hhb1000cihr001.versatel.de (62.214.63.97) 6.761 ms 7.336 ms 7.565 ms 3 62.214.38.9 (62.214.38.9) 7.688 ms 8.027 ms 8.202 ms 4 62.214.37.202 (62.214.37.202) 19.592 ms 62.214.38.178 (62.214.38.178) 19.156 ms 62.214.37.202 (62.214.37.202) 19.983 ms 5 * * * $ ping www.python.org PING www.python.org(2a04:4e42:9::223 (2a04:4e42:9::223)) 56 data bytes 64 bytes from 2a04:4e42:9::223 (2a04:4e42:9::223): icmp_seq=1 ttl=57 time=16.5 ms 64 bytes from 2a04:4e42:9::223 (2a04:4e42:9::223): icmp_seq=2 ttl=57 time=15.5 ms $ traceroute www.python.org traceroute to www.python.org (151.101.36.223), 30 hops max, 60 byte packets 1 gateway (192.168.7.1) 0.390 ms 0.491 ms 0.663 ms 2 hhb1000cihr001.versatel.de (62.214.63.97) 6.761 ms 7.336 ms 7.565 ms 3 62.214.38.9 (62.214.38.9) 7.688 ms 8.027 ms 8.202 ms 4 62.214.37.202 (62.214.37.202) 19.592 ms 62.214.38.178 (62.214.38.178) 19.156 ms 62.214.37.202 (62.214.37.202) 19.983 ms 5 * * *
  19. SSLError, EuroPython 2018 tcpdump $ tcpdump -iany host localhost and

    port 443 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes 19:45:51.506997 IP6 localhost.46972 > localhost.https: Flags [S], seq 3484797679, win 43690, options [mss 65476,sackOK,TS val 1161298182 ecr 0,nop,wscale 7], length 0 19:45:51.507022 IP6 localhost.https > localhost.46972: Flags [R.], seq 0, ack 3484797680, win 0, length 0 19:45:51.507074 IP localhost.48106 > localhost.https: Flags [S], seq 231424897, win 43690, options [mss 65495,sackOK,TS val 3260527088 ecr 0,nop,wscale 7], length 0 19:45:51.507086 IP localhost.https > localhost.48106: Flags [R.], seq 0, ack 231424898, win 0, length 0 $ tcpdump -iany host localhost and port 443 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes 19:45:51.506997 IP6 localhost.46972 > localhost.https: Flags [S], seq 3484797679, win 43690, options [mss 65476,sackOK,TS val 1161298182 ecr 0,nop,wscale 7], length 0 19:45:51.507022 IP6 localhost.https > localhost.46972: Flags [R.], seq 0, ack 3484797680, win 0, length 0 19:45:51.507074 IP localhost.48106 > localhost.https: Flags [S], seq 231424897, win 43690, options [mss 65495,sackOK,TS val 3260527088 ecr 0,nop,wscale 7], length 0 19:45:51.507086 IP localhost.https > localhost.48106: Flags [R.], seq 0, ack 231424898, win 0, length 0
  20. SSLError, EuroPython 2018 Tools • host, dig • ping, traceroute

    • tcpdump, wireshark • curl, wget • nmap • read logs • firewall logs • HTTP
  21. SSLError, EuroPython 2018 TLS handshake DNS lookup TCP handshake ClientHello

    Supported cipher suites max version, client random, ... ServerHello select cipher suite version, server random, ... ... ... Finish ... ... Finish ... HTTP GET ...
  22. SSLError, EuroPython 2018 Unsupported / wrong protocol • SSLV3_ALERT_HANDSHAKE_FAILURE failed

    to negotiate acceptable TLS/SSL parameters • TLSV1_ALERT_PROTOCOL_VERSION recognized but unsupported protocol • OSError: [Errno 0] Error server closed connection • called a function you should not call TLS_ssl.c:8PROTOCOL_ssl.c:8SERVER on client-side
  23. SSLError, EuroPython 2018 SSLV3_ssl.c:8ALERT_ssl.c:8HANDSHAKE_ssl.c:8FAILURE TLS Alert (40): handshake_ssl.c:8failure • no

    cipher suite overlap / OpenSSL update • unsupported TLS version (sometimes) • other bad/unsupported handshake parameters • EC curves • signatures algorithms • ...
  24. SSLError, EuroPython 2018 sslscan $ sslscan www.python.org ... Supported Server

    Cipher(s): Rejected SSLv3 256 bits ECDHE-RSA-AES256-SHA Rejected SSLv3 256 bits ECDHE-ECDSA-AES256-SHA Failed SSLv3 256 bits DH-DSS-AES256-GCM-SHA384 ... Rejected TLS11 0 bits NULL-MD5 Accepted TLS12 256 bits ECDHE-RSA-AES256-GCM-SHA384 ... Accepted TLS12 128 bits ECDHE-RSA-AES128-GCM-SHA256 Rejected TLS12 128 bits ECDHE-ECDSA-AES128-GCM-SHA256 Accepted TLS12 128 bits ECDHE-RSA-AES128-SHA256 ... $ sslscan www.python.org ... Supported Server Cipher(s): Rejected SSLv3 256 bits ECDHE-RSA-AES256-SHA Rejected SSLv3 256 bits ECDHE-ECDSA-AES256-SHA Failed SSLv3 256 bits DH-DSS-AES256-GCM-SHA384 ... Rejected TLS11 0 bits NULL-MD5 Accepted TLS12 256 bits ECDHE-RSA-AES256-GCM-SHA384 ... Accepted TLS12 128 bits ECDHE-RSA-AES128-GCM-SHA256 Rejected TLS12 128 bits ECDHE-ECDSA-AES128-GCM-SHA256 Accepted TLS12 128 bits ECDHE-RSA-AES128-SHA256 ...
  25. SSLError, EuroPython 2018 Asymmetric encryption public key encrypts, private key

    decrypts • ElGamal encryption • RSA encryption (PKCS#1) • RSAES-PKCS1-v1.5 • RSAES-OAEP
  26. SSLError, EuroPython 2018 Symmetric-key algorithm (bulk encryption) Same key for

    encryption and decryption. • DES • Triple DES (3DES) • RC4 • AES (AES-128, AES-256) • CHACHA20
  27. SSLError, EuroPython 2018 Asymmetric signatures private key signs hash of

    message message, public key verifies • RSA signature (PKCS#1) • RSASSA-PKCS1-v1.5 • RSAES-PSS • DSS (DSA) • ECDSA (secp256r1, secp384r1, …) • EdDSA (Edward Curve25519, …)
  28. SSLError, EuroPython 2018 Cryptographically secure hash functions Hash functions for

    MAC, signatures, and more. • MD5 • SHA (SHA1) • SHA2 • SHA-256 • SHA-384
  29. SSLError, EuroPython 2018 Key agreement protocol own private key +

    peer's public = key • finite field Diffie-Hellman (DH) • elliptic curve Diffie-Hellman (ECDH) • ephemeral DH / ECDH Common secret = = Secret colours + + (assume that mixture separation is expensive) Public transport = = Secret colours + + Common paint Alice Bob
  30. SSLError, EuroPython 2018 Cryptographic building blocks • key agreement /

    exchange • authentication algorithm • bulk encryption (symmetric) • cipher mode • one-way function for message authentication (MAC)
  31. SSLError, EuroPython 2018 IANA names != OpenSSL cipher suites •

    TLS_ssl.c:8RSA_ssl.c:8WITH_ssl.c:8AES_ssl.c:8256_ssl.c:8CBC_ssl.c:8SHA256 • AES256-SHA256 • TLS_ssl.c:8ECDHE_ssl.c:8ECDSA_ssl.c:8WITH_ssl.c:8AES_ssl.c:8256_ssl.c:8GCM_ssl.c:8SHA • ECDHE-ECDSA-AES256-GCM-SHA384
  32. SSLError, EuroPython 2018 ssl module ciphers $ python3 >>> import

    ssl, pprint >>> ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) >>> ctx.set_ciphers('AES256-SHA256') >>> pprint.pprint(ctx.get_ciphers()) [{'aead': False, 'alg_bits': 256, 'auth': 'auth-rsa', 'description': 'AES256-SHA256 TLSv1.2 Kx=RSA Au=RSA ' 'Enc=AES(256) Mac=SHA256', 'digest': 'sha256', 'id': 50331709, 'kea': 'kx-rsa', 'name': 'AES256-SHA256', 'protocol': 'TLSv1.2', 'strength_bits': 256, 'symmetric': 'aes-256-cbc'}] $ python3 >>> import ssl, pprint >>> ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) >>> ctx.set_ciphers('AES256-SHA256') >>> pprint.pprint(ctx.get_ciphers()) [{'aead': False, 'alg_bits': 256, 'auth': 'auth-rsa', 'description': 'AES256-SHA256 TLSv1.2 Kx=RSA Au=RSA ' 'Enc=AES(256) Mac=SHA256', 'digest': 'sha256', 'id': 50331709, 'kea': 'kx-rsa', 'name': 'AES256-SHA256', 'protocol': 'TLSv1.2', 'strength_bits': 256, 'symmetric': 'aes-256-cbc'}]
  33. SSLError, EuroPython 2018 TLS handshake with RSA key exchange DNS

    lookup TCP handshake ClientHello Supported cipher suites max version, client random, ... ServerHello select cipher suite version, server random, ... Certificate Chain ServerHelloDone Finish MAC of handshake message ChangeCipherSpec ClientKeyChange RSA encrypted pre-master secret Finish MAC of handshake message ChangeCipherSpec HTTP GET (verify mac)
  34. SSLError, EuroPython 2018 TLS handshake with Diffie-Hellman ClientHello Supported cipher

    suites max version, client random, ... Finish MAC of handshake message ChangeCipherSpec ClientKeyChange Diffie-Hellman server params Finish MAC of handshake message ChangeCipherSpec HTTP GET (verify mac) ServerHello select cipher suite version, server random, ... Certificate Chain ServerHelloDone ServerKeyExchange Diffie-Hellman server params Signature
  35. SSLError, EuroPython 2018 Ephemeral Diffie-Hellman ✔ negotiate TLS version ✔

    negotiate cipher suite ✔ validate server cert chain ✔ replay protection: MAC client/server random ✔ perfect forward secrecy ✗ actually no PFS for session resumption… fixed in TLS 1.3
  36. SSLError, EuroPython 2018 openssl s_ssl.c:8client CONNECTED(00000003) depth=2 C = US,

    O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA verify return:1 depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 Extended Validation Server CA verify return:1 depth=0 businessCategory = Private Organization, jurisdictionC = US, jurisdictionST = Delaware, serialNumber = 3359300, C = US, ST = New Hampshire, L = Wolfeboro, O = Python Software Foundation, CN = www.python.org verify return:1 --- Certificate chain 0 s:/businessCategory=Private Organization/jurisdictionC=US/jurisdictionST=Delaware/serialNumber=3359300/ C=US/ST=New Hampshire/L=Wolfeboro/O=Python Software Foundation/CN=www.python.org i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA 1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA --- Server certificate -----BEGIN CERTIFICATE----- MIIH9zCCBt+gAwIBAgIQDEqEI45zRFWbuE0eDzGIgzANBgkqhkiG9w0BAQsFADB1 ... CONNECTED(00000003) depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA verify return:1 depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 Extended Validation Server CA verify return:1 depth=0 businessCategory = Private Organization, jurisdictionC = US, jurisdictionST = Delaware, serialNumber = 3359300, C = US, ST = New Hampshire, L = Wolfeboro, O = Python Software Foundation, CN = www.python.org verify return:1 --- Certificate chain 0 s:/businessCategory=Private Organization/jurisdictionC=US/jurisdictionST=Delaware/serialNumber=3359300/ C=US/ST=New Hampshire/L=Wolfeboro/O=Python Software Foundation/CN=www.python.org i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA 1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA --- Server certificate -----BEGIN CERTIFICATE----- MIIH9zCCBt+gAwIBAgIQDEqEI45zRFWbuE0eDzGIgzANBgkqhkiG9w0BAQsFADB1 ...
  37. SSLError, EuroPython 2018 openssl s_ssl.c:8client (2) New, TLSv1.2, Cipher is

    ECDHE-RSA-AES128-GCM-SHA256 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES128-GCM-SHA256 Session-ID: A2EF4A3041C7BDEBCA402CE245F32631A17D5140D42EB114161E24DE47E96835 Session-ID-ctx: Master-Key: 54D831ABAA0E537CF7E15844C6A1FD6D05A52EFB0CA0DB8D... PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 7200 (seconds) TLS session ticket: ... Start Time: 1532023855 Timeout : 7200 (sec) Verify return code: 0 (ok) Extended master secret: yes New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES128-GCM-SHA256 Session-ID: A2EF4A3041C7BDEBCA402CE245F32631A17D5140D42EB114161E24DE47E96835 Session-ID-ctx: Master-Key: 54D831ABAA0E537CF7E15844C6A1FD6D05A52EFB0CA0DB8D... PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 7200 (seconds) TLS session ticket: ... Start Time: 1532023855 Timeout : 7200 (sec) Verify return code: 0 (ok) Extended master secret: yes
  38. SSLError, EuroPython 2018 X.509 certificates • ASN.1 • CER/DER: binary

    ASN.1 • PEM: base64 encoded ASN.1 + header/footer • P12, PFX: PKCS#12 safe bags • cert / private key pair • content • public key • metadata • extensions • issuer signature
  39. SSLError, EuroPython 2018 Certificate Certificate: Data: Version: 3 (0x2) Serial

    Number: 04:af:72:06:22:2a:f4:84:f8:b8:ec:e1:b2:36:57:90:59:86 Issuer: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 Validity Not Before: Jun 26 19:16:27 2018 GMT Not After : Sep 24 19:16:27 2018 GMT Subject: CN = secure.europython.eu Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:c8:... Exponent: 65537 (0x10001) Certificate: Data: Version: 3 (0x2) Serial Number: 04:af:72:06:22:2a:f4:84:f8:b8:ec:e1:b2:36:57:90:59:86 Issuer: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 Validity Not Before: Jun 26 19:16:27 2018 GMT Not After : Sep 24 19:16:27 2018 GMT Subject: CN = secure.europython.eu Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:c8:... Exponent: 65537 (0x10001)
  40. SSLError, EuroPython 2018 Certificate extension X509v3 extensions: X509v3 Key Usage:

    critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication X509v3 Basic Constraints: critical CA:FALSE X509v3 Subject Key Identifier: C1:9C:34:1F:AB:21:C0:7A:43:3E:DE:F4:A1:5B:BA:B3:33:C8:3D:96 X509v3 Authority Key Identifier: keyid:A8:4A:6A:63:04:7D:DD:BA:E6:D1:39:B7:A6:45:65:EF:F3:A8:EC:A1 Authority Information Access: OCSP - URI:http://ocsp.int-x3.letsencrypt.org CA Issuers - URI:http://cert.int-x3.letsencrypt.org/ X509v3 Subject Alternative Name: DNS:cloud1.europython.io, DNS:dev.europython.eu, ... DNS:ep2017.europython.eu, DNS:ep2018.europython.eu, ... Signature Algorithm: sha256WithRSAEncryption 95:d3:cb:ec:c3:63:1e:41:c8:ab:37:3d:09:a6:... X509v3 extensions: X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication X509v3 Basic Constraints: critical CA:FALSE X509v3 Subject Key Identifier: C1:9C:34:1F:AB:21:C0:7A:43:3E:DE:F4:A1:5B:BA:B3:33:C8:3D:96 X509v3 Authority Key Identifier: keyid:A8:4A:6A:63:04:7D:DD:BA:E6:D1:39:B7:A6:45:65:EF:F3:A8:EC:A1 Authority Information Access: OCSP - URI:http://ocsp.int-x3.letsencrypt.org CA Issuers - URI:http://cert.int-x3.letsencrypt.org/ X509v3 Subject Alternative Name: DNS:cloud1.europython.io, DNS:dev.europython.eu, ... DNS:ep2017.europython.eu, DNS:ep2018.europython.eu, ... Signature Algorithm: sha256WithRSAEncryption 95:d3:cb:ec:c3:63:1e:41:c8:ab:37:3d:09:a6:...
  41. SSLError, EuroPython 2018 Certificate types • trust anchors (root CA

    certs) • intermediate CA certs • end-entity certs • server • client • code signing • email • CRL/OCSP signing • ... root CA self-signs intermediate CA 1 intermediate CA 2 signs end-entity cert signs signs
  42. SSLError, EuroPython 2018 Certificate types (2) • root CA •

    Basic Constraints: CA True, no pathlen restriction • Key Usage: cert signer, CRL signer • intermediate CA certs • Basic Constraints: CA True, pathlen: …, 3, 2, 1 • Key Usage: cert signer, CRL signer • end-entity certs • Basic Constraints: CA False • Key Usage: Digital Signature, Key Encipherment • Extended Key Usage: TLS server • Subject Alternative Name: dNSName:cz.pycon.org
  43. SSLError, EuroPython 2018 Cert chain $ openssl s_client \ -connect

    cz.pycon.org:443 -servername cz.pycon.org ... --- Certificate chain 0 s:/CN=cz.pycon.org i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 i:/O=Digital Signature Trust Co./CN=DST Root CA X3 ... $ openssl s_client ... | openssl x509 -text -noout $ openssl s_client \ -connect cz.pycon.org:443 -servername cz.pycon.org ... --- Certificate chain 0 s:/CN=cz.pycon.org i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 i:/O=Digital Signature Trust Co./CN=DST Root CA X3 ... $ openssl s_client ... | openssl x509 -text -noout
  44. SSLError, EuroPython 2018 Get verification error (Python 3.6) $ openssl

    s_client \ -connect expired.badssl.com:443 \ -servername expired.badssl.com ... SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES128-GCM-SHA256 ... Start Time: 1527832087 Timeout : 7200 (sec) Verify return code: 10 (certificate has expired) Extended master secret: no $ openssl s_client \ -connect expired.badssl.com:443 \ -servername expired.badssl.com ... SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES128-GCM-SHA256 ... Start Time: 1527832087 Timeout : 7200 (sec) Verify return code: 10 (certificate has expired) Extended master secret: no
  45. SSLError, EuroPython 2018 Certificate verification • certificate has expired get

    a new certificate • certificate is not yet valid check clocks • key usage / handshake_failure X509v3 key usage: Digital Signature, Key Encipherment
  46. SSLError, EuroPython 2018 Certificate chain failures • self signed certificate

    test cert? • unable to verify the first certificate no intermediate CAs • unable to get local issuer certificate root CA missing locally • self signed certificate in certificate chain root CA in chain, but missing locally
  47. SSLError, EuroPython 2018 Python 3.7 Traceback (most recent call last):

    .. File "/home/heimes/dev/python/3.7/Lib/ssl.py", line 1108, in do_handshake self._sslobj.do_handshake() ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1045) Traceback (most recent call last): .. File "/home/heimes/dev/python/3.7/Lib/ssl.py", line 1108, in do_handshake self._sslobj.do_handshake() ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1045)
  48. SSLError, EuroPython 2018 Trust anchors / root CAs • Linux,

    BSD • file / directory, path compiled into OpenSSL • requests, pip • certifi package • Windows • crypt32 CertOpenStore() hack • macOS • system Python: TEA (trusted evaluation agent) • Python.org installer: certifi
  49. SSLError, EuroPython 2018 Linux CA stores # Taken from https://golang.org/src/crypto/x509/root_linux.go

    _CERTIFICATE_FILE_LOCATIONS = [ "/etc/ssl/certs/ca-certificates.crt", # Debian/Ubuntu/Gentoo etc. "/etc/pki/tls/certs/ca-bundle.crt", # Fedora/RHEL 6 "/etc/ssl/ca-bundle.pem", # OpenSUSE "/etc/pki/tls/cacert.pem", # OpenELEC "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", # CentOS/RHEL 7 ] # Taken from https://golang.org/src/crypto/x509/root_linux.go _CERTIFICATE_FILE_LOCATIONS = [ "/etc/ssl/certs/ca-certificates.crt", # Debian/Ubuntu/Gentoo etc. "/etc/pki/tls/certs/ca-bundle.crt", # Fedora/RHEL 6 "/etc/ssl/ca-bundle.pem", # OpenSUSE "/etc/pki/tls/cacert.pem", # OpenELEC "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", # CentOS/RHEL 7 ]
  50. SSLError, EuroPython 2018 OpenSSL verify paths >>> ssl.get_default_verify_paths() DefaultVerifyPaths( cafile='/etc/pki/tls/cert.pem',

    capath='/etc/pki/tls/certs', openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/etc/pki/tls/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/etc/pki/tls/certs') >>> ssl.get_default_verify_paths() DefaultVerifyPaths( cafile='/etc/pki/tls/cert.pem', capath='/etc/pki/tls/certs', openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/etc/pki/tls/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/etc/pki/tls/certs')
  51. SSLError, EuroPython 2018 Hostname verification Certificate: Data: ... Subject: CN

    = secure.europython.eu ... X509v3 extensions: X509v3 Subject Alternative Name: DNS:cloud1.europython.io, DNS:dev.europython.eu, DNS:ep2015.europython.eu, DNS:ep2016.europython.eu, DNS:ep2017.europython.eu, DNS:ep2018.europython.eu, DNS:epstage.europython.eu, DNS:europython.eu, DNS:europython.io, DNS:helpdesk.europython.eu, DNS:mail.europython.eu, DNS:mail.europython.io, DNS:mattermost.europython.eu, DNS:secure.europython.eu, DNS:wiki.europython.eu, DNS:www.europython.eu Certificate: Data: ... Subject: CN = secure.europython.eu ... X509v3 extensions: X509v3 Subject Alternative Name: DNS:cloud1.europython.io, DNS:dev.europython.eu, DNS:ep2015.europython.eu, DNS:ep2016.europython.eu, DNS:ep2017.europython.eu, DNS:ep2018.europython.eu, DNS:epstage.europython.eu, DNS:europython.eu, DNS:europython.io, DNS:helpdesk.europython.eu, DNS:mail.europython.eu, DNS:mail.europython.io, DNS:mattermost.europython.eu, DNS:secure.europython.eu, DNS:wiki.europython.eu, DNS:www.europython.eu
  52. SSLError, EuroPython 2018 Don't roll your own verification • CN/SAN

    • wildcards • internationalized domain names (IDNA) • > 6 bugs in Python's hostname verification code • CVE-2013-2099, #12000, #17997, #17305, #30141 • Python 3.7 uses X509_ssl.c:8VERIFY_ssl.c:8PARAM_ssl.c:8set1_ssl.c:8host() OpenSSL 1.0.2+ / LibreSSL 2.7.0
  53. SSLError, EuroPython 2018 HTTP, HTTP/2 • Server Name Indication (SNI)

    host == HTTP Host • H/2 requires TLS 1.2 with PFS • ALPN GET / HTTP/1.1 Host: ep2018.europython.eu GET / HTTP/1.1 Host: ep2018.europython.eu
  54. SSLError, EuroPython 2018 How to debug SSLError • check connection

    (TCP/DNS) • openssl s_ssl.c:8client • openssl x509 • curl -s -v • check logs • tcpdump + wireshark • update to Python 3.7
  55. SSLError, EuroPython 2018 Tools • Wireshark, tcpdump • openssl command

    line (s_ssl.c:8client, x509, verify) • curl • sslscan • strace, ptrace, ltrace • https://www.ssllabs.com/ssltest/ • https://lapo.it/asn1js/
  56. SSLError, EuroPython 2018 Resources • https://istlsfastyet.com/ • Deploying TLS 1.3:

    the great, the good and the bad (33c3) https://www.youtube.com/watch?v=0opakLwtPWk