目录
一、注入类型
1.联合查询注入
2.报错注入
3.bool注入(布尔盲注)
4.sleep注入(时间盲注)
二、注入技巧
1.科学计数法绕过正则
2.过滤information
3.无列名注入
MySQL联合查询注入利用union(联合查询)可以同时执行多条SQL语句的特点,在参数中插入恶意的SQL注入语句,同时执行两条SQL语句,获取额外敏感信息或者执行其他数据库操作
有注入点,且数据有回显,那就可以用联合查询注入
-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3--+
information_schema数据库包含所有的数据库名和表名以及列名,利用这一点进行SQL注入
报错注入解决的是数据没有回显,但是会返回报错信息的情况
报错注入报错注入的函数有7个,这里演示三个常用的
2.1.floor
floor报错注入,在MySQL中,floor函数与rand()函数、group by子句一起使用时,利用rand()函数可以导致报错注入。
sqllabs这里的第17关对username进行了过滤,输入1'有报错,无回显,但是update语句使用不了updatexml进行报错注入,那就上floor
1' and (select 1 from (select count(*), concat(database(), floor(rand(0)*2))x from information_schema.tables group by x)a)#
2.2.updatexml
利用该函数中第二个参数XPath_string的报错进行注入,有三个参数
2.3.extractvalue
和updatexml一样,也是利用该函数中第二个参数XPath_string的报错进行注入,不过它只有两个参数
1' and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1)))--+
页面没有报错和回显信息,只会返回正常或者不正常的信息,这时候就可以用bool注入
bool注入原理是先将你查询结果的第一个字符转换为ascii码,再与后面的数字比较,如果为真,整个查询条件就为真,返回正常的结果,反之,返回不正常的结果
1' and ascii(substr((select database()),1,1))>110--+
盲注如果靠手工的话,是很费时间的,所以我们最好使用工具进行,使用Python脚本或者sqlmap
sleep注入解决的是页面没有任何报错信息输出,不管对或错都是一种返回结果,此时我们就无法使用bool注入了
主要原理和布尔盲注一样,比较大小,如果为真就返回1,为假就沉睡5秒,通过网络请求可以看到请求有多少秒
1' and if(ascii(substr((select database()),1,1)) >120,1,sleep(5))--+
时间盲注,sqlmap跑得也比较慢
正常查询语句被匹配上了,但是我们可以利用这里的\b,一个单词的开头为from,那如果单词开头不是from就可以绕过过滤了
但是如果写其他的字母在from前,mysql会报错,而科学计数法就不会报错,正常查询,只是会多一列数据
过滤了information库,我们还可以用下面的库和表来代替(mysql版本大于5.7),但这三个都需要root权限,真实环境中是不太可能给root权限的
sys.x$schema_table_statistics_with_buffer
sys.x$schema_table_statistics
sys.x$ps_schema_table_statistics_io
所以还有不需要root权限的(mysql版本大于5.7),但是这两个表里没有列名,也就是说,用着两个库我们根本查不出来列名
mysql.innodb_table_stats
mysql.innodb_table_index
3.1.使用join,using
首先自连接查询出来的表,没有using条件的结果是两张表的笛卡尔积,那么列名必然会有重复的部分,而主键是不允许重复的,所以查询出来会报错,也就把列名爆出来了
-1' union select * from (select * from users as a join users b)c--+
爆出来一个字段后, 使用using()将该字段作为连接两张表的条件,这样这个字段就不会重复了
然后依次这样操作,就可以爆出列名
-1' union select * from (select * from users as a join users b using(id))c--+
上一种方法是查询出列名后再查数据,而这种方法不需要列名,直接查询数据
联合查询后,我们将列名分别赋为了1,2,3
那么我们可以将这张虚拟表作为我们要查询的表,查询所有第二列的数据
这样我们就无需列名,查询出数据了
当反引号被过滤时,我们也可以用别名的方式来代替
还有很多种过滤,比如过滤空格、单引号、函数,但也有很多绕过的方式
最后附上之前自己看书总结的SQL注入绕过方式,不是很全