In this post, I'll be detailing how to pwn all of the flags in the Hacker101 CTF Micro-CMS v1 challenge. This level contains four flags, all which are centered around web application attacks. If you're just diving into web application testing, this is a straightforward and fun challenge. Let's jump right into it!
When we spin up the scenario, we are presented with the following page:
Flag 0: Stored XSS
To collect our first flag, we will perform a stored XSS attack. When we click on "Create a new page," we are presented with the following form:
We see a small disclaimer at the bottom of the page stating that Markdown is supported but scripts are not. We can confirm this by testing a simple payload in the large box:
This will generate a pop-up alert on the page if this field is vulnerable to XSS. When we click "create," we see the following and get no alert:
What if we test the title field? We can edit the page and modify it such that our payload is in the "title" field instead of the large box:
If we click save, we don't see anything happen:
However, if we navigate back to the main page by clicking "go home," we get an alert with the flag in it:
Note that because this is a Stored XSS, the pop up will generate every time you visit the page, so if you'd like to avoid that, do this part last OR access the page by it's index number in the URL bar, which would actually lead close to how we can find a later flag.
Flag 1: SQLi
Structured Query Language Injection, or SQLi, is when you can manipulate the queries that a web application makes to a database. This is dangerous in that it can allow an unauthorized user to gain access to sensitive information such as usernames, passwords, and PII. You can read more on SQLi here: https://portswigger.net/web-security/sql-injection
For this flag, as I mentioned at the end of the last flag's walkthrough, each page is referenced by an ID number in the URL, such as what's pictured below:
In the above example, 8 is the page identifier. In this scenario, the web application is accessing a database to retrieve the information displayed on page 8 via its identifier. The query would probably look like something below:
SELECT * FROM pages WHERE pageid = '8';
So what if we manipulated the query via the identifier parameter? Let's try adding an apostrophe to the end of the URL. Adding a single quote or apostrophe to a query often results in an error because it breaks the SQL syntax, and it also shows the attacker that the web application is likely vulnerable to a SQLi.
It doesn't work. Let's try the same thing with the page being edited:
A great additional resource to learn more about SQLi can be found here: https://www.briskinfosec.com/blogs/blogsdetail/While-testing-sql-injection-why-do-testers-frequently-use-single-quotes
Flag 2: IDOR
Insecure Direct Object Referencing, or IDOR, is when you can access sensitive information by abusing the parameters that point directly to an object or resource. For example, let's say that you can access account information for account #47852 at domain llamaglamaarbitrarywebsite.xyz by visiting the following URL:
If I change that account number and am able to access another account's information, we have an instance of IDOR taking place. This is one variation of IDOR, but you can find more information on the topic here: https://portswigger.net/web-security/access-control/idor
Whenever you access one of the pages on the website, the URL looks like this:
If you click on the pre-existing pages, you'll see that they have their own number as well. So what happens if we iterate through that number in the search bar?
Once we hit page 5, we get the following display:
We can't access anything here, and the page source doesn't reveal any information either. We have no hyperlink/button to edit the page...but what's the URL pattern to access the edit page? If you look at the screenshot from the previous flag, you'll see that the structure for the edit page URL was as follows:
What if we do that with this page that we're "unable to access" as well? If we modify the URL, we get the following result:
Flag 3: Stored XSS
If you recall from Flag 0, the large box in the edit page does not process scripts. What if we figured out how to get around that and perform cross-site scripting anyway? On the Markdown Test page we see that the code in the box generates a button without a function. Let's put it to use:
When we click "Save," we get the flag:
You can copy it by visiting the page source code.
I hope this was a helpful guide and wish you the best of luck on your CTF-ing journey!