8

Does the recent shellshock vulnerability in bash affect stock Django? Assume any of the production setups listed on the Django site are used (gunicorn, wsgi, nginx).

If not, are there any commonly used Django extensions that could be vulnerable?

Obviously, bash should be updated regardless, but most coverage of actual exploits in the wild has focused on PHP/Apache setups, and I haven't seen anything about Django.

Anders
  • 64,406
  • 24
  • 178
  • 215
fredley
  • 1,455
  • 1
  • 16
  • 25

2 Answers2

5

A security advisory about the matter was posted on the Django blog:

This issue does not affect Django directly, but will affect most users of Django.

Any web server which is serving traffic over a CGI or CGI-like interface (including WSGI) should upgrade its version of Bash immediately.

schroeder
  • 123,438
  • 55
  • 284
  • 319
  • How does it affect WSGI? – Smit Johnth Sep 28 '14 at 01:55
  • An update to the advisory says: "In its usual configuration WSGI, unlike CGI, does not set shell environment variables from the request, and so is not vulnerable (unless you are setting shell/OS environment variables based on request data yourself)." – Hamish Downer Sep 30 '14 at 13:38
  • @HamishDowner in the future use '@nick' tag so the person you mention gets a notification. – Smit Johnth Jan 02 '15 at 19:26
4

Update bash, and this specific problem goes away.

But if you want to know if you were vulnerable before this, there will be application specific paths to add to generic vulnerabilities (until bash is patched - then there may be new non-bash vulnerabilities discovered later with the same pattern).

The specific problem is in allowing attacker controlled environment variables. If the attacker is able to remotely get an environment variable set to a function definition followed by an immediate command; the attacker could wait for some totally unrelated command to get exec'ed by bash. It does not matter which bash program it is, or if the arguments were validated (or hardcoded, etc).

Specifically, bash has a main entry point like any other program, and it has this signature:

int main(int argc, char** argv, char** arge); //bash's main entry point

This main function gets invoked as an internal detail of invoking an exec. If arge was not cleaned before-hand, the main of bash will dutifully do what the bash shell is supposed to do. One of those things is parsing the environment.

We are all in the habit of scrubbing argc and argv for cleanliness. But most people totally ignore what is in arge. So if a process was told by a remote socket to set an environment variable (ie: HTTP_COOOKIE) then some entry of arge has that value. Say that arge[42] has a value:

HTTP_COOKIE=() { :; }; /usr/bin/eject

Then bash's main sees that the string value has the open/close parenthesis, and guesses that this must be a function definition. So it dutifully defines HTTP_COOKIE as a function, and also executes the immediate command after it.

So, if the environment has this variable, nothing bad has happened yet. But you could easily be calling innocuous Python code that isn't obviously executing bash. This is all you see:

Licensing().check()

Perhaps there is a binary that your company uses that checks a license, and you call this function (you don't know what it does). But say that ultimately what it does is this (resolved to the C implementation):

//There are no arguments to this program so this is "safe"
execl("/bin/bash", "bash", "-c", "licensingWrapper", (char*)0);

Then bash starts up...

//This is bash's main function
int main(int argc, char** argv, char** arge) {
    ....
    parseEnvironment(arge);  //!!!!
    ....
}

Then in parseEnvironment, at arge[42] it sees some variable named 'HTTP_COOKIE' and parses it. bash hasn't got the faintest clue what this variable is for, but it sees that it's a function definition with some immediately executed command; and just does it. This environment parse is just a standard prerequisite for getting the shell ready to execute whatever argv says to execute.

If you think about this a bit deeper, it is just another case of not cleansing input. Nobody cleanses environment input. To make things worse, the environment variables get interpreted differently based on what they are being passed in to (bash, sh, java, ...). So if you had a generic function to cleanse the environment, it would be specific to the kinds of exec you expect to get run later.

int main(int argc, char** argv, char** arge) {
    BOOL isClean = TRUE;
    isClean &= cleanseEnvironment(arge, BASIC_SANITY);
    isClean &= cleanseEnvironment(arge, BASH_RULES);
    if(isClean) {
        parseEnvironment(arge);
    }
    else {
        return -EBADENVIRONMENT;
    }
    ...
}

So I would be highly suspicious of environment variables being set to attacker tainted values. Then simply assume that some shell that you hadn't thought of will get executed with that environment later. You have an obvious problem if you can show that bash is eventually executed. But it could easily be an indirect path, like tcl being executed, then tcl causes bash to get invoked.

Rob
  • 639
  • 3
  • 9
  • "The specific problem is in allowing attacker controlled environment variables." +1 for that. Any feature is a security threat in the same time. If it's not needed - it has to be turned off. – Smit Johnth Jan 02 '15 at 19:28