这一篇主要就是总结了一下我在学习sql注入和做相关题目的时候遇到的一些题型、知识点、攻击方法和特别的绕过方法,内容不是很全,但肯定有用😉
小知识记录:
空格:
()或/**/替代=:like替代%00也可以注释(截断)后面的'replace可以替代insert插入
查询所有库
select schema_name from information_schema.schemata
replace into score values("火华",666,666,666); #插入数据
delete from score where listen=11; #删除数据
二次注入
[网鼎杯 2018]Comment
[网鼎杯2018]Unfinish
注册好之后会自动跳转到登录页面,我们登上去发现我们的用户名出现在了界面上,那么这就很可能是用户明通过登录之后从数据库查询传到index.php页面了,那这就很符合二次注入的点了,我们就只能在注册的时候考虑用户名注入了,那我们就尝试构建一下payload
//注册用户
insert into tables values('$email','$username','$password')
regexp与like匹配
like匹配
在表t列c中,匹配以f开头;以f结尾;包含f;包含f/l/a的记录。
select * from t where c like 'f%' |
regexp正则匹配
在表t列c中,匹配以f开头;以f结尾;包含f的记录。
select * from t where c regexp '^f' |
匹配包含f或l或a的记录
select * from t where c regexp 'f|l|a' |
匹配包含ae/be/ce/de的记录;匹配包含ea/eb/ec/ed的记录
select * from t where c regexp '[abcd]e' |
使用-进行范围匹配搜索
select * from t where c regexp '[a-d]e' |
regexp盲注脚本
import requests |
堆叠注入
[强网杯 2019]随便注、[GYCTF2020]Blacklist
show查询
show databases; |
重命名获取字段内容
这个方法比较绕,大致思路如下:通常输入1能获取一个普通的字段内容,这里输入1可以获取words 表id 字段中的数据,我们要的flag 在flag_table 表flag 字段中。然后将原来的表和列改为其他名字,将flag 的表和列改为word 和id,如此直接输入1便能查询到flag。
# 1';payload# |
handler查表
handler用来读表中的数据,会根据语句后面的参数决定。需要注意的是,在用handler读取表中数据的时候,需要先open一个表,然后才能read,最后还需要close。
HANDLER demo OPEN; |
过滤information
获取表名
mysql.innodb.table.stats和database_name=""
SELECT group_concat(table_name) FROM mysql.innodb_table_stats WHERE database_name=database() |
sys.schema_table_statistics_with_buffer
SELECT group_concat(table_name) FROM sys.schema_table_statistics_with_buffer WHERE table_schema= |
无列名注入
法一
注:这个方法必须当union没有被过滤时才能利用。
table0中有3个字段(列),输入以下命令
select 1,2,3 union select * from table0 |
会得到如下内容
1 |
2 |
3 |
|---|---|---|
linyue |
2333 |
happy |
jiantang |
5799 |
fine |
这样就获得了一张新表table1,其字段名是1 2 3,内容还是table0中原来的内容
# 获取第一列的内容 |
如果过滤了反引号,使用如下方法绕过
#获取第一列的内容 |
ascii比较
查询字段数
((select 1,2,3)>(select * from f1ag_1s_h3r3_hhhhh)) |
1,2,3或1,2这样不断尝试,根据回显确定字段数。
直接给脚本吧😅
import string |
addslashes()和str_replace()过滤
例题:[CISCN2019 总决赛 Day2 Web1]EasywebGET传入id和path两个参数。
过滤分析
|
addslashes($id)函数,会在**$id**中的特殊字符前,添加反斜杠,这些特殊字符为:'、"、\、NULL字符(\0)。str_replace(array("\\0","%00","\\'","'"),"",$id);会将**$id中的\0、%00、\'、'都替换为空字符串。\\0是NULL字符(\0),\\'是转义的单引号\',%00是URL编码的NULL**字符。
转义字符是什么意思?
# echo 'I'm happy.'; (1) |
(1)I'm中的'被解释为字符串的结束符;(2)I\'m中的\'被解释为一个单引号字符,有了\的转义,才不会被解释为结束符。
绕过分析
如果输入$id=\0,addslashes()使其为\\0,str_replace()过滤其中的\0,最后剩下一个\。放入原语句id='{$id}' or path='{$path}'中,成为id='\' or path='{$path}',如此以来,第二个原本为结束符的单引号被转义为单引号字符,而第三个原本为起始符的单引号便成了结束符。
如果输入http://65e65fa9-e2cc-4aba-8ce5-41cee1623c5e.node5.buuoj.cn:81/image.php?id=1\0&path=or 1=1#,则构成的sql语句如下:
select * from images where id='1\' or path='or 1=1#' |
原意是由or连接的id和path两个条件,通过恶意注入成了由or连接的id和1=1这两个条件。
现在,参数id传入1\0;参数path传入or xxxx#,构成的sql语句中,1\' or path=无用,or xxxx#中的xxxx#才是真正要利用的代码。
注:如果没有过滤,通常我们只需输入1',由输入的'提前闭合,便可以完成注入。而这次我们是利用过滤将原来的结束符转义,再结合第二个条件的开始符来完成注入。