What

A small CMS, with very basic functions.

Home page

Difficulty: Easy

Flag0

Hint0: Try creating a new page

Hit the link Create a new page. crete page (blank)

Fill out title and content. create page (filled)

Click Save button to create the page. create page (executed)

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.

/page/5

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? Edit 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. Edit forbidden page 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.

URL 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:

XSS on Title

Create the page.

Save 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 :)

FLAG2

XSS on 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.

Markdown Test

Edit the page.

Edit Markdown Test

Look up on HTML/JS reference, what inline options you have for a button tag. I’ve inserted onclick="alert('3')" here.

button onclick XSS

Save the page, XSS would just work fine. But where’s my FLAG?

Onclick XSS works

Check the source of the page to get your last FLAG!

Onclick XSS 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