What
A small CMS, with very basic functions.
Difficulty: Easy
Flag0
Hint0: Try creating a new page
Hit the link Create a new page.
Fill out title and content.
Click Save button to create the page.
Hint1: How are pages indexed?
Pages are indexed with ascending numbers in a form of /page/$
(like *.ctf.hacker101.com/page/1, /2, etc.)
Hint2: Look at the sequence of IDs
Testing is /page/1
.
Markdown Test is /page/2
.
The page we have created starts at */page/11
.
What is between page/2
and page/11
?
Hint3: If the front door doesn’t open, try the window
Edit the page ID in the address bar and open page/3
, page/4
, etc.
You’ll find that /page/5
is Forbidden.
Hint4: In what ways can you retrieve page contents?
When you open /page/1
(Testing) or /page/2
(Markdown Test), or on the page you’ve created, see that link Edit this page?
Open any pages above for editing and check the URL!
It is /page/edit/$
.
Change the ID to 5 (/page/edit/5
) and collect the first FLAG.
Flag1
Hint0: Make sure you tamper with every input
What inputs do we have on this site (make a habit of manually looking around on a site)?
There are form inputs on Edit Page (/page/edit/$
) and on Create Page (/page/create
):
Title:
<input type="text">
Text:
<textarea name="body">
Hint1: Have you tested for the usual culprits? XSS, SQL injection, path injection
XSS has worked only on Title field (see FLAG2). There is a comment under the textarea: “Markdown is supported, but scripts are not”.
For SQL injection, see last hint.
No luck with path injection.
Hint2: Bugs often occur when an input should always be one type and turns out to be another
Title field expects text, javascript worked here (see FLAG2).
Body textarea accepts only markdown, javascript filtered there.
URL expects only numbers as page ID.
Hint3: Remember, form submissions aren’t the only inputs that come from browsers
… Also, there is the address bar in the browser.
Put a single apostrophe (') after the page’s URL in the address bar, like /page/edit/1'
for the FLAG.
This simulates the case when a page ID (in this case “1”) is processed by a backend script and used in an SQL query without sanitizing it first. See more on SQL injection (a very basic injection would be something like /page/edit/1' or 1=1; --
), but here, to get the flag, a single apostrophe is enough. I’ve tried some basic injection after it without luck.
Flag2
Hint0: Sometimes a given input will affect more than one page
The first input I’ve tried has resulted in a FLAG.
Open a page for editing, then insert <script>alert('1')</script>
into the Title field:
Create the page.
Hint1: The bug you are looking for doesn’t exist in the most obvious place this input is shown
You are inserting the XSS on some page’s Title field. If you reload the page, nothing happens. Try navigating to the Home page :)
Home page lists the page titles in an unordered list. List items use Title field values without satitation. This is where our payload kicks in.
Flag3
Hint0: Script tags are great, but what other options do you have?
Using markdown, you can insert URLs, buttons, images on the page.
If you load Markdown Test page (/page/2
), there is an example for an image (broken) and a button element.
Edit the page.
Look up on HTML/JS reference, what inline options you have for a button tag. I’ve inserted onclick="alert('3')"
here.
Save the page, XSS would just work fine. But where’s my FLAG?
Check the source of the page to get your last FLAG!
I’ve also tried XSS on the image element, following this link, but couldn’t manage to make it work.
Takeaway(s)
- Manually try all available functions of the site, understand how they works
- Whatch for low-hanging fruits, like unsanitized user inputs (XSS, SQLi)
- Look for “missing” pages