freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

WAF攻与防—自定义WAF规则与WAF绕过
2022-06-07 21:00:36
所属地 山东省

初窥WAF攻防之道

WAF的核心原理是正则表达式,针对攻击行为的拦截也是要先定义各种攻击payload,然后针对该payload添加拦截规则。

前言

攻击者(黑客)通过各种技术手段绕过WAF防护从而对目标进行攻击,防守方,通过查看WAF日志等方式,了解最新的攻击方式,从而针对性的编写新的WAF规则实施防护。攻防双方就在这互相“攻伐”过程中,不断丰富我们WAF攻防的内容,今天,我们来同时扮演双方的角色,以全局的视角深入理解一下WAF攻防。

先有矛还是先有盾?

先有矛还是先有盾?这个自古以来充满争议的问题,在WAF攻防这里,却没有任何异议。先用WAF 才能有WAF绕过,因此我们的学习,也先从防守方:编写自定义的WAF规则开始。

防守|针对不同的漏洞编写不同的WAF规则

基础知识:WAF主要检测的12个变量

想要学习WAF自定义规则编写,除了掌握正则表达式的编写,还要知道 绕过WAF的数据主要从哪来?这就要求我们了解WAF主要检测的十二个变量。

URL--------------------http://10.67.8.118:8889/abc/shell.php
URL-path--------------------/abc/shell.php
Host--------------------10.67.8.118:8889
Parameter-name--------------------id(id=123)
Parameter--------------------123
Header-name--------------------Accept-Encoding(举例)
Header--------------------gzip,deflate
Cookie-name--------------------id(id=1)
Cookie--------------------1
Version--------------------1.1(HTTP/1.1)
Method--------------------POST
Request-Body--------------------id=123

URL

在WWW上,每一信息资源都有统一的且在网上唯一的地址,该地址就叫URL(Uniform Resource Locator,统一资源定位器),它是WWW的统一资源定位标志,就是指网络地址。url主要包括协议、认证、地址、端口、路径、参数、标识符等,如下是一张url的标志图。


image-20220527235220362

URL-Path

描述的是项目或者模块中资源绝对路径(不是相对路径)

Host

主机地址

Parameter-name

参数名

Parameter

参数

Header-name

头文件名

header

http请求头。标注请求文件类型

cookie-name

cookie名(类似于键)

cookie

cookie值(类似于键名)

version

浏览器版本

Method

请求类型

Request-Body

请求体

WAF自定义基础|通过nginx配置文件抵御攻击

验证浏览器行为

简单做一个比喻。当前疫情紧张时期,假如某个地区因疫情物资紧张,居民采购蔬菜被限量。而有些贪心的人,派了一堆歪果仁(没有国籍不享受政策)来冒领蔬菜。怎么防止这种事情呢?工作人员在发蔬菜之前,会给领取者一张纸,上面写着“天王盖地虎”,如果那人能念出纸上的字,那么就是享受政策的人,给红包,如果你不能念出来,那么请自觉离开。

是的,在这个比喻中,居民就是浏览器,歪果仁就是攻击器,我们可以通过鉴别cookie功能(念纸上的字)的方式来鉴别他们。

下面是通过nginx配置cookie鉴别功能的代码

if 
($cookie_say !=
"twgdh"
){  
add_header Set-Cookie
"say=hbnl"
;
rewrite .*
"$scheme://$host$uri"
redirect;
}

让我们看下这几行的意思,当cookie中say为空时,给一个设置cookie say为twgdh的302重定向包,如果访问者能够在第二个包中携带上cookie值,那么就能正常访问网站了,如果不能的话,那他就只能永远活在302中。

那假如贪心的人 发现了规律,他们发给每个歪果仁一个录音笔,重复播放”天王盖地虎,天王盖地虎“此时我们怎么办呢?

这时,工作人员的对策是这样做的,要求领取者出示有自己名字的户口本,并且念出自己的名字,“我是xxx,天王盖地虎”。于是一群只会嗡嗡叫着“天王盖地虎”的歪果仁又被撵回去了。

if ($cookie_say != "twhdjl$remote_addr"){   
add_header Set-Cookie
"say=twgdh$remote_addr";
rewrite .*
"$scheme://$host$uri"
redirect;
}

这样的写法和前面的区别是,不同IP的请求cookie值是不一样的,比如IP是1.2.3.4,那么需要设置的cookie是say=twgdh1.2.3.4。于是攻击者便无法通过设置一样的cookie(比如CC攻击器)来绕过这种限制。

然而这似乎也不是一个万全之计,因为攻击者如果研究了网站的机制之后,总有办法测出并预先伪造cookie值的设置方法。因为我们做差异化的数据源正是他们本身的一些信息(IP、user agent等)。攻击者花点时间也是可以做出专门针对网站的攻击脚本的。那么我们就没有对策了吗?

那么要如何根据他们自身的信息得出他们又得出他们算不出的数值?答案是用salt加散列。例如md5("opencdn$remote_addr"),虽然攻击者知道可以自己IP,但是他无法得知如何用他的IP来计算出这个散列(md5不可逆)。

rewrite_by_lua '
local
say = ngx.md5(
"opencdn"
.. ngx.var.remote_addr)
if
(ngx.var.cookie_say ~= say)
then  
ngx.header[
"Set-Cookie"
] =
"say="
.. say
return
ngx.redirect(ngx.var.scheme ..
"://"
.. ngx.var.host .. ngx.var.uri)
end

通过这样的配置,攻击者便无法事先计算这个cookie中的say值,于是攻击流量(代理型CC和低级发包型CC)便在302地狱无法自拔了。

防扫描

前人总结的知识结晶已经很完善了,可以直接用这个模块来做防护。

https://github.com/loveshell/ngx_lua_waf

自定义WAF规则预防常见攻击

防止sql注入

利用WAF防止sql注入可以通过过滤sql注入所需要的关键字,例如union select等来进行

#==Block SQL Injections

set $block_sql_injections 0;

if ($query_string ~ "(=.*--)|(w+(%|$|#|&)w+)|(.*||.*)|(s+(and|or)s+)|(b(select|update|union|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)b)"){

set $block_sql_injections 1;

}

if ( $block_sql_injections = 1){

return 403;

}

防止xss攻击

通过过滤插入xss标签的常用标点符号 进行防护

set $block_xss 0;
if ($query_string ~ "(~|{|}|"|'|<|>|?)"){
set $block_xss 1;
}
if ( $block_xss = 1){

return 403;
}

防止ssrf

最简单的方法:使用正则表达式过滤属于内网的IP地址

防止rce

借鉴了 常做的ctf题目的思路,还使用了通配符防止简单绕过

set $block_rce 0;
if ($query_string ~ "/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i"){
set $block_rce 1;
}
if ( $block_rce = 1){

return 403;
}

攻击|各种姿势绕过WAF

绕过WAF主要利用的是三方面的特性 ,服务器特性,应用层特性,WAF层特性

利用服务器特性绕waf

image-20220528020433330

%特性(ASP+IIS)

在asp+iis的环境中存在一个特性,就是特殊符号%,在该环境下当们我输入s%elect的时候,在WAF层可能解析出来 的结果就是s%elect,但是在iis+asp的环境的时候,解析出来的结果为select

Ps.此处猜测可能是iis下asp.dll解析时候的问题,aspx+iis的环境就没有这个特性。

%u特性(asp+iis和aspx+iis)

Iis服务器支持对于unicode的解析,例如我们对于select中的字符进行unicode编码,可以得到如下的 s%u006c%u0006ect ,这种字符在IIS接收到之后会被转换为select,但是对于WAF层,可能接收到的内容还是 s%u006c%u0006ect,这样就会形成bypass的可能。

另类%u特性(ASP+IIS)

该漏洞主要利用的是unicode在iis解析之后会被转换成multibyte,但是转换的过程中可能出现: 多个widechar会有 可能转换为同一个字符。 打个比方就是譬如select中的e对应的unicode为%u0065,但是%u00f0同样会被转换成为 e。

s%u0065lect->select s%u00f0lect->select 

WAF层可能能识别s%u0065lect的形式,但是很有可能识别不了s%u00f0lect的形式。这样就可以利用起来做WAF的绕过。

apache畸形method

在GET请求中,GET可以替换为任意参数名字,不影响apahce接收参数id=1

TEST /sql.php?id=1 HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1

利用应用层特性绕WAF

image-20220528015106594

大小写转换

使用简单,但是效果不好

例如:

and 1=2    可以使其变为 AnD 1=2

image-20220528012912726

使用注释

使用简单,效果一般

union select 1,2,3,4, from admin

注释完的效果

/**/union/**/select/**/1,2,3,4 from admin

/**/un/**/io/**/n/**/sel/**/ec/**/t/**/1,2,3,4 from admin

第二种注释

/*!and*/ 1=2 

效果显著 此处感叹号为"非"的意思,意思是感叹号后面的不注释

url编码
/ =%2f  *==%2a  %=%25

/**/==%252f%252a*/
p.s正常编码为%27


p.s:url编码现在基本过不掉了

使用空字节

一些过滤器在处理输入时,如果碰到空字节就会停止处理

我们通常也会利用空字节进行绕过过滤器

如:

id=1 %00 and 1=2
利用嵌套剥离

有些过滤器会从用户的输入中进行剥离一些敏感的函数

那我们可以通过函数的嵌套进行绕过一次剥离

selselectect  剥离后为  select 
宽字节
union = uю%69яю这里把i不用宽字节 直接url编码 其他的字符都用对应的宽字节
select = こхlх%уt //t不编码 其他的都宽字节 中间插上%
from = цR%яэ //宽字节+%
空格=%20=%ва //в是2的款字符 а是0的宽字符
, = Ь //,号的宽字节
参数污染

通常在一个请求中,同样名称的参数只会出现一次。但是在HTTP协议中是允许同样名称的参数出现多次的。针对同样名称的参数出现多次的情况,不同的服务器的处理方式会不一样:

例如针对sql注入的测试:

$sql = "select * from admin where id=1";
$sql=$sql."".$_POST['bbs'];

echo $sql;

$pattern='/^.*union.*$/';

if(preg_match($pattern, $sql))
{echo "注入测试   ";}

在特定情况下 可以绕过一些WAF

bbs=u&bbs=n&bbs=i&bbs=o&bbs=n&bbs=select 1,user(),3

应用层组合拳绕过waf

替换法+URL编码

例:先判断注入点,把and为&&,urlencode后为%26%26

http://192.168.60.68/sql.php?id=1%20%26%26%20-1=-2

同样的 替换法可以和其他方法组合使用

例如:注释+替换法

内联注释+替换法

1.利用()代替空格

2.利用mysql特性/*!*/执行语句

3.利用/**/混淆代码

我给出的注入语句是:

union/%00//!50010select/(database//()),(user//())%23 (50010代表数据库版本)

这里要注意的几点是:

1.mysql关键字中是不能插入//的,即se//lect是会报错的,但是函数名和括号之间是可以加上//的,像database//()这样的代码是可以执行的

2./!/中间的代码是可以执行的,其中50010为mysql版本号,只要mysql大于这个版本就会执行里面的代码

3.数据或者函数周围可以无限嵌套()

4.利用好%00 user())

image-20220528013144013

利用WAF层特性绕WAF

image-20220528020007063

逻辑问题

(1)云WAF防护,一般我们会尝试通过查找站点的真实IP,从而绕过CDN防护。
(2)当提交GET、POST同时请求时,进入POST逻辑,而忽略了GET请求的有害参数输入,可轻易Bypass。
(3)HTTP和HTTPS同时开放服务,没有做HTTP到HTTPS的强制跳转,导致HTTPS有WAF防护,HTTP没有防护,直接访问
HTTP站点绕过防护。
(4)特殊符号%00,部分WAF遇到%00截断,只能获取到前面的参数,无法获取到后面的有害参数输入,从而导致Bypass。
比如:id=1%00and 1=2 union select 1,2,column_name from information_schema.columns

性能问题

第一种情况:在设计WAF系统时,考虑自身性能问题,当数据量达到一定层级,不检测这部分数据。只要不断的填充数 据,当数据达到一定数目之后,恶意代码就不会被检测了。

?a0=0&a1=1&.....&a100=100&id=1 union select 1,schema_name,3 from
INFORMATION_SCHEMA.schemata
备注:获取请求参数,只获取前100个参数,第101个参数并没有获取到,导致SQL注入绕过。

第二种情况:不少WAF是C语言写的,而C语言自身没有缓冲区保护机制,因此如果WAF在处理测试向量时超出了其缓冲区 长度就会引发bug,从而实现绕过。

?id=1 and (select 1)=(Select 0xA*1000)+UnIoN+SeLeCT+1,2,version(),4,5,database(),user(),8,9
PS:0xA*1000指0xA后面”A"重复1000次,一般来说对应用软件构成缓冲区溢出都需要较大的测试长度,这里1000只做参
考也许在有些情况下可能不需要这么长也能溢出

第三种情况:多次重复提交同一个请求,有些通过了WAF,有些被WAF所拦截了,应该性能问题导致部分请求bypass

这种情况 多次访问就完事了

白名单

白名单分好多种,原理大同小异。这里展示两种

IP白名单

从网络层获取的ip,这种一般伪造不来,如果是应用层的获取的IP,这样就可能存在伪造白名单IP造成bypass。 测试方法:修改http的header来bypass waf

以下是常用的header头:

X-forwarded-for
X-remote-IP
X-originating-IP
x-remote-addr
X-Real-ip

url白名单

为了防止误拦,部分WAF内置默认的白名单列表,如admin/manager/system等管理后台。只要url中存在白名单的字 符串,就作为白名单不进行检测。常见的url构造姿势:

http://10.9.9.201/sql.php/1.js?id=1
http://10.9.9.201/sql.php/admin.php?id=1
http://10.9.9.201/sql.php?a=/manage/&b=../etc/passwd
http://10.9.9.201/../../../manage/../sql.asp?id=2

分块传输绕过WAF

为啥把它单拎出来讲?确实太强大了qaq

前置知识:关于分块编码传输

在通过http传输文件的时候,通常会有一个Content-Length用来指定文件的长度,比如传输图片,静态页面,客户端也以Content-Length作为接收内容结束的标志,接收完毕后就可以断开连接了。但是有时候发送方并不能确定内容的长度,造成的影响就是:接收方无法通过Content-Length得到报文体的长度,也就无法得知什么时候应该中断连接。

为此我们需要一个新的机制:不依赖头部的长度信息,也能知道实体的边界。

HTTP 1.1引入了分块传输编码的方式。只要在header头部加入Transfer-Encoding: chunked,就代表这个报文采用了分块编码。此时不用指定Content-Length接收方也可以知道什么时候传输结束了,只需要约定一个信号即可,比如,接收方只要接收到一个长度为0内容为0的分块,则代表传输完毕。

分块传输实例理解

向本地post一个数据包,为id=123455

image-20220528013905782

可以实验一下,如果关闭burp在repeater选项里面自带的content-length补全功能,然后去掉Content-Length,就无法接收到id。

image-20220528013937621

接下来我们将其改为分块传输的方式:

image-20220528013954326

通过上图可以看到,即使没有Content-Length,我们也可以采用分块传输的方式,分多少块,每块多大都不是唯一的,但是最后的结尾需要一个长度为0内容为空的块(内容为两个空行)。

利用分块传输绕过WAF

当我们将传输的内容分块时,处理后的HTTP请求由于和已知的payload相差较大,所以可以起到一定的绕过WAF的效果。

比如我们来试试安全狗:

image-20220528014100273

但是有一些如Imperva的,360等比较好的WAF已经对传输编码的分块传输做了处理,可以把分块组合成完整的HTTP数据包,这时直接使用常规的分块传输方法尝试绕过的话,会被WAF直接识别并阻断。

这个时候我们可以在每个分块长度标识处加上分号“;”作为注释,如下所示:

image-20220528014132273

在分块数据包中加入注释的话,WAF就识别不出这个数据包了。

分块传输在绕WAF方面功能强大,具体可以看这篇文章

https://www.freebuf.com/articles/web/194351.html

后记

浅学了一波WAF攻与防,初入门径,便感心力交瘁....

知识真是浩渺如烟海,越学越感到自己的菜是不可弥补的。世界永远在拷打着我的无知。

继续努力吧,路漫漫而修远兮。越学习,学习的目的越转变,原来学习是为了有一天证明给世界看我很强。现在明白了对于世界来说,自己无知这件事是不可弥补的。现在学习的目的便是获取自我成长的愉悦了,不过不管怎么说,能在自己感兴趣的领域学到知识本身就是一件很快乐的事情呢,享受这份简单的快乐就好。

现在是凌晨两点,世界,不晚安。

参考文章

https://blog.csdn.net/baidu_19620507/article/details/105366404

https://www.freebuf.com/articles/network/128370.html

https://blog.csdn.net/heiyeshuwu/article/details/51325830?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6-51325830-blog-105366404.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6-51325830-blog-105366404.pc_relevant_default&utm_relevant_index=10

https://blog.csdn.net/zdy8023/article/details/89280716

https://saucer-man.com/information_security/100.html

https://www.freebuf.com/articles/web/194351.html

# 黑客 # web安全 # 系统安全 # 网络安全技术
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录