Level 18
In this level we’re given access to the source behind index.php
. I originally thought there might be something in the way user inputs were compared but no luck. 2 things caught my attention - the first being a comment on the maximum number of sessions: $maxid = 640; // 640 should be enough for everyone
, followed by the snippet below:
Which seems to indicate some sessions would already have the admin
flag set - so why not iterate through all 640 of them and see if the flag is set correctly somewhere?
I fired up Burp Intruder but given I only have the community edition, which throttles requests, it turned out to be faster to write the NodeJS snippet below:
And soon enough:
sessionId: 119 + <html>
<head>
...
<div id="content">
DEBUG: Session start ok<br>You are an admin. The credentials for the next level are:<br>
...
Level 19
We’re told the code for this level is similar to the previous one, but that the format of session ID (PHPSESSID
) differs.
Using Burp’s sequencer I gathered close to 10,000 tokens. A quick run through sort | uniq
led to a list of 640 unique tokens. I ran through those fairly quickly with the below:
But none of them worked - something wasn’t right. From looking at the tokens, it was clear there was a part that was static: 2d616263
. This turned out to be hex for -abc
, abc
being the username I originally tried to log in with!
Essentially I could re-use the code for natas18, but would need to append -admin
to each session id and convert it to hex instead. A few tries later, we’re in!
For the record the session was derived as: const s = Buffer.from(
${sessionId}-admin).toString('hex');
Level 20
This one is a little different from the previous 2 given the session ID seems pretty random. A quick look at the code however reveals a red flag. The mywrite
function:
And myread
:
Whatever we pass in as the username will be written to file and read back as key/value pairs in the $_SESSION
object. So if we could add admin 1
as an entry, we’d be home free. In other words, we need to add a new line to get the mywrite
function to essentially write 2 entries.
Modifying the request to foo%0Aadmin%201
(with \n
and (space)
URL-encoded) does just that - though note I had to modify the request directly in Burp vs through the textbox for this to work.
Level 21
We’re presented with a page that states it is co-located with natas21-experimenter. The code on the main page indicates we’re back to figuring out how to stuff admin=1
in $_SESSION
- but there’s nothing on this page that would allow us to change that.
The other page however (natas21-experimenter) allows user input - lots of it. Looking at the code, the following snippet jumps out:
We’re free to add new parameters to $_REQUEST
when submitting changes and those will be set in $_SESSION
- yay!. Adding &admin=1
to the POST
parameters does the trick. However, this isn’t the site we need those on.
Instead we grab the referer header along with the cookies and pass those back to the original site:
Referer: http://natas21-experimenter.natas.labs.overthewire.org/index.php
Cookie: __cfduid=dc5dfb9ecd6e2ed04913757fe15630eb81548476605; PHPSESSID=d0vhsull9qme8gi98ic81etna5
This tricks it into re-using the session we created for natas21-experimeter
- which contains admin=1
. Done!
Level 22
The source tells us the credentials for natas23 will only be displayed if if(array_key_exists("revelio", $_GET))
- but the snippet at the top strips all our parameters (the header
function is essentially a redirect).:
If we were to view this in say Firefox, the browser would automatically follow the redirect to /
. But with curl
, which doesn’t follow redirects by default, it’s easy: curl -v --user natas22:<password_for_natas22> http://natas22.natas.labs.overthewire.org/?revelio -o - | grep Password
Level 23
The snippet of interest is as below:
strstr
returns the first occurrence matching the string. The part that’s interesting however is the numeric comparison $_REQUEST["passwd"] > 10
. This being PHP, the way it ‘converts’ a string to a digit is by stripping all characers apart from numeric ones. So if passwd=20plussomerandomtext
, in a string context this would be 20
. Funky heh?
Level 24
This level highlights some more PHP oddities:
strcmp
is known to behave oddly when the first argument is an array (see the official documentation, in the comments section). Try if for yourself here! Passing in ?passwd[]=foo
as an argument does the trick.