Wargame: Natas
Level: 11
Category: Web Exploitation
Description
The page stores preferences in a cookie named data. The value is XOR-encrypted with a secret key then base64-encoded. The goal is to forge a cookie that sets showpassword to yes.
Overview
- The server XOR-encrypts a JSON object with a short repeating key, then base64-encodes the result before setting it as a cookie.
- XOR encryption is reversible: if you know both the plaintext and ciphertext, you can recover the key.
- We know the default plaintext (
{"showpassword":"no","bgcolor":"#ffffff"}), so we XOR it against the decoded cookie to find the key. - We then re-encrypt modified JSON (
showpassword: "yes") with the recovered key and send the forged cookie.
Background: Known-Plaintext XOR Attack
- XOR has the property that
C = P XOR K, soK = P XOR C. - If the key is shorter than the plaintext, it repeats cyclically; the key length can be found by looking for a repeating pattern in
P XOR C. - Base64 encoding is not encryption; it only obscures the binary data from casual inspection.
Solution
Step 1: Extract the Default Cookie
- Make a GET request to the page and read the
datacookie from the response. - Base64-decode the cookie value to get the raw ciphertext bytes.
Step 2: Recover the XOR Key
- XOR the decoded ciphertext byte-by-byte against the known default plaintext
json_encode(["showpassword"=>"no","bgcolor"=>"#ffffff"]). - The result is a repeating sequence; use a regex to find the repeating unit.
- The key is
qw8J.
import base64, json
default = json.dumps({"showpassword": "no", "bgcolor": "#ffffff"}, separators=(',', ':'))
ciphertext = base64.b64decode("MGw7JCQ5OC04PT8jOSpqdmkgJ25gbCorKCEkIzlscm5oKC4qLSgubjY=")
key_stream = "".join(chr(ord(p) ^ c) for p, c in zip(default, ciphertext))
# key_stream repeats "qw8J"
key = "qw8J"
Step 3: Forge the Cookie
- Construct the modified JSON with
showpasswordset to"yes". - XOR each byte with the repeating key, then base64-encode the result.
target = json.dumps({"showpassword": "yes", "bgcolor": "#ffffff"}, separators=(',', ':'))
cipher = bytes(ord(c) ^ ord(key[i % len(key)]) for i, c in enumerate(target))
forged = base64.b64encode(cipher).decode()
Step 4: Send the Forged Cookie
- Make a GET request with
cookies={"data": forged}. - The server decrypts, finds
showpassword == "yes", and prints the password.
Password
YWqo0pjpcXzSIl5NMAVxg12QxeC1w9QG