5 ms·
I don't quite get it yet. Let's suppose someone sends a header like this: 'User-Agent:() { :; }; touch /tmp/shellshocked' Then in my cgi script I do a harmless
by candl 12y ago
I don't quite get it yet. Let's suppose someone sends a header like this: 'User-Agent:() { :; }; touch /tmp/shellshocked'
Then in my cgi script I do a harmless system('date') call. The file /tmp/shellshocked won't be created right? The file would have been created had I done for example a system('echo $HTTP_USER_AGENT') call. (That is, one needs to explicitly reference the environment variable that gets passed to bash). Is my understanding correct?
- phs2501 12y agoNo, bash interprets as functions ALL environment variables that begin with '() {' on startup. If you have an unpatched bash it will also excute any trailing commands after the function definition. You don't need to manually reference any environment variables at all to be vulnerable. This is to how the bash feature of exporting functions to subshells ("export -f") works.
- regularfry 12y agoThis is not my understanding. My understanding is that because this mechanism is intended to pass functions down to the system() call, all environment variables are parsed up front in case they contain any. Because the vulnerability lies in the parsing, it doesn't matter whether you reference the variable in the subsequent shell process or not.
- candl 12y agoOdd. I am running quite old software: echo $0 -> bash ls -l /bin/sh -> /bin/bash GNU bash, version 3.1.17(2)-release Apache/2.2.25 And I couldn't reproduce the vurnerability in a perl cgi script unless I had explicitly referenced an environment variable in the system() call like I posted above. I thought all versions are vurnerable. #test-cgi.pl use strict; use warnings; use CGI; print "Content-Type: text/plain\n\n"; my $q = CGI->new(); print "\nHEADERS:\n==============\n"; my %headers = map { $_ => $q->http($_) } $q->http(); foreach my $k ( keys %headers ) { print "$k\n $headers{$k}\n"; } system("echo hello"); #request.py import socket def build_request(meth, host, path, headers=None): req = "%s %s HTTP/1.0\r\nHost: %s\r\n" % (meth, path, host) if headers is not None: req = req + "\r\n".join(headers) + "\r\n" return req + "\r\n" sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ip_addr = 'xxx.xxx.xxx.xxx' sock.connect((ip_addr, 80)) headers = [ 'User-Agent:() { :; }; /bin/touch /tmp/testshellshock;', ] req = build_request("GET", ipaddr, "/cgi-bin/test-cgi.pl", headers) sock.sendall(req)
- rbh42 12y agoFrom "man perlfunc" unser "system": If there is only one scalar argument, the argument is checked for shell metacharacters, and if there are any, the entire argument is passed to the system's command shell for parsing (this is "/bin/sh -c" on Unix platforms, but varies on other platforms). If there are no shell metacharacters in the argument, it is split into words and passed directly to "execvp", which is more efficient. So your example does not invoke the shell.
- candl 12y agoPassing a shell metacharacter to the system function does indeed then trigger the vurnerability. Thanks as I didn't realize it wasn't calling the shell otherwise.