Hacker News new | ask | show | jobs
by 542458 1087 days ago
At risk of asking a dumb question, is there any good reason that you’d want nginx to allow traversing into “..” from a URL path? It just seems like problems waiting to happen.

Edit: Actually, I’m a bit lost as to what’s happening in the original vuln. http://localhost/foo../secretfile.txt gets interpreted as /var/www/foo/../secretfile.txt or whatever… but why wouldn’t a server without the vulnerability interpret http://localhost/foo/../secretfile.txt the same way? Why does “..” in paths only work sometimes?

5 comments

That has been a known issue in nginx for a very long time and its a common attack vector at CTFs:

https://book.hacktricks.xyz/network-services-pentesting/pent...

There is a LFI vulnerability because:

    /imgs../flag.txt
Transforms to:

    /path/images/../flag.txt
I've only implemented a handful of HTTP servers for fun, but I've always resolved relative paths and constrained them. So I'd turn "/path/images/../flag.txt" into "/path/flag.txt", which would not start with the root "/path/images/" and hence denied without further checks.

Am I wrong, or, why doesn't nginx do this?

It does when you use the root directive. Alias should hardly be used if possible for those reasons.
The problem is that a URL isn't actually a path. It's an abstract address to a resource which can be a directory or file (or an executable or stream or ...).

In this case part of the URL is being interpreted by nginx as a directory (http://localhost/foo) due to how that URL is mapped in the configuration to the local filesystem. Apparently it references a directory, so when nginx constructs the full path to the requested resource, it ends up with "${mapped_path}/../secretfile.txt" which would be valid on the local filesystem even if it doesn't make sense in the URL. Notice how the location of the slashes doesn't matter because URLs don't actually have path elements (even if we pretend they do), they are just strings.

This is a very common problem that I have noticed with web servers in general since the web took off. Mapping URLs directly to file paths was popular because it started with simple file servers with indexes. That rapidly turned into a mixed environment where URLs became application identifiers instead of paths since apps can be targeted by part of the path and the rest is considered parameters or arguments.

And no, it generally doesn't usually make sense to honor '.' or '..' in URLs for filesystem objects and my apps sanitize the requested path to ensure a correct mapping. It's also good to be aware that browsers do treat URLs as path-like when building relative links so you have to be careful with how and when you use trailing '/'s because it can target different resources which have different semantics on the server side.

Not in any "normal" use-case, no. It'd make sense to make this behavior opt-in, like having a `allow_parent_traversal on;` flag in the location.
Just guessing, but NginX probably either checks for "/foo/bar/.." and disallows it, or normalizes it to "/foo/" but "/foo/bar.." is a perfectly valid file name, so it doesn't get caught by the net checking for this.
> Why does “..” in paths only work sometimes?

That fully depends upon the file permissions. In this case, let's assume that a user has permissions to read files all the way from the web index directory (../index.html) back to the root directory (/). At that point, since they have permission to traverse down to the root directory, they now have permission to view any world viewable file that can be traversed to from the root directory, for instance /etc/passwd.

In other words, imagine a fork with three prongs, and your web server resides on the far right prong. Imagine that the part of the fork where the prongs meet (the "palm" of the fork) is the file system. If your web server residing on the far right prong of that fork allows file permission to files and directories that lead all the way to the palm of the fork, at that point you could continue accessing files on other prongs once you have reached the palm.

Isn't setting correct permissions for www-data like, the first note in a bunch of "secure your web server" tutorials? I thought if read is only set for the directory with actual public files, and not for the parent directory, there should be no traversal possible like this?
> "Isn't setting correct permissions for www-data like, the first note in a bunch of "secure your web server" tutorials?"

It is indeed. And yet here we are.