Live data from Hacker News

If your code accepts URIs as input, filter out “file://”

blog.steve.fi

41–50 of 161 posts

Re: If your code accepts URIs as input, filter out “file://”

#41
file:// urls are awesome! People forget about them and nobody actually understands what to expect from these urls. Consider cross-origin policy implications. Is file:///home/john/bar.html on the same origin as file:///home/john/foo.html ?

Also, XHR is totally allowed to go to file://

Re: If your code accepts URIs as input, filter out “file://”

#43

Wrong way around: only allow http:// and https:// (and generally filtering out anything thats not letters, numbers, slash or dot is probably a good idea. Remove any sequences of more than one slash or dot.

I believe uri today accept all sorts of characters outside ascii.

Re: If your code accepts URIs as input, filter out “file://”

#44
post #35

Earlier quoted context omitted.

> filtering out anything thats not letters, numbers, slash or dot is probably a good idea. This is highly non-trivial once you realize that the world speaks more than ASCII and things like http://www.xn--n3h.net exist.

>This is highly non-trivial once you realize that the world speaks more than ASCII and things like http://www.xn--n3h.net exist. I was under the impression that requests to and from the server still used ASCII? That is, the server would see a host header as this: Host: www.xn--n3h.net And not as this: Host: www.[snowman icon].net Anything else is a question of URL-encoding, which if not used would raise interesting b…

Right but how does the user submit it and what do you put in the href?

Re: If your code accepts URIs as input, filter out “file://”

#45

Earlier quoted context omitted.

>Wrong way around: only allow http:// and https:// For myself, it's a subtle change in developer thinking - "what should I allow" vs "what should I exclude" - that's paid off massively over the years.

https://en.m.wikipedia.org/wiki/Robustness_principle

https://en.wikipedia.org/wiki/End-to-end_principle

Most of the advice in this thread would accidentally disable ftp support.

Re: If your code accepts URIs as input, filter out “file://”

#46
post #40

Also make sure you don't follow 301/302, or someone can set up a http link which redirects to file:// .

Or just, when following 301/302, call the same function again – which then validates the link completely again.

I'm not sure why you're getting downvoted, it's a little unfair for people to downvote a sensible suggestion without explaining why.

One possible downside is that someone could Redirect A -> B and redirect B -> A, which risks tying up your resources following links, but browsers limit how many redirects will be followed, so it ought to be possible to limit redirects.

Re: If your code accepts URIs as input, filter out “file://”

#47

Earlier quoted context omitted.

(Also be weary of imagetragick-type bugs too, where the URL starts innocuously and then contains some shellcode, because you pass the URL to something that'll paste it into system() call)

I certainly am weary of bug branding...

I know, me too, but I didn't name it.

There's a section on the main page imagetragick.com talking about branding and how they got no traction without one.

Re: If your code accepts URIs as input, filter out “file://”

#48
post #28

Also be sure not to allow loopback connections (ie your own site or localhost) or you can cause a deadlock if the user requests the same URL to download from your site recursively. Choose an appropriate timeout too to prevent users tying up backend processes with a HTTP server that is slow to respond, and don't follow Location headers to avoid bypassing of your initial filters. A Range header should also be used to p…

> Also be sure not to allow loopback connections (ie your own site or localhost) or you can cause a deadlock if the user requests the same URL to download from your site recursively.

Keep in mind that any arbitrary domain can point DNS to a loopback or LAN address. So the code that fetches a URL needs to include this filtering.

> don't follow Location headers to avoid bypassing of your initial filters

Often, you'll want to follow redirects, but re-apply your filters when doing so.

> A Range header should also be used to prevent users from telling your server to download multi-GB files and causing bandwidth waste / denial of service.

You can't count on support for Range, and the server might also just behave unexpectedly. Your fetching code needs to limit how much data it accepts from a server, and drop the connection after some upper bound.

Re: If your code accepts URIs as input, filter out “file://”

#49
post #28

Also be sure not to allow loopback connections (ie your own site or localhost) or you can cause a deadlock if the user requests the same URL to download from your site recursively. Choose an appropriate timeout too to prevent users tying up backend processes with a HTTP server that is slow to respond, and don't follow Location headers to avoid bypassing of your initial filters. A Range header should also be used to p…

> Also be sure not to allow loopback connections (ie your own site or localhost) or you can cause a deadlock if the user requests the same URL to download from your site recursively. Keep in mind that any arbitrary domain can point DNS to a loopback or LAN address. So the code that fetches a URL needs to include this filtering. > don't follow Location headers to avoid bypassing of your initial filters Often, you'll w…

> Your fetching code needs to limit how much data it accepts from a server, and drop the connection after some upper bound.

And if you accept compressed responses, remember that they can be a lot bigger when decompressed: e.g. gzip allows for factor 1000.

Re: If your code accepts URIs as input, filter out “file://”

#50
Also be very wary of ../ or possibly ..\ in URIs.

Say you have http://example.org/download?file=release/software-1.0.zip so that you can log download statistics.

If you just fetch GET["download"] and return it, you're gonna have a bad time if they try http://example.org/download?file=../../../../../etc/hosts (browsers strip it out automatically, but it's easy enough to type such a request into a telnet session.)

And don't just assume your safeguard works. Act like a hacker and try it out on yourself to make sure it works. Add an assert(validate("../") == false); at startup on your server, so it won't even run otherwise. Forbid the use of fopen() and instead go through your own file::open() function that calls validate() internally, then #define fopen ERROR_DONT_USE after (or whatever equivalent for the language you use.)

It is a hostile world, you can never be too safe by adding multiple (even seemingly redundant) layers of protection.

Post reply on HN