Skip to content

Forbid SimpleHTTPRequestHandler serving files outside of specified directory #132142

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

Closed
donBarbos opened this issue Apr 5, 2025 · 9 comments
Closed
Labels
stdlib Python modules in the Lib dir type-feature A feature request or enhancement

Comments

@donBarbos
Copy link
Contributor

Current behavior has long been known (#54440 (comment)) and documented but it seems that leaving it is not the best solution, especially when it is easy to fix.

I suggest adding a check that the source file is not located above the current directory, otherwise return Forbidden.

Can be reproduced by next steps:

$ mkdir workdir
$ echo "SECRET CONTENT" > secret.txt
$ ln -s secret.txt workdir/leak.txt
$ python -m http.server 8000 -d workdir
$ curl http://localhost:8000/leak.txt
SECRET CONTENT

We can implement this by adding a similar check to SimpleHTTPRequestHandler.translate_path method:

    def translate_path(self, path):
        # previous checks
        real_base = os.path.realpath(self.directory)
        real_path = os.path.realpath(path)

        if not real_path.startswith(real_base):
            self.send_error(403, "Forbidden")
            return ""
        return path

I can send PR

@picnixz picnixz added type-feature A feature request or enhancement stdlib Python modules in the Lib dir labels Apr 5, 2025
@picnixz
Copy link
Member

picnixz commented Apr 5, 2025

As you observed, it's documented and I think it should be kept as is. Some users might want to use that for fast debugging, possibly with hacky solutions so I don't think we need to be safe here. On the other hand, we could, if needs arise, add an option that disables following symlinks but I don't know if it's worth it. I'm -0 for this one (as http.server is not for production use, I don't consider this as a bug)

@gpshead wdyt?

@picnixz picnixz changed the title SimpleHTTPRequestHandler allows serving files outside of specified directory Forbid SimpleHTTPRequestHandler serving files outside of specified directory Apr 5, 2025
@donBarbos
Copy link
Contributor Author

I also want to add that it seems http.server is not for production use follows from the fact that we have similar problems, i.e. the opposite consequence.
As an example, we have already fixed the error with scrub control characters from the log messages in version 3.12.
I mean that such behavior should be corrected since this is a drawback and not a feature (in issue #54440 this is also called a bug)
It seems this behavior was documented to show a security issue, but it could be improved :-)

@picnixz
Copy link
Member

picnixz commented Apr 6, 2025

this is also called a bug

The discussion in that issue was quite long and I don't think it was categorized as such by a core dev. I personally don't consider this as a bug. It's known, documented and warned against.

It seems this behavior was documented to show a security issue, but it could be improved :-)

We don't want to patch all possible security holes. Anyone using http.server should be aware that they are subject to possible attacks (the security considerations section is non-exhaustive).

As an example, we have already fixed the error with scrub control characters from the log messages in version

This is a bit different. The issue here was that it was possible to send incorrect control characters into the log messages and directly affect the server without the latter being misconfigured (namely even by serving an empty directory!) There were other security issues that were patched, e.g., #87389, but this doesn't require the server to be faulty itself.

Now in your example, the leakage of the secret is due to the symlink itself. Yes, it's a security issue, but this only happens if the server decides to host such files, not because an adversary is able to provide some input to the server and access files outside its root location.

So for this specific one, I really don't think we need to change the existing behaviour. I'm interested in Gregory's opinion on that matter as he fixed previous security issues for http.server. So I'm still -0.

@sobolevn
Copy link
Member

sobolevn commented Apr 6, 2025

http.server never meant to be super secure. But, adding --secure-root (or anything similar) seems like a useful feature.

@picnixz
Copy link
Member

picnixz commented Apr 6, 2025

I'd like to point out that this would not protect against faulty handlers who can still access files outside the server's location. In PHP, typical code subject to directory traversal attacks is:

<?php
include($_GET['file']);
?>

Assuming that the handler's do_GET method does something similar, say by echoing the content of a file by reading it using some open(params["file"]) without checking the GET parameter, we would still be able to print the content of a "forbidden" file.

So, maybe a server.is_valid_path() method could be useful and users could use it to sanitize arbitrary paths (without having to transform it into translate_path(), which btw is not documented).

Now, note that the above attack requires a faulty handler, so something on the server side that is already poorly written. So, I still want to keep the security considerations section and warn users that external files could still be accessed and that only naive directory listing is protected.

@gpshead
Copy link
Member

gpshead commented Apr 6, 2025

As an example, we have already fixed the error with scrub control characters from the log messages in version 3.12.
I mean that such behavior should be corrected since this is a drawback and not a feature (in issue #54440 this is also called a bug)
It seems this behavior was documented to show a security issue, but it could be improved :-)

Claiming something is "secure" adds a huge ongoing maintenance burden. This comment is ironically an example of why.

Ex: If we add --secure-root "feature" it encourages people to depend on it and complain about any possible way to get around it - which is not something we, the Python Core Team, are in a position to guarantee over the length of a release cycle as there is no concrete set of requirements or anyone dedicated to treating the http modules as a Product.

I don't think we should invest further in these servers. Quality http servers exist outside of the standard library.

@9001
Copy link

9001 commented Apr 6, 2025

Also, most webservers do follow symlinks, and it's the behavior I would expect. I frequently create a folder full of symlinks to outside locations just to share all of those from one httpd.

I'm not a cpython dev so this is just another outsider opinion.

@krishpranav
Copy link

@gpshead, @picnixz

Have opened a PR: #132224

@picnixz
Copy link
Member

picnixz commented Apr 7, 2025

We didn't agree on this feature. And two core devs (Gregory and me) were not convinced. I prefer rejecting this feature.

@picnixz picnixz closed this as not planned Won't fix, can't repro, duplicate, stale Apr 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stdlib Python modules in the Lib dir type-feature A feature request or enhancement
Projects
None yet
6 participants