This level has a second site associated with it, where all the action is:
Main Site
PHP sourcecode of the main page:
The main site needs “admin” session variable set to 1 for us to get the next password.
Experimenter Site
The PHP sourcecode of the experimenter page:
The first thing I noticed on the experimenter site is the use of “DEBUG” variable again, so I immediately set it for future use. When looking at the requests in Burp, I noticed the request for the main site and the experimenter site have different PHPSESSION cookie values, so that may be a problem when we’re trying to set “admin=1” for the main site.
There’s a line in the source that sets some HTML with values we have control over, so maybe we can inject HTML. $form .= “$key: <input name=’$key’ value=’$val’ />”;
Tested an injection of ‘ />admin:<input name=’admin’ value=’1 on the “bgcolor” value. Success with the injection!
To use the debug flag while we submit the form, put it all in the address bar like “/index.php?debug&align=center&fontsize=100%25&bgcolor=yellow%27%20/%3E%3Cbr%3Eadmin:%3Cinput%20name=%27admin%27%20value=%271&submit=Update”
Looking at the page source for this is pretty revealing:
From looking at the debug output, it looks like can modify our injection to get placed into the session array instead of the HTML. It’s a little easier to do within Burp Repeater than it would be in the browser:
Success! Notice how "[admin] => 1" is injected into the session array.
All we should have to do is then change the PHPSESSID of the main site to this one and reload. Just load the main site request into Repeater and change the PHPSESSID value, then Send… BUT IT DOESN’T WORK!!
Maybe we DO have to inject the value first into the HTML to set it into the Session Array. Since we have to interact with the ‘Update’ button on the page, use the browser for this part. Use the HTML injection from earlier for the “bgcolor” value, yellow’ />admin:<input name=’admin’ value=’1, then press the ‘Update’ button. When you get the response, the HTML should be changed to include our admin value. Then press ‘Update’ once more to add the values into the Session Array.
Check that it worked by using the Burp Repeater again on the main site, don’t forget to change the PHPSESSID value to the experimenter site!
AWESOME! It worked!
LEVEL 22
This level is almost completely blank on the HTML, only a link to the sourcecode! Let’s see it…
This time it is checking for a variable 'revelio'. And that’s ALL it’s checking for!! This level must be a Harry Potter joke.
Sure enough, that’s all it needed!
Doing this from the browser doesn’t get the same results though, because there’s a redirect, “Location: /”.
LEVEL 23
Here we only have a password entry form.
Looks like the function strstr() is being used to search a variable ‘passwd’ for the phrase “iloveyou”. The only other check is that ‘passwd’ equals a number greater than 10. So there is a check for a number, and a check for a string. It appears that putting a mathematical operator in the second check must force it to treat the string as a number, dropping off the invalid non-numerical characters. Because “11iloveyou” works!!
LEVEL 24
This is another password input form just like the last level. Here is the sourcecode for this one:
This password check is using strcmp() this time. Go straight to the manual page to see if there’s anything interesting about it. The first thing that catches my eye is the return values.
“Returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal. ”
This is used in a boolean check, so “0” means False. There is a NOT operator on the strcmp(), so that would mean a “0” result means True now. The way to get the intended result is if the strings are equal. We’re probably not going to just guess the password, so maybe there is something else we can exploit in the return values.
One of the comments on the manual page is interesting:
<span class="html">strcmp() will return NULL on failure.</span>
This has the side effect of equating to a match when using an equals comparison (==). Instead, you may wish to test matches using the identical comparison (===), which should not catch a NULL return.
Please use strcmp() carefully when comparing user input, as this may have potential security implications in your code.
Getting it to return NULL might give us a useful side effect. In the example in the comment, the variable is assigned an array to get a failure. So to force the ‘passwd’ variable to an array, put in /?passwd[]=something for the query. That returns an error message and success!
LEVEL 25
This level starts out with a block of text that gets replaced when you change the language setting.
Sourcecode:
Looking at the source there are a couple of things that jump out at me. First is the homegrown checks on input for the language file. Those checks can probably be gotten around. Also there is a logfile getting written to that may be vulnerable to a stored XSS type of attack.
Objective 1
Try to get around the checks on the included language file.
I started out with getting one of the checks to fail, to see what would happen and to create the log file, using /?lang=/../logs/natas25_g2ouhkp80fj036rpalvnpb9l13.log There was no obvious result on the response page, but maybe the log file was created.
Next I tried /?lang=/…/./logs/natas25_g2ouhkp80fj036rpalvnpb9l13.log. Important point being the “../” was removed from “/…/./”, leaving “/../” correctly in place. I get the expected log output as:
Objective 2
Get around the check for “natas_webpass”.
Stored XSS is likely possible on the log file using the User-Agent string, since that gets saved. Injecting some PHP that reads “natas_webpass” should bypass the check on our variable.
Write “User-Agent: <?php include(“/etc/natas_webpass/natas26″); ?>” into the HTTP header using Burp Repeater: