# Notepad Series - InCTF Internationals 2021

tl;dr

• Notepad 1.5 - CRLF on the name parameter of Golang’s Header().Set() method
• Notepad 2 - Xsleaks using Timing-Allow-Origin header

Challenge Author: Az3z3l

## Initial Analysis:

All three challenges almost had the same base code with slight changes leading to different vulnerabilities. The challenge is a notepad application, where a user can enter whatever data they want. Only one note can be stored at a time. The notes are mapped to the user using their cookie. All the notes are retrieved from /get endpoint. Other endpoints are /add which adds a new note and /find. The /find endpoint is interesting. It has several parameters like condition, startsWith, endsWith and debug. The debug parameter which when set, can add a header in the response if your note doesn’t match your query. The

ie., consider the user’s note to be inctfi_123 and the request is /find?startsWith=incth&debug&addnew=param, the response would contain addnew: param as a header, but, if it is /find?startsWith=inctf&debug&addnew=param, the response contains no additional header.

Note: The cookie is set to HTTPOnly for all the challenges and SameSite is Lax except for the last challenge. The /find api has the following headers set to it be default

## Notepad 1 - Snakehole’s Secret

Number of Solves: 21
Points: 823

### Challenge Description

Janet Snakehole, the rich aristocratic widow with a terrible secret, is being investigated by the FBI’s number 1, Burt Tyrannosaurus Macklin. Burt found a website that she visits often. See if you can find anything.

### Solution

In this challenge the note of the user is inserted into the HTML document using innerHTML and no sanitization is done on the backend. So a user insert arbitrary HTML and get XSS. But this is just a self-XSS. To get XSS on the admin side, we can use the /find api to set a Set-Cookie header and use our own cookie on admin. The final payload is

Flag: inctf{youll_never_take_me_alive_ialmvwoawpwe}

## Notepad 1.5 - Arthur’s Article

Number of Solves: 16
Points: 900

### Challenge Description

Arthur Morgan was asked to retrieve an important article from Cornwall’s computer. Help him steal it.

### Solution

In this challenge, the XSS bug is removed and the Header setting part gets weird.

In, Notepad 1, the Header name was compared with a regex, but in this challenge, only the value is compared with a regex. With a bit of testing, one can understand that Header().Set() is vulnerable to a CRLF bug in the name parameter. Final payload that can be used is

Some of the unintended ways using Xsleaks are, Refresh header with a redirection back to a webhook and Content-Disposition header to download the page and check for navigation.

## Notepad 2 - Ken’s Chronicle

Number of Solves: 14
Points: 925

### Challenge Description

Arthur Morgan was asked to retrieve an important article from Cornwall’s computer. Help him steal it.

### Solution

This challenge was based on XSLeaks. The challenge uses a Secure cookie with SameSite as None. One other important difference in this challenge is the typo "X-Frame-Options": "DENI",. This allows the page to open in an Iframe. The Header setting part is shown below.

In this, we are allowed to set only a Header value of less than 4 characters. And it also disallows a Header name that matches [A-Za-z]{7}-[A-Za-z]{11}(Intent was to block Content-Disposition). The idea was to use Timing-Allow-Origin: * header. This header allows the host to use the performance api on the request used to fetch that resource. Without Timimg-Allow-Origin header, performance api doesn’t give back the full result, but a minified version of it.

The state I used in my POC was nextHopProtocol, which would be equal to “” if the header was not set. So, if our startsWith is correct, nextHopProtocol would be empty.

Exploit:

One other way to do this is use Refresh header and counting the onload events. Since this challenge uses a SameSite: None, has no Iframe protections, aaand the number of headers we can use are vast, there are quite a number of ways to solve this.

Flag: inctf{tis_a_mooo_point_lkbsdgbyhsl}