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

Tales from Python Core Security (ConFoo Montreal 2017)

Tales from Python Core Security (ConFoo Montreal 2017)

Christian Heimes

March 10, 2017
Tweet

More Decks by Christian Heimes

Other Decks in Programming

Transcript

  1. Tales from Python Core Security ConFoo Montreal 2017 Christian Heimes

    [email protected] / @ChristianHeimes Senior Software Engineer 2017-03-10
  2. 2 Who am I • from Hamburg / Germany •

    Linux user since 1998 • Python developer since 2002 • Python core contributor since 2008
  3. 3 Python • PEP 370: Per user site-packages directory •

    PEP 452: API for Cryptographic Hash Functions v2.0 • PEP 456: Secure and interchangeable hash algorithm • PEP 543: Unified TLS API (Cory Benfield) • maintainer of ssl and hashlib modules • maintainer of Coverity Scan • Python Security Response Team (emeritus) • I put bytes and b'' into Python 2
  4. 4 Professional Life • Senior Software Engineer with Red Hat

    • Security Engineering & Identity Management • FreeIPA IdM • Dogtag PKI • Custodia
  5. 8 Topics • What does 'secure' mean? Why is it

    so hard? • Security efforts • Examples of CPython security issues • How to write secure software • from __future__ import ...
  6. 10 Python Security People • Alex Gaynor • Antoine Pitrou

    • Ashwini Oruganti • Benjamin Peterson • Cory Benfield • Gregory P. Smith • Hynek Schlawack • lvh • Paul Kehrer • Serhiy Storchaka • Victor Stinner
  7. 28 Reviews • PEP process • design reviews • code

    reviews • commit reviews • Did I mention reviews?
  8. 29 Collaboration • Upstream vendor security teams • Ruby and

    PHP security • Python Cryptography Authority (PyCA) • security people (Ryan Sleevi, DJB)
  9. 30 Tools • multiple compilers and platforms • compiler warnings

    • clang code analysis • fuzzing • Coverity Scan • python-security.readthedocs.io
  10. 31

  11. 32

  12. 34

  13. 35

  14. 36

  15. 38 XML entities <!DOCTYPE example [ <!ENTITY title "My title"

    > ]> <xml> <tag attribute=”value”>&title;</tag> </xml> <!DOCTYPE example [ <!ENTITY title "My title" > ]> <xml> <tag attribute=”value”>&title;</tag> </xml>
  16. 39 XML entities expansion attack <!DOCTYPE xmlbomb [ <!ENTITY a

    "1234567890" > <!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;"> <!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;"> <!ENTITY d "&c;&c;&c;&c;&c;&c;&c;&c;"> ]> <bomb>&d;</bomb> <!DOCTYPE xmlbomb [ <!ENTITY a "1234567890" > <!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;"> <!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;"> <!ENTITY d "&c;&c;&c;&c;&c;&c;&c;&c;"> ]> <bomb>&d;</bomb>
  17. 40 XML network / file access <!DOCTYPE external [ <!ENTITY

    remote SYSTEM "http://www.python.org/some.xml"> <!ENTITY local SYSTEM "file:///etc/passwd"> ]> <xml> <url>&remote;</file> <file>&local;</file> </xml> <!DOCTYPE external [ <!ENTITY remote SYSTEM "http://www.python.org/some.xml"> <!ENTITY local SYSTEM "file:///etc/passwd"> ]> <xml> <url>&remote;</file> <file>&local;</file> </xml>
  18. 41 XML attacks • billion laughs / exponential entity expansion

    • quadratic blowup entity expansion • DTD & external entity expansion (remote and local) • attribute blowup / attribute hash collision attack • decompression bomb (gzip) • XPath injection attacks • XInclude <xi:include /> • XMLSchema-Import <xs:import /> • XSLT features wie xalan/redirect, xalan/java
  19. 44 HTTP RFC822 header content-type: text/html; charset=utf-8 content-length: 47446 x-clacks-overhead:

    GNU Terry Pratchett <html> <head> ... content-type: text/html; charset=utf-8 content-length: 47446 x-clacks-overhead: GNU Terry Pratchett <html> <head> ...
  20. 45 HTTP header parsing sock = create_connection(('host', 80)) f =

    sock.makefile() for line in f: name, value = line.split(':', 1) ... sock = create_connection(('host', 80)) f = sock.makefile() for line in f: name, value = line.split(':', 1) ...
  21. 46 HTTP parsing (fixed) MAX_LENGTH = 1024 sock = create_connection((host,

    port)) f = sock.makefile() while True: line = f.readline(MAX_LENGTH + 1) if len(line) > MAX_LENGTH: raise ValueError ... MAX_LENGTH = 1024 sock = create_connection((host, port)) f = sock.makefile() while True: line = f.readline(MAX_LENGTH + 1) if len(line) > MAX_LENGTH: raise ValueError ...
  22. 47 CVE-2013-1752 • Issue #16037 httplib (Adrien Kunysz) • Issue

    #16038 ftplib • Issue #16039 imaplib • Issue #16040 nntplib • Issue #16041 poplib • Issue #16042 smtplib
  23. 48 Header injection http://127.0.0.1%0d%0aX-injected:%20header %0d%0ax-leftover:%20:12345/foo GET /foo HTTP/1.1 Host: 127.0.0.1

    X-injected: header x-leftover: :12345 >>> socket.getaddrinfo( '127.0.0.1\r\n', 12345)[0][4] ('127.0.0.1', 12345) http://127.0.0.1%0d%0aX-injected:%20header %0d%0ax-leftover:%20:12345/foo GET /foo HTTP/1.1 Host: 127.0.0.1 X-injected: header x-leftover: :12345 >>> socket.getaddrinfo( '127.0.0.1\r\n', 12345)[0][4] ('127.0.0.1', 12345)
  24. 50 Python's dict type • dicts are implemented as hash

    maps • closed hashing • open addressing • average search and insert: O(1) • worst case: O(n)
  25. 51 Hash map primer >>> hash('de') 12800076900115529 >>> hash('de') &

    (8 - 1) 1 >>> hash('de') 12800076900115529 >>> hash('de') & (8 - 1) 1 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 de
  26. 52 Hash map primer (2) >>> hash('df') 6672104196504639850 >>> hash('df')

    & (8 - 1) 2 >>> hash('df') 6672104196504639850 >>> hash('df') & (8 - 1) 2 0 1 2 3 4 5 6 7 de df
  27. 53 Hash collision >>> hash('cf') & (8 - 1) 1

    >>> hash('bg') & (8 - 1) 1 >>> hash('cf') & (8 - 1) 1 >>> hash('bg') & (8 - 1) 1 0 1 2 3 4 5 6 7 de cf bg df
  28. 54 PEP 456 SipHash24 • First attempt by Victor Stinner

    failed • Alternatives were slow and/or insecure • SipHash24 by Jean-Philippe Aumasson and Daniel J. Bernstein
  29. 56 TLS / SSL • encrypts communication • protects data

    integrity • prevents reply attacks • authenticate server with X.509 certificate
  30. 57 TLS handshake 1) Client and server negotiate connection parameters.

    • protocol version • SSL 3, TLS 1.0, TLS 1.1, TLS 1.2 • cipher suit • TLS_RSA_WITH_AES_128_CBC_SHA • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 2) Client verifies server cert. 3) Client and server agree on a master secret.
  31. 58 Hostnames in X.509 certificates Certificate: Data: Issuer: C=IL, O=StartCom

    Ltd., ... Validity Not Before: Feb 2 08:35:11 2015 GMT Not After : Feb 1 21:03:59 2017 GMT Subject: C=US, ST=Oregon, L=Beaverton, O=Python Software Foundation, CN=*.python.org X509v3 extensions: X509v3 Subject Alternative Name: DNS:*.python.org, DNS:python.org Certificate: Data: Issuer: C=IL, O=StartCom Ltd., ... Validity Not Before: Feb 2 08:35:11 2015 GMT Not After : Feb 1 21:03:59 2017 GMT Subject: C=US, ST=Oregon, L=Beaverton, O=Python Software Foundation, CN=*.python.org X509v3 extensions: X509v3 Subject Alternative Name: DNS:*.python.org, DNS:python.org
  32. 59 Bug #0 No function to verify a hostname •

    ssl.match_hostname() added in Python 3.2 • backported to 2.7.9
  33. 60 Bug #1 (Issue #12000) Use CN when subject alternative

    name field has no dNSName entries. • fixed in 3.3
  34. 62 Bug #3 (Issue #17997) Use RFC 6125 instead of

    outdated RFC 2818 • only one left-most wildcard is allowed • *.*.python.org or www.*.python.org are forbidden • fixed in 3.3.3
  35. 63 Bug #4 (Issue #17997) Fix wildcard matching for internationalized

    domain names (IDN) • über.python.org → xn--ber-goa.python.org • fixed in 3.3.3 • Mozilla NSS / Firefox and OpenSSL 1.0.2dev were affected, too.
  36. 64 Bug #5 (Issue #18709) NULL bytes inside subjectAltNames general

    names, e.g. www.python.org\x00evil.com • fixed in 3.4 • Ruby and PHP were also affected
  37. 65 Bug #6 (too many CVEs) Python does not check

    hostname by default • PEP 476 (Alex Gaynor) • fixed for httplib/urllib in 3.4 and 2.7.9 • still not fixed for imap, pop, smtp etc.
  38. 66 Bug #7 (issue #17305) Python does not support IDNA

    2008 • critical for German domains like straße.de • IDNA 2003: strasse.de • Chrome, Edge, Konqueror • IDNA 2008: xn--strae-oqa.de • Firefox • still not fixed
  39. 68 homoglyphic confusion attack >>> import unicodedata >>> for c

    in 'Руthοn': ... print(unicodedata.name(c)) ... CYRILLIC CAPITAL LETTER ER CYRILLIC SMALL LETTER U LATIN SMALL LETTER T LATIN SMALL LETTER H GREEK SMALL LETTER OMICRON LATIN SMALL LETTER N >>> import unicodedata >>> for c in 'Руthοn': ... print(unicodedata.name(c)) ... CYRILLIC CAPITAL LETTER ER CYRILLIC SMALL LETTER U LATIN SMALL LETTER T LATIN SMALL LETTER H GREEK SMALL LETTER OMICRON LATIN SMALL LETTER N
  40. 70

  41. 72 Think first! • Read, understand and use open standards

    • Learn from mistakes • Document security claims and trade-offs • Design software for human • Default to secure and easy to use • Defense in depths
  42. 73 Does • Use frameworks • Django, Flask, Plone, Pyramid…

    • sqlalchemy • PyCA cryptography • passlib • Use TLS/SSL (Let's Encrypt, FreeIPA)
  43. 75 Here be dragons • Beware of dangerous Python features

    • exec(), eval(), import • pickle, marshal • random module • Don't roll your own crypto!
  44. 81 Random Number Generator • random.random() • /dev/random • /dev/urandom

    • getrandom() Linux syscall • getentropy() BSD syscall • CryptGenRandom() Work-in-progress: osrandom_engine
  45. 82 Python 3.6 • PEP 524 os.urandom() • hashlib •

    blake2, sha3, scrypt • ssl • OpenSSL 1.1.0 • sessions • get cipher suite • AF_ALG Linux Kernel Crypto
  46. 85 Future • TLS 1.3 • Hardware security (Intel MPX,

    HSM, TPM 2.0) • 2FA • containers • IoT (internet of things) • Quantum Computers