什么是sql注入
- 通过操纵SQL语句,使得应用程序在数据库上执行攻击者指定的恶意SQL语句的一种攻击方式。攻击者可以通过应用程序的输入界面,如表单、URL参数等方式,将恶意的SQL代码注入到应用程序中,从而访问,修改,删除甚至控制数据库内的数据和系统。
sql注入原理
- 针对 SQL 的攻击行为可以描述为通过用户可控参数中注入 SQL 语法,破坏原有 SQL 结构,达到编写程序时意料之外结果的攻击行为,其成因可以归结为以下两个原因叠加造成的:
- 程序编写者在处理程序和数据库交互时,使用字符串拼接的方式构造 SQL 语句。
- 未对用户可控参数进行足够的过滤,便将参数内容拼接到 SQL 语句中。
sql的类型
- 数字型 参数两边没有单双引号。
- 字符型 参数两边有单双引号。
判断以上两种类型的方式
- 最直白的的一种方式,可以利用算数运算的方式进行判断,比如当传参的方式为?id=1时与 ?id=3-1回显的页面一致,就可以判断当前类型为数字型,回显的页面不一致,则判断为字符型
可能存在的位置
- 根据 SQL 注入漏洞的原理,在用户的“可控参数”中注入 SQL 语法,也就是说 Web 应用在 获取用户数据的地方,只要带入数据库查询,都有可能存在 SQL 注入的可能,这些地方通常 包括:
- GET 数据
- POST 数据
- cookie 数据
sql注入常见的利用手法
1、联合查询
- 联合查询是最常用的 SQL 注入手法,有两个要求:一是字段数相同,二是数据类型相同。 联合查询可以跨库,跨表查询。
2、报错注入
- 在注入点的判断过程中,发现数据库中 SQL 语句的报错信息,会显示在页面中,因此可以进 行报错注入。
- 注意:错误信息来自于 数据库 、 中间件 还是 Web 容器。
3、布尔盲注
- 利用页面的布尔类型状态来进行判断,目标获取数据库名字。
4、延时注入
- 注入恶意SQL语句时故意添加一些延时操作,使数据库在执行SQL语句时暂停一段时间,从而占用服务器资源、影响数据库性能、延长攻击时间和隐藏攻击痕迹。
如何寻找注入点
- 尝试在输入语句的字段中输入特殊字符,比如:单引号,双引号,单括号,单引号+括号,双引号+括号等,并观察输入字符后回显页面是否有特殊变化,如果输入字符后回显的页面发生变化,则判断可能存在注入点
以下将利用闯关的方式来演示常见的利用手法(靶场sqli)
1、联合查询(利用第一关来演示)
(1)当输入?id=1页面是正常输出的
(2)判断注入的类型,由图中可以看到当?id=2时与?id=3-1时所回显的页面是同一页面,说明此处进行了运算,则判断它为数字型
(3)寻找注入点,首先在正常语句后加入特殊字符单引号 ' 发现页面出现了报错
(4)通过打开源代码进行审计,原有的 id 本就有单引号,当我们再次输入单引号后,原本的单引号与我们输入的单引号做了闭合,此时源代码中的单引号成了多余,所以发生了报错,这时我们就可以执行查询语句
(5)由此我们可以引用数据库查询语句order by 与 --+ ,以下图中可以看到表中有三个字段,我们接着往下走
- order by 用于查询数据库表中有几个字段
- --+ 用于注释语句
(6)这里我们可以使用联合查询语句 union进行尝试了,下图中可以看到我们不但识别到可以回显的点,也同样知道了表中有14行数据
- union 用于联合两个或多个查询语句
(7)到这里,思路得清晰,首先尝试查找到数据库名,紧接着查询表,查询字段
(8)利用数据库名,查询这个库中所有的表名
?id=15' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--+
(9)利用查询到的表名,查询users中的字段
id=15' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' and table_schema=database()--+
2、报错注入
在注入点的判断过程中,发现数据库中 SQL 语句的报错信息,会显示在页面中,因此可以进 行报错注入,这里需要引用函数
函数一:
extractvalue()
and extractvalue(1,concat(0x5e,(select database()),0x5e))--+
函数二:
#关于floor()函数
?id=1’and (select 1 from (select count(*) ,concat(database( ),floor(rand(0)*2))x from information_schema.tables group by x)a) --+
在进行报错注入时,floor()函数一般需要与rand()、count()、group by联用。作用:
floor(x):对参数x向下取整;
rand():生成一个0~1之间的随机浮点数;
count(*):统计某个表下总共有多少条记录;
group by x:按照(by)一定的规则(x)进行分组;
报错原理: floor()函数与group by、rand()联用时,如果临时表中没有该主键,则在插入前会再计算一次rand(),然后再由group by将计算出来的主键直接插入到临时表格中,导致主键重复报错,错误信息如: Duplicate entry '.' for key'group_key' 。
3、布尔盲注
-
当不知道数据库返回值的情况下时【无回显】,输入 1’and ‘1’='1 和1’and ‘1’='2显示不一样,仅返回正确、或者错误的页面时,存在布尔型盲注入。
使用盲注之前我们得先了解两个函数
ascii (ASCII码)
substr(截取字符串)
(1)依据输入正常字符回显画面,首先判断数据库名得长度
?id=1' and length(database())=8--+
(2)长度知道了,开始尝试查询数据库名,依据注入ASCII码的方式,当ASCII码的值为115时页面跟正常的显示是一样的,所以对照ASCII表判断出数据库名的第一个字母为 s
4、延时注入
这个手法其实与布尔盲注很相似,都是利用对照ASCII码去获取信息,与布尔盲注得不同之处在于,延时注入返回页面相同,通过返回页面不能判断其正确性,需要通过响应时间判断正确性,所以我们需要尝试使用sleep页面延时刷新,通俗点理解就是我们需要sleep函数让页面延时
#认真走好每一小步 请多指教
@L尘痕