34 ms·
I finally understand how it can be used.
by CSDude 12y ago
I finally understand how it can be used.
- jMyles 12y agoI'm sorry; perhaps I'm slow. I see the problem, but how can a stranger set an environment variable?
- smsm42 12y agoIn a webserver, like Apache, environment variables are set from headers sent by the client, e.g. each header like Cookie would produce variable like HTTP_COOKIE. These variables can contain any data that the user sent. If Apache uses external code (like PHP, Ruby, Python, etc.) to process the request, it may pass these variables to that code, and if that code runs some command on the system, these variables may be passed to the command shell, which would lead to code contained in the variable to be executed at that point. This can also happen with other service processes - such as OpenSSH, that sets ORIG_SSH_COMMAND variable to the command that the user supplies. That may allow people to break out of restricted accounts -i.e. accounts that are supposed to run just one command (ssh-based services, like SVN or Git, may be an example) and run arbitrary commands under such user.
- pbhjpbhj 12y ago>OpenSSH, that sets ORIG_SSH_COMMAND variable to the command that the user supplies // So they set shell vars without sanitising them first?
- JackC 12y agoAs an analogy, suppose I go to a website written in PHP and register with the username "Robert'); DROP TABLE Students;--". A correct PHP script will sanitize the name; it'll escape the quote and run something like `update users set name='Robert\'); DROP TABLE Students;--'`. If mysql then ignores the backslash and drops the Students table, that is definitely a mysql problem and not a PHP problem. Doing any more on the PHP side to "sanitize" the name would actually break the script by screwing up valid names. In this case, the shell variables are correctly sanitized by Apache or whatever, and then mishandled by bash. For example, imagine this very simple system: - Web server receives a GET request with the user's name. - Web server sets the environment variable USERS_NAME='<whatever was submitted with quotes escaped>'. - Web server sends back the result of running `bash print_welcome_message.sh`. It might not be considered great design, but there's nothing inherently insecure in this system, and there are plenty of actual systems that more or less work this way. And it's also perfectly valid for a user to have the name `() { :;}; echo vulnerable`. It ought to work fine to set USERS_NAME to that value and send back `Welcome, () { :;}; echo vulnerable.` Instead, an unpatched bash will execute the contents of USERS_NAME. The only way for the web server to prevent that would be to change the user's name, which would be wrong behavior -- given a properly working shell, it would print the wrong name in the response. The web server does its sanitization job correctly when it successfully sets USERS_NAME in spite of any single quotes or what-have-you -- this part isn't its problem.
- digil 12y agoAhh, Little Bobby Tables. http://xkcd.com/327/ http://xkcd.com/327/ :)
- vertex-four 12y agoCGI scripts is the most obvious way - when executing a CGI script, each HTTP header gets translated into an environment variable - but I have no doubt there's all sorts of odd network-facing apps which set environment various and then run a command, even if you're not running CGI scripts.
- pbhjpbhj 12y agoSurely though the CGI framework sanitises the headers first? Otherwise this seems like it's a pretty predictable problem - isn't "always sanitise user data" the cardinal rule of backends. I can certainly imagine that I might have designed a web page that passed user input direct to a BASH script to do a ping or some such, but not if it's public facing.
- SwellJoe 12y agoOne of the comments in this thread (http://seclists.org/oss-sec/2014/q3/650 http://seclists.org/oss-sec/2014/q3/650 ), seems to indicate that Apache is an attack vector for this vulnerability.
- AgentME 12y agoWhat sanitization do you expect the CGI framework to apply to the header value representing the user agent? str_replace($userAgent, '() {', 'no bash bug for you')? Only a few environment variables are given any meaning by the system. Other environment variables don't have any predefined meaning and can be any null-terminated string.
- pbhjpbhj 12y agoIndeed, lol. It's a bit clearer to me now. Thanks for your comment. It seems like a sort of loose typing issue. Perhaps if when setting environment variables the app using them could specify a type (eg nonExecutableText) such that bash knows it's receiving textual content that mustn't be executed; would that help?
- base698 12y agoThere are a lot of scripts the do something like: curl 'http://myradframework.com/script.sh' http://myradframework.com/script.sh' | bash That'd be pretty easy to do this if they weren't honest or man in the middle attack the site.
- notdonspaulding 12y agoThat's not really the risk with this vulnerability. Piping a web-sourced script to bash has always been a vulnerability, but it's one that you choose to live with when you do it. The reason this is newsworthy is because there are some network-facing programs (CGI-based web servers, some SSH configurations) that will set the value of some environment variables to a user-supplied value, which bash will then be executed by bash when that program spawns a new process.
- jonhohle 12y agoThat will run arbitrary code regardless
- 0x0 12y agoLots of internet facing software fills env vars with user data: Apache may set several SSL_* vars and HTTP_* vars, ssh may set LC_*, LANG, TERM, etc; procmail and other smtp filters probably have their fair share too. The moment any child process of these hit a system() or popen() like call, /bin/sh initializes and may hit the bug.
- pbhjpbhj 12y agoSo it's a sort of injection attack that targets inputs to bash that manage to bypass normal sanitisation? Apache takes SSL_* headers, say, from a client and simply passes those to BASH and this exploit means that BASH will execute a payload dropped in to the header?Am I close? Wouldn't that also be an Apache [httpd] bug in that it's allowing unsanitised user data to hit the shell? Similarly are you saying that if I set a LANG variable and SSH to a server that the server will use that variable to give to BASH, even if it's not a recognised LANG variable? Perhaps I'm misunderstanding as such things would be massive holes any way regardless of this BASH issue. From the example code at the top of the thread it seems that you only need to affect a single variable, that bash reads, in order to pwn the whole server. Interestingly on Ubuntu the BASH update for this is rated "medium".
- pfg 12y agoIt's kind of the equivalent of a web app that basically evals any given GET parameter with a specially crafted value. Apache sets environment variables, it does not pass user input directly to bash as code or anything like that. The fact that bash can be tricked to execute this code is a problem that needs to be addressed by bash, not any other software.
- pbhjpbhj 12y ago>"Apache sets environment variables, it does not pass user input directly to bash as code or anything like that." // This is contrary to how I'm understanding the situation. BASH, or whichever shell is being used, sets environment variables; Apache httpd et al. pass off some user data (from clients, eg browser headers) to the shell to set variables under limited circumstances [like use of CGI], no? Then when BASH gets initialised something is happening in the parsing of variables causing statements included with the variable (which variable can be a function definition) to be executed. I realise now that as things stand you can't sanitise many of the fields [like http client headers] as they don't have well defined forms. But setting variables for use by BASH seems as close to "pass user input directly to bash" as you're going to get. Mainly I'm doubting that all these different apps duplicate code to set env variables when the shell already knows how to do it, doesn't seem very *nixy. Happy to be corrected as I'm - as I'm sure you've guessed - a bit out of my depth.
- chappar 12y agoHere is a simple c program to demonstrate this. #include<stdio.h> #include <stdlib.h> int main() { setenv("VAR", "() { :;}; echo vulnerable", 0); system("ls"); } #./a.out vulnerable a.out #
- daveloyall 12y agoThat's awesome. Does system() invoke /bin/sh? Does it look for 'sh' on the path? What are the rules?