3

I'm writing a simple HTTP server in Lua and while I can easily find resources on how to secure against Unix directory traversal, I already found some caveats in the Windows version. While I'm already looking for C:\ at the beginning (C being "any letter" here), ../ and /.. (with backslash as the directory delimiter as well) and \\ at the beginning. The code will be passed to ANSI C fopen(), compiled under Microsoft Visual C++ v10 (no idea what's the system call this call compiles to). Are there any other traps I should look out for in this case?

I'm only interested in solutions involving the modification of my code, most preferably by checking the filename against patterns.

3
  • I really hope this is just a project for the sake of learning.
    – user10211
    Sep 12, 2013 at 13:27
  • It is. Here's the code: svn.nmap.org/nmap/ncat/scripts/httpd.lua
    – d33tah
    Sep 12, 2013 at 13:27
  • Ah, you mean the HTTP server I wrote? More of a demo, with a big warning "don't use it on production". Yet I'd rather make it secure. Its main use scenario is simple file (or directory) sharing over a trusted network.
    – d33tah
    Sep 12, 2013 at 13:28

1 Answer 1

7

Paths in Windows are relatively complex. In particular, Microsoft has a habit of inventing new features, so even if your HTTP server is really protected against path traversal today, it may become vulnerable under next version of Windows, possibly even a small update.

Right now, your are using "blacklist-thinking": you are trying to enumerate all the "bad" constructions, and specifically detect them. Blacklists are known to be fragile because it is very hard to be exhaustive, and then to remain exhaustive. You should use whitelist-thinking, i.e. define a syntax for allowed paths and exclude everything else.

For instance, define that an allowed path consists in a sequence of components separated by slash characters ("/", not "\"), with the following rules:

  • A component contains only letters, digits, dashes ("-"), underscores ("_") or dots (".").
  • A dot may not appear as first or last character in a component.
  • There shall not be any two consecutive dots in a component.
  • A component contains at least one character, and at most 64 characters (arbitrary limit).
  • No two consecutive slashes may appear in a path.
  • A path does not begin with a slash.
  • A path is not empty.
  • The total length of a path shall not exceed 250 characters.

All these rules are easy to enforce programmatically. And they guarantee a "clean local path" that you can send to fopen(). Note that most Windows functions are perfectly happy with the "/" as separator, but you may still want to replace all slashes by backslashes (after checking all the rules above, of course).

3
  • Is 'component' just the word you are using for a directory? Because it is valid (but perhaps misguided) for a filename to be test......txt, for example, which would violate the two-dot rule.
    – Gray
    Sep 12, 2013 at 13:56
  • 1
    Yes, I am using "component" as meaning "directory or file". The point is that, for a HTTP server, I don't actually need to support every possible path name; I just have to support paths which "make sense". I can declare that test......txt will not be allowed, even if the underlying Windows would have accepted it. (Similarly, IIS, the HTTP server from Microsoft, will reject file names which contain a "+", even though Windows itself has no problem whatsoever with such names -- and rejecting names with a "+" is very rarely an issue.)
    – Tom Leek
    Sep 12, 2013 at 14:02
  • Thank you for the clarification. I can see your point now.
    – Gray
    Sep 12, 2013 at 16:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .