You've successfully subscribed to N0Sec
Great! Next, complete checkout for full access to N0Sec
Welcome back! You've successfully signed in
Success! Your account is fully activated, you now have access to all content.


Author: Nameless0ne
Difficulty: Medium
Date Released: TBD

You've been hired by Billy Joel to get revenge on Ducky Inc...the company that fired him. Can you break into the server and complete your mission?

Topics Covered

  1. SQL Injection
  2. Systemd Privilege Escalation
  3. Flask

This is a medium box created by myself. I had a lot of fun creating this one because I got to work on some skills that I haven't had a chance to work on in a long time. The web app was created in Flask and I got some good practice in with databases and SQLAlchemy. The entire thing is reverse proxied through nginx as well so that was interesting to learn.

The entire room is as realistic as I could get it within my skill level at the time. It only is running on port 80 but since it's not on the open Internet, I figured not getting a self-signed certificate was fine. I spent a lot of time working on the web app alone. All of the graphics, with the exception of the front page corporate photos and parallax background were done by Varg.

So I hope the effort I put into this comes through to whoever does this room. Without further ado, let's get on with it.


We start our journey with the wonderful nmap scan


Only 2 ports open here and we know how it goes with SSH so lets go onto the only other option.

If we open up our browser to the IP address, we find the front page.

front page

Browsing around the rest of the website, we have more pages.


There's more to click on but we'll get to that in a bit. For now, these are our interesting pages. So, since we have a Login and Contact page, let's test both of those to see if they do anything

contact check
contact flash

Well it does look like it POSTs and seems to have some sort of validation on the fields but other than flashing the success message, it doesn't do anything else. Let's try the Login page.

login check

Again, some validation but it's just a GET. There's no backend stuff going on here. Moving on. Let's go with gobuster for this and try to brute force the directories that are available.


This was stopped early because I made the box and know what the missing directory was (it's templates) and didn't feel like waiting. But we do see there's an /admin page. So that's interesting. Let's go.


But we'll soon find that once we test this, it too is also just a GET. The two login pages were meant to keep with the realism but they weren't meant to go anywhere else.

So this leaves us with a few pages; the contact page and the different products that we haven't gone to yet. But first, let's try robots.txt just for the funsies (and because I know it doesn't go anywhere and wanna show the awesome 404 image Varg did)

no robots here

No duckies here. Now let's go check out some of the product pages.


So besides the images being awesome, we see some information about the different bulk types of duckies that Rubber Ducky Inc sells. Just pictured here above we have a Box of Duckies and a Pallet of Duckies. Not pictured are Truckload of Duckies and Dozen of Duckies. Each image seems to have a title, description/details, colors, price, and whether it's in stock or out of stock (how helpful!).

This can maybe tell us (and it does) that these pages are querying a database. You could intercept the request to one of the pages with Burp but I'll save you the trouble and just tell you that, yes, these are querying the database in some way.

I tried doing this in every manual way possible to get details of the databases and tables but couldn't get anything to drop/dump so I went with sqlmap for this.

The following images are going to show results of cached tests I ran prior to writing this writeup. You should get the same results. When running the scan, just press Enter to accept the default prompts.


Got our database, now the tables.

tables query

Sweet. Now let's select the user table

user table
user table 2

It looks like we have a table of users from different companies. So it looks like users are able to sign-up (somehow), are given an account with username and password with their sales or accounts payable email and company card. Oh, and would you look at that. I see something that looks like a flag (redacted) in the credit_card column.


So, next table of interest is probably that system_user table.

system_user table

We have 3 users here with emails, usernames and passwords. Obviously the interesting one is server-admin, which seems to be a shared account (maybe it's not...we don't know) and a few others. Just because I know which one is the right one to check, we're going to crack the password for server-admin.

Time for some Hashcat!


hashcat cmd

This was again cached for me so we'll just add --show to that to bring it out but if you run that you should get the password fairly quickly.

hashed pw

So our password for server-admin is inuyasha. Just like that, we have our credentials for foothold. On to the next section.

Initial Foothold

We have our foothold as server-admin. Let's login via SSH in our Kali terminal with ssh server-admin@

sudo -l

If we do sudo -l as above, we can see the commands we are able to run. We're fairly limited but it is just a server admin account after all. It's expected that they'll have limited access like this. If we do a groups check, we can see that we're part of the server-admin and www-data groups. That is interesting. We may be able to do something with that later. It's probably expected that this server admin would manage the web app in some way.

Since we know there's a web app running, we can probably check /var/www for more information. Heading over there, and we see there's a directory called duckyinc. Perfect! We found our webapp root folder.

If we poke around, we can see that it's written in Python! Woooo! This is where we'll privesc to root.


Privilege Escalation

So with that knowledge, we can probably safely assume that this is running as some kind of service on system start. We can check /etc/systemd/system to confirm. If we navigate to that location, we find a service called duckyinc.service.


So it's definitely a service running on gunicorn. It's running as flask-app with group www-data.

If we remember our output earlier from sudo -l we can run systemctl commands for this service. We can also sudoedit it. It doesn't matter that it's sudoedit in this case so long as we can edit it. Let's do that now to get to root.

modified service


If we enumerate using LinEnum or Linux Smart Enumeration or LinPeas once we become root, we can find that there's a bash script running but it's obfuscated so we don't know what it's actually doing. But if we remember back from our mission objecties, Billy wanted us to deface the website. Let's try doing that by editing index.html.


Once we edit this file in any way, the script checks it and returns the root flag in /root. We can navigate there in our root shell and grab the flag.

mission accomplished


This was a fun room to make (I don't think they're ever not fun though). I enjoyed learning about Flask and how to make a Flask app vulnerable to certain things. I could've gone a different way with this and done XSS or SSRF or something (ideas for a future room!). I hope you enjoyed it and learned something along the way.

Until next time cyber cowboy.