Natas Challenges (part 2)
Continuing to work through the OverTheWire natas challenges, this post covers solutions for levels 10 through 14.
natas10
Starting this off by going to: http://natas10.natas.labs.overthewire.org/
Login info is:
|
|
Looks like the same challenge as before, except that there is now filtering of ;
and &s
from the input strings. However, since that’s all the filtering that is done, it’s simple enough to just use a different escape-like character to execute multiple commands, this challenge can be solved with the URL encoding for a \n
, aka %A0
:
|
|
And the password:
|
|
natas11
Starting this off by going to: http://natas11.natas.labs.overthewire.org/
Login info is:
|
|
The hint after opening the page is:
Cookies are protected with “XOR” encryption.
Followed by a prompt asking for a cookie and a button to view the source.
Time to look at the source:
|
|
Looking over the source that’s available from the server, the process is the following:
- Pass default data into the “loadData” function
- Load the “data” from the saved cookie.
- Decrypt the cookie to check the values with the following operations:
- Base64_decode(…)
- Xor_encrypt(…)
- Json_decode(…)
- Once decrypted update the “default data” that were passed in and return the new values.
- Save the “loadedData” with the following operations:
- Json_encode(…)
- Xor_encrypt(…)
- Base64_encode(…)
One of the more interesting things to note is the xor_encrypt function used for both the save and load data (encrypt and decrypt). An interesting behavior behind XOR:
A = X ^ Y == A ^ X = Y
This behavior is interesting because despite not knowing the key that was used by the server, we do know what the expected value of the cookie is. Which a little bit of coding, we can exploit the behavior of XOR to get the key used by the server back. Once we have the key, we can update the value of showpassword
to yes
, re-encrypt the data, reload the page, and have the password show up, unlocking the next level.
Using the input of #ffffff
for the saved cookie produces the following:
|
|
It’s worth noting that %3D
is the URL encoding for =
, so really the cookie is,
|
|
Using the original “xor_encrypt” function from above and modifying it slightly to take in a key:
|
|
Create a function that takes in the original or default data, as well as the base64_decoded
cookie. The purpose of this function is to use the “known” data and our “encrypted” data in order to determine the key.
|
|
Create a function that takes in the base64_decoded
text, and our discovered key to decrypt the data (verifies that everything works as expected):
|
|
Put together with the known data (taken directly from the original source):
|
|
Grabbing the cookie from the browser:
|
|
Then call the function to determine the key used by passing in the base64_decoded
cookie:
|
|
Verify that we have the correct key by decoding the cookie entirely:
|
|
Update the defaultdata
's showpassword to yes and then encrypt with the key just found:
|
|
All that’s left is to take the cookie and put it into the browser and refresh.
Which gives us the password:
|
|
natas12
Starting this off by going to: http://natas12.natas.labs.overthewire.org/
Login info is:
|
|
This challenge has a simple JPEG upload form, with a max size of 1KB
, and an option to view the source.
Clicking the view the source:
|
|
One of the first interesting to notice, is it looks like $_POST["filename"]
reads from the input field filename
. Looking that over it seems to encode a random string and ALWAYS appends the .jpg
file extension to the end of it.
|
|
In the code from the server this function is used to determine a new random name, regardless of what the original upload name was:
|
|
The trick with this challenge lies here:
|
|
So the file extension is always tied to the $_POST["filename"]
, if we can change what the file ending is for the POST
, it should be possible to upload any arbitrary file.
The end goal here is to upload a simple php script to execute a command to read the password for natas13
. The payload we need to create php file with the following contents:
|
|
Back in the browser, use the inspector to change the hardcoded file extension to php
. After that upload the php payload and recieve a link to execute the php script.
Doing so reveals the password:
|
|
natas13
Starting this off by going to: http://natas13.natas.labs.overthewire.org/
Login info is:
|
|
This challenge is just like natas12, except this time around there’s better security:
|
|
This time around there’s an explicit check on the exif_imagetype
. Looking up the documentation exif_imagetype:
exif_imagetype()
reads the first bytes of an image and checks its signature.
In order to still have our code get executed, the same sort of exploit as last time can be used, except the php payload that is uploaded needs to have a few bytes added to the beginning to bypass this exif_imagetype
filter.
On linux there a hex dumping tool called xxd
that can be used to look at a real jpg
. By looking the raw bytes of the jpg
we can figure out what the first few bytes are that would be checked by exif_imagetype
. Most files have some sort of identifying header information that applications use to know how to parse it. Wiki has good details about JPEG File Interchange Format.
In the case of a jpg
the contents look like:
|
|
So all that’s left is to insert these bytes at the start of the php payload, a quick one line python script should do the trick:
|
|
Following the same process as last time with our new and improved php file as we did in natas12
, results the password of:
|
|
natas14
Starting this off by going to: «http://natas14.natas.labs.overthewire.org/>
Login info is:
|
|
With JPG upload bypasses covered, it’s time to move onto username and password login bypasses that are validated via SQL queries. Presented with a form asking for Username and Password, and a button for viewing source:
The source shows the following:
|
|
Based on the source it seems there’s a debug option to print out the query that was executed to check to see if the username and password is valid. We can abuse this with the following:
|
|
Which gives us the following output:
|
|
The interesting thing here is that the query doesn’t seem to be well guarded against improperly formatted input which opens the door to sql injection attacks.
Ultimately the code is just checking that the result from the query is greater than 1:
|
|
The trick here will be to always get a positive value out of the query, regardless if the username and password are actually valid. Given the lack of checking against the characters provided, it should be possible to abuse the input and have the sql query ignore the username and password and evaluate any condition provided, in this case using an OR
with an always true statement.
In practice this means that the input needed is: " or "a"="a
. The first "
closes off the opening quotation mark allowing for the OR
to be evaluated as an SQL statement. That statement is "a"="a
, which is always true. One thing to notice is that there is not final "
, that is because the original sql statement would normally have included that had we not closed it early.
In practice this looks like:
|
|
And here we have the password for the next level:
|
|