• Server Configuration – Basic Security Part 7

    by  • 25 July 2012 • Security

    NB: This is the seventh post in a series of posts on web application security.

    Configuring a server correctly is both 1) hard and 2) critical.

    You’ve probably spent a bunch of time configuring Apache or nginx, or whatever your server of choice is, for performance. But have you configured it for security?

    I can’t tell you exactly what to do without knowing your set up, but some basics:

    1. Are directories only writeable by the web serverapplication user1?
    2. Do all of them even need to be? Are you sure?
    3. Can the web process write to its own source files?
    4. Are any Alias or ScriptAlias directives set you don’t know about?
    5. Are your firewall rules restrictive enough?
    6. There is literally so much more. Contract a good sysadmin.
    7. Is PHP installed on your Python server?

    1: See Valentin’s comment about running server and application(s) as separate users. He’s right.

    Let me elaborate on the last one, because our security team will let me. We had left PHP installed (part of our puppet configs) on app servers that were only going to run Python. Someone discovered a small hole—we weren’t checking the extensions of uploaded images—and realized they could upload PHP scripts, and the Apache server, happily serving “static” files, interpreted and ran them.

    Shit.

    Don’t do that. Learn from us on that one. Double check. Then check again.

    What else?

    Those of you who’ve configured servers, webdevs, devops, sysadmins, what are other key things to check to make sure you’ve hardened your server configuration?

    • http://twitter.com/ianmthomasuk Ian Thomas

      > we weren’t checking the extensions of uploaded images—and realized they could upload PHP scripts,
      > and the Apache server, happily serving “static” files, interpreted and ran them.

      I’m not that familiar with Python, but surely the same could happen with a user uploading a Python script?

      I also prefer to check more than just the extension of uploaded images. In PHP I would use getimagesize to examine the temporary version of the image (i.e. before it’s available in the webroot for an attacker to execute). I then choose my own extension based on that info.

    • Carl Meyer

      > I’m not that familiar with Python, but surely the same could happen with a user uploading a Python script?

      Not generally. The most common way to serve Python through Apache these days is mod_wsgi, which requires special Apache configuration pointing to an “entry point” script, it doesn’t just blindly execute things based on extension.

      The older mod_python (which has been discontinued) can be configured to execute any .py file as a script, more like mod_php. Having mod_python enabled and configured in that way (or having ExecCGI enabled on your static files directory) would indeed be just as much of a mistake as having mod_php enabled.

    • http://getsolidstate.com getsolidstate

      these days, we use set of pre-built scripts to harden servers.

      especially once you get into PCI compliance, there is no way to do all this yourself.

      things to perform generally are:
      – install grsecurity kernel
      – clamav
      – aide / rkhunter (IPS)
      – proper file perm/ownersips
      – JIT (just-in-time patching)
      – real-time malware
      – anti ddos via sysctl
      – disabling un-needed services

      checkout atomicorp.com’s ASL, it takes care of a lot of these things,

      also aqueduct is also a good starting point, which is a set of bash/puppet scripts to perform these mundane tasks.

    • http://jamessocol.com/ James

      > The older mod_python (which has been discontinued) can be configured to execute any .py file as a script, more like mod_php. Having mod_python enabled and configured in that way (or having ExecCGI enabled on your static files directory) would indeed be just as much of a mistake as having mod_php enabled.

      Also, I suppose you could do something with AddHandler but you’d have to be pretty explicitly trying to do that.

      > I also prefer to check more than just the extension of uploaded images. In PHP I would use getimagesize to examine the temporary version of the image (i.e. before it’s available in the webroot for an attacker to execute). I then choose my own extension based on that info.

      That’s more like what we do now. Even valid images, though, can contain PHP in comment fields, so it’s important to do both, and more.

    • http://rhelmer.org/ Rob Helmer

      Misconfiguration of the webserver “proxy” feature is unfortunately pretty common (usually intending to reverse-proxy internally to a standalone server such as node.js), and can allow nefarious people not only to proxy HTTP but other connections (e.g. sending spam email):

      http://wiki.apache.org/httpd/ProxyAbuse

      Also, keeping any kind of privileged data anywhere in the htdocs directory (configuration files, etc) usually leads to trouble.. even if you get this right initially it’s very easy to accidentally drop the permissions or particular rule that is blocking that file over time.

      Better to keep things like configuration outside of the htdocs dir.

    • http://voracity.org voracity

      Sorry, I don’t understand the above comments. How can something that’s uploaded (stored) without a .php extension be executed as php?

      Also, why don’t CGI environments by default disable execution permissons on any uploaded or written-to-disk content? It doesn’t fix every issue, but as James says, it’s another lock on the door.

    • http://jamessocol.com/ James

      @voracity: Server misconfiguration. Also, note that one vector is to upload a valid image with a .php extension, that contains PHP code (e.g. <?php do_something() ?> in image comment fields. That would pass most image validity checks, so you need to do both, the image validity and the extension.

      As for your second question: I don’t know, but very rarely do files actually have to be marked +x “executable” when we’re dealing with web frameworks. In Django, only manage.py is usually executable. In a PHP site, none of them need to be. So setting -x doesn’t necessarily do much.

    • http://voracity.org voracity

      Thanks, but that still makes no sense to me. (I’m sorry if this makes me appear dull.) My personal approach to security is very much KISS. Rule #1 (on a PHP server) is that a file is a php file IFF it has a .php extension. In other words, I don’t consider a file with a .php extension a “valid” image — it’s extension is a major sign of it’s invalidity!

      On the second question, I’m not really talking about finessing config files or frameworks given the current state of the art. I’m asking why the state of the art is not better than it is.

      But I can imagine an incremental step to making this work better in a framework. For instance, we can make it so that all executable extensions need to be registered with the server (which is roughly the case already in many environments), and then the low level file handlers (in language plus environments like PHP, Python or whatever) are modified such that no file with such extensions can be written to the file system without an explicit request to do so. No need to rely on chmod if we want to avoid that for whatever reason.

      I’m not suggesting that’s perfect (maybe for socio-cultural-political reasons, PHP changes its file handlers, but nobody else does; maybe there’s holes in the implementation) but it’s way better than the current state of the art where an executing PHP file can currently generate another executing PHP file completely unintentionally.

    • http://jamessocol.com/ James

      > Thanks, but that still makes no sense to me. (I’m sorry if this makes me appear dull.) My personal approach to security is very much KISS. Rule #1 (on a PHP server) is that a file is a php file IFF it has a .php extension. In other words, I don’t consider a file with a .php extension a “valid” image — it’s extension is a major sign of it’s invalidity!

      That’s correct. You can construct an image, like a GIF or JPG, with PHP code in it. If you don’t also check the extension, that code can get executed. You need to do both, which is what I said before, and what we weren’t doing in the bug I linked from the article.

    • Taran’li Maren

      @James: I’m confused like voracity. If your server only interprets files with .php extensions, then why do you have to examine the contents of uploaded images? Accepting an upload with a valid extension will not result in the php code in the comments being executed. Worst case, the image is corrupted when viewed by a user.

    • http://jamessocol.com/ James

      @Taran’li: The issue in the linked bug is that we were not checking the extension. We were checking that it was a valid image, but forgot to check the extension, or assumed that Django’s ImageField would do that for us.

      It’s very rare that someone would configure a server to pass images through the PHP interpreter–though it’s possible–but it’s entirely possible to upload an HTML file with a .jpg extension. The server will serve it as an image, but some browsers, especially old IE, will ignore the Content-Type header in the response if the thing really looks like HTML, and execute it (and any inline scripts).

      So ideally, you want to 1) require valid image extensions, 2) validate that the images are valid, and 3) just to be on the safe side, strip extraneous comment fields from image formats that allow them. (3) will help in really rare cases, it’ll also make the images a little smaller, in terms of page weight.

    • https://progval.net/ Valentin Lorentz

      question “Are directories only writeable by the web server user?” should actually be “Are directories only writeable by the web application user?”.
      It is more secure to run each application in a different user account. If one is compromised, it cannot compromise others.

    • http://jamessocol.com/ James

      Valentin makes an excellent point and I’m updating the post accordingly.