The challenge page is a true script kiddie blog - teaching the fine art of
sqlmap and armitage. In the developer tools, we notice a cookie has been set:

```  
skidtoken=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6InNraWQifQ.eyJ1c2VybmFtZSI6InNraWQifQ.sacXoUrQCXpaylE4a4RGrCawHqBJJVGfOozOaPxQqOo  
```  
The JWT token decodes to the header

``` json  
{  
"typ": "JWT",  
"alg": "HS256",  
"kid": "skid"  
}  
```  
and the body

``` json  
{  
"username": "skid"  
}  
```

The kid field in the header represents a key identifier. The key identifier is
used to let the server know which key has been used to sign the token. This is
very useful for instance when the token issuing server rotates keys. This
allows for a grace period where tokens that have issued right before the key
rotation can still be validated by the server after the key rotation. The key
identifier is also useful for simply having many different keys at the same
time.

Anyway, this key identifier can often represent a key in a jwks.json file, a
regular file or a key in a database. We can look for a publicly available
jwks-file. We try a few different files:  
* jwks.json  
* /.well-known/jwks.json  
* skid.json  
* skid

and a few permutations of those, but no luck. Let's instead try to look for a
sql injection. We can just modify our token with for instance the tool on
jwt.io. Remember that since the kid field is used to look for the key used for
the signature, we do not need to provide a valid signature now. Let's just
change the kid to `skid'` and see if we can trigger an error. Change the
cookie value in developer tools and refresh the page.

```  
Bad Request

(sqlite3.OperationalError) unrecognized token: "'skid''"  
[SQL: select * from key where name like 'skid'']  
(Background on this error at: http://sqlalche.me/e/13/e3q8)  
```

Nice, the key is stored in a sqlite db and we have a sql injection
vulnerability! We can now use a union to choose our own key by effectivly
changing the query to

``` sql  
select * from key where name like 'a key that does not exist'  
union  
select <our key>  
```

But first we need to detect how many fields there are in the table. A few
tries gives us the correct number of columns. The final payload for our kid
field is `asdbqweqwe' union select 'a','a','a`. As we have replaced all fields
of the key with a's we can forge our token in jwt.io setting the secret to `a`
and the username field in the body to admin.

![SQL injection in jwt kid field in jwt.io][forging-token]

Updating our cookie with the forged token and refreshing the page reveals our
flag.

[forging-token]: https://lorentzvedeler.com/assets/imgs/jwt-with-sqli.png "SQL
injection in jwt kid field in jwt.io"

Original writeup (https://lorentzvedeler.com/writeup/2020/09/26/bsidesbos-
web/).