Write-Up Advent of CTF 2020 Challenge 9


The NOVI University Of Applied Sciences is offering an Advent CTF challenge for December 2020. The CTF is created by our community member of the and Chief Lecturer for Cyber Security at the NOVI University, Arjen Wiersma. If you want to participate in these CTF challenges, you can create an account on the website

Challenge 9

  • Description: Can you find a way to get into the Naughty List Management System as an admin?
  • 900 Points

Let’s start with the challenge. I visited the challenge URL on and ended on a webpage with a login portal for the Naughty List Management System.

Advent of CTF Challenge 9: Naughty List Management System

We can start with a simple SQL Injection on the login form. I used ' OR 1=1 as the first SQL Injection payload for the username and password field. After clicking on the button Login, to check the response, I got redirected to the webpage with the message Hey user your password is incorrect.

Hey user your password is incorrect

After reading this message twice, we can notice that user and incorrect are written in bold. Why is that? If we read your password is incorrect. Maybe is the username`` and password incorrect? Let’s give it a try.

The naughty list is currently empty

Well, we are making progress. According to the message The naughty list is currently empty.... we can conclude that this user account does not have the proper privileges to access the naughty list. We can check the cookies, in the Developer Tools, let’s check what we have.

Cookie in the Local Storage

Ok. There is a cookie value. This is the current cookie value:


This cookie is encoded with Base64 encoding. After decoding we can see the human-readable value of the cookie value.

{"typ":"JWT","alg":"HS256"}{"auth":31028,"text":"I do love a good puzzle.","role":"user","iat":1607540950}.rXdO%R.Í¿|mtv¥,Ê..6..,èº..²Þ..õ.

It seems that this web server is using JSON Web Tokens, let’s take a dive into that.

JSON Web Tokens

Well, I don’t have any experience with the JSON Web Tokens (JWT) yet, so let’s take a look at how it works. JWT is a standard for creating tokens that assert some number of claims. For example, a server could generate a token that has the claim “logged in as admin” and provide that to a client. The client could then use that token to prove that they are logged in as admin. The tokens are signed by the server’s key, so the server is able to verify that the token is legitimate.

The JWT is using an algorithm that generates the signature. Unfortunately, some libraries treated tokens signed with the none algorithm as a valid token with a verified signature. The result? Anyone can create their own “signed” tokens with whatever payload they want, allowing arbitrary account access on some systems.

The JSON Web Tokens are vulnerable to attacks. So, in this CTF Challenge we need to attack the JWT.

Generally, a JWT has three parts. The three parts are separated from each other with a single dot ‘(.)’.


With this information I can divide our cookie into these three parts

Header Payload Signature
{“typ”:”JWT”,”alg”:”HS256″} {“auth”:31028,”text”:”I do love a good puzzle.”,”role”:”user”,”iat”:1607540950} rXdO%R.Í¿mtv¥,Ê..6..,èº..²Þ..õ.
“typ”:”JWT” = type“alg”:”HS256″ = algoritme Contains the claims. Here is our role defined as user. A signature, based on the algorithm


We now know that this website is using JWT and we can modify the value to our own needs. Our current JWT cookie is using the HS256 algorithm, as we already know, we can change this algorithm to none. When we change the algorithm to none, we can also remove the signature part of the token. But beware, the JWT must continue to consist of three parts, so the token must end with a dot ..

We are now changing the value alg to none and the payload part "role":"user" to "role":"admin". The decoded token then looks like this:

header = {"typ":"JWT","alg":"none"}
payload = {"auth":31028,"text":"I do love a good puzzle.","role":"admin","iat":1607540950}.
signature = # empty because the algorithm is set to none

I’ve used CyberChef to encode the header and the payload.

header = eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0
payload = eyJhdXRoIjozMTAyOCwidGV4dCI6IkkgZG8gbG92ZSBhIGdvb2QgcHV6emxlLiIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTYwNzU0MDk1MH0
signature =

We can now put this cookie together, and separate the parts from each other with a dot ..


Replace the current cookie with the modified cookie and refresh the page, and we got the flag: NOVI{Jw7_f@ilure_in_n0ne}.

Advent of CTF Challenge 9 flag

It has taken me quite a long time to build this JWT, because I’ve decoded and encoded the cookie in one time, with all three parts at the same time. But, it’s very important to know that each part, the header, and payload must be encoded and decoded separately from each other.


Thanks for reading!


This post is licensed under CC BY 4.0 by the author.