利用 PHP 特性绕 WAF 测试

VSole2023-06-14 09:24:49

在测试绕过 WAF 执行远程代码之前,首先构造一个简单的、易受攻击的远程代码执行脚本,内容如图:

第 6 行是一个比较明显的命令执行代码,第 3 行尝试拦截 system、exec 或 passthru 等函数(PHP 中有许多其他函数可以执行系统命令,这三个是最常见的)。

这个脚本部署在 Cloudflare WAF 和 ModSecurity + OWASP CRS3 之后。对于第一个测试,尝试读取 passwd 的内容;

/cfwaf.php?code=system("cat /etc/passwd");

可以看到,被 CloudFlare 拦截了,我们可以尝试使用未初始化变量的方式绕过,比如:

cat /etc$u/passwd

Cloudflare WAF 已被绕过,但是由于脚本检查敏感函数,所以被脚本拦截,那么如何绕过脚本的函数检测呢?我们看看关于字符串的 PHP 文档:

https://secure.php.net/manual/en/language.types.string.php

PHP 字符串转义序列:

  • [0–7]{1,3} 八进制表示法的字符序列,它会自动溢出以适应一个字节(例如“\400”===“\000”)
  • \x[0–9A-Fa-f]{1,2} 十六进制字符序列(例如“\x41”)
  • \u{[0–9A-Fa-f]+} Unicode 代码点序列,将作为该代码点的 UTF-8 表示输出到字符串(在 PHP 7.0.0 中添加)

不是每个人都知道 PHP 表示字符串的语法,而“PHP 变量函数”则成为我们绕过过滤器和规则的瑞士军刀。

PHP变量函数

PHP 支持变量函数的概念。这意味着如果变量名后面附加了圆括号,PHP 将寻找与变量求值结果同名的函数,并尝试执行它。除其他事项外,这可用于实现回调、函数表等。

这意味着语法如 $var(args); 和 "sting"(args; 等于 func(args); 。如果我可以通过使用变量或字符串来调用函数,则意味着我可以使用转义序列而不是函数名。这里有一个例子:

第三种语法是十六进制符号的转义字符序列,PHP 将其转换为字符串“system”,然后使用参数“ls”转换为函数系统。让我们尝试使用易受攻击的脚本:

此技术不适用于所有 PHP 函数,变量函数不适用于 echo、print、unset()、isset()、empty()、include、require 。利用包装函数将这些构造中的任何一个用作变量函数。

改进用户输入检测

如果我从易受攻击脚本的用户输入中排除双引号和单引号等字符,会发生什么情况?即使不使用双引号也可以绕过它吗?让我们试试:

正如您在第三行看到的,现在脚本阻止在 $_GET[code] 查询字符串参数中使用“和”。我以前的有效负载现在应该被阻止:

幸运的是,在 PHP 中,我们并不总是需要引号来表示字符串。PHP 使您能够声明元素的类型,例如 $a = (string)foo; 在这种情况下,$a 包含字符串“foo”。此外,圆括号内没有特定类型声明的任何内容都被视为字符串:

在这种情况下,我们有两种方法可以绕过新过滤器:第一种是使用类似 (system)(ls) 的方法;但是我们不能在代码参数中使用“system”,所以我们可以像 (sy.(st).em)(ls); 一样连接字符串。第二种是使用 $GET 变量。如果我发送像 ?a=system&b=ls&code=$GETa 这样的请求;结果是:$GET[a] 将替换为字符串“system”,$GET[b] 将替换为字符串“ls”,我将能够绕过所有过滤器!

让我们尝试使用第一个有效负载 (sy.(st).em)(whoami);

和第二个有效载荷 ?

?a=system&b=cat+/etc&c=/passwd&code=$\_GET[a]($\_GET[b].$\_GET[c]);

在这种情况下,没有用,但您甚至可以在函数名称和参数内部插入注释(这可能有助于绕过阻止特定 PHP 函数名称的 WAF 规则集)。以下所有语法均有效:

get_defined_functions 函数

此 PHP 函数返回一个多维数组,其中包含所有已定义函数的列表,包括内置(内部)函数和用户定义函数。内部函数可以通过 $arr[“internal”] 访问,用户定义的函数可以使用 $arr[“user”] 访问。例如:

这可能是另一种无需使用其名称即可访问系统功能的方法。如果我对“系统”进行 grep,我可以发现它的索引号并将其用作我的代码执行的字符串:

显然,这应该对我们的 Cloudflare WAF 和脚本过滤器有效:

字符数组

PHP 中的每个字符串都可以用作字符数组(几乎像 Python 那样),您可以使用语法 $string[2] 或 $string[-3] 引用单个字符串字符。这可能是另一种规避阻止 PHP 函数名称的规则的方法。例如,使用这个字符串 $a=”elmsty/ “; 我可以编写语法系统(“ls /tmp”);

如果幸运的话,您可以在脚本文件名中找到所需的所有字符。使用相同的技术,您可以使用类似的方法选择所需的所有字符

OWASP CRS3

有了 OWASP CRS3,一切都变得更难了。首先,使用之前看到的技术,我只能绕过第一个偏执级别,这太神奇了!因为 Paranoia Level 1 只是我们可以在 CRS3 中找到的规则的一小部分,所以这个级别旨在防止任何误报。对于 2 级偏执狂,由于规则 942430“受限 SQL 字符异常检测(args):超出特殊字符数”,所有事情都变得困难。我能做的只是执行一个不带参数的命令,如“ls”、“whoami”等。但我无法像使用 Cloudflare WAF 那样执行类似 system(“cat /etc/passwd”) 的命令:

字符串函数php
本作品采用《CC 协议》,转载必须注明作者和本文链接
在渗透或者CTF中,总会有特殊函数被过滤,如'ls、cat、tac'。防火墙将这些函数加入黑名单,我们需要找一些方法来代替,用fuzz给他们替换,就出现了BYpass思路。学习就是先走一回别人的老路,知识点到量才可以开创自己的新路。
php中的disable_function是EG(ini_directives)来获得的,而phpinfo根据 EG(ini_directives) 中获取信息并打印。
这里根据红日安全PHP-Audit-Labs对一些函数缺陷的分析,从PHP内核层面来分析一些函数的可利用的地方,标题所说的函数缺陷并不一定是函数本身的缺陷,也可能是函数在使用过程中存在某些问题,造成了漏洞,以下是对部分函数的分析
这意味着如果变量名后面附加了圆括号,PHP 将寻找与变量求值结果同名的函数,并尝试执行它。除其他事项外,这可用于实现回调、函数表等。利用包装函数将这些构造中的任何一个用作变量函数。这可能是另一种规避阻止 PHP 函数名称的规则的方法。
最近写了点反序列化的题,才疏学浅,希望对CTF新手有所帮助,有啥错误还请大师傅们批评指正。php反序列化简单理解首先我们需要理解什么是序列化,什么是反序列化?本质上反序列化是没有危害的。但是如果用户对数据可控那就可以利用反序列化构造payload攻击。
转自:计算机与网络安全PHP可以直接访问本地服务器路径以及在服务器上执行脚本文件。合理地限制PHP的访问范围
记录一次本人CVE漏洞挖掘的过程,此漏洞已被分配编号:CVE-2023-36078
写在前面关于无字母数字Webshell这个话题,可以说是老生常谈了。之前打 CTF 的时候也经常会遇到,每次都让人头大,所谓无字符webshell,其基本原型就是对以下代码的绕过:PHP中的异或来看这样一段代码:
mysql提权总结
2021-09-17 15:04:08
使用过MySQL的人都知道,MySQL有很多内置函数提供给使用者,包括字符串函数、数值函数、日期和时间函数等,给开发人员和使用者带来了很多方便。
VSole
网络安全专家