mcpField
A
auditing-php-applications

auditing-php-applications

github.com/trilwu安全17756 次安装12 周前更新
代码仓库

关于 auditing-php-applications

面向 PHP 代码审计者的安全审查技能,将通用漏洞审计方法应用于 PHP 特有的危险点。重点覆盖版本相关行为、框架生态风险及从输入到危险操作的验证。

主要功能

  1. 01追踪输入到危险操作的路径
  2. 02检查 PHP 反序列化与对象注入
  3. 03审查文件包含、包装器及文件上传
  4. 04识别 SQL 注入与类型比较绕过
  5. 05结合 PHP 版本验证漏洞影响

适用场景

  1. 01审计 PHP 应用或插件源代码
  2. 02检查 WordPress、Magento、Joomla 或 Laravel 项目
  3. 03调查疑似 RCE、LFI、SQLi 或对象注入
  4. 04判断用户输入参与的 unserialize 或 == 是否可利用

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/trilwu/secskills --skill auditing-php-applications

安装后在 Claude Code 中输入/auditing-php-applications确认已加载。

详细介绍

审计 PHP 应用

这是构建在 auditing-code-for-vulnerabilities 之上的 PHP 专用层。 将该技能中的方法论——上下文 → 攻击面 → 漏洞类型排查 → 变体分析 → 四问验证关卡——应用于下面的 PHP 危险函数目录。之所以需要此技能,是因为 PHP 有一些任何与语言无关的方法论都无法涵盖的陷阱:某些特性会将文件读取变成远程代码执行,而某些比较规则会让 == 变成身份验证绕过。

本工具集有意不为其他语言提供专门的审计技能,只有这一项例外。 PHP 之所以例外,是因为它在遗留 Web 和 WordPress/Magento 领域占据主导地位,而严重漏洞往往就藏在这些地方;此外,PHP 的动态特性会以审查者必须专门留意的方式出问题。

适用场景

  • 审查 PHP 代码库或插件,查找可利用的漏洞
  • 审计 WordPress、Magento、Joomla 或 Laravel 应用的源代码
  • 追踪 PHP 中疑似的 RCE、LFI、SQLi 或对象注入路径
  • 判断用户输入中的 unserialize、include 或 == 是否可被利用

不适用场景

  • 通用审计方法,或非 PHP 语言——使用 auditing-code-for-vulnerabilities;此技能以其为前提
  • 查找已植入的 Webshell 或后门,而不是漏洞——使用 hunting-web-backdoors
  • 在找到危险函数后构建反序列化利用链——使用 exploiting-deserialization
  • 对运行中的应用进行黑盒测试——使用 testing-web-applications
  • 只审查某项变更的差异——使用 reviewing-code-changes

按漏洞类型分类的危险函数

追踪用户输入(超全局变量、请求头、上传的文件名、曾经由用户输入产生的数据库值)是否到达以下任一危险函数。只有当输入源能够到达危险函数时,才构成漏洞。

远程代码执行
  • 直接 eval 危险函数: eval、assert(字符串参数,PHP 8.0 之前)、 preg_replace(使用 /e,PHP 7.0 之前)、create_function(PHP 8.0 之前)、 mb_ereg_replace/mb_eregi_replace(使用 e 选项)。
  • 命令执行: system、exec、passthru、shell_exec、反引号、 proc_open、popen、pcntl_exec。注意不要混淆 escapeshellarg 和 escapeshellcmd——escapeshellcmd 无法防止参数注入。
  • 动态调用: $func()(其中 $func 来自输入)、 call_user_func/call_user_func_array、array_map/usort/ preg_replace_callback(使用受用户输入影响的回调)。
对象注入(PHP 特有的漏洞)
  • 对任何用户可控数据调用 unserialize() 都会导致对象注入。利用方式是构造 POP 链:现有类中的 __wakeup、__destruct、 __toString 或 __call 魔术方法在对象实例化时执行危险操作。存在漏洞的文件本身可能完全不包含危险代码——利用链组件可能位于框架或依赖项中。
  • **phar:// 是伪装的 unserialize,但受版本限制。**在 PHP 8.0 之前,对 phar:// 路径执行任何文件操作(file_exists、fopen、include、 getimagesize 等)都会自动反序列化 Phar 的元数据。因此,如果路径遍历或 LFI 让文件函数访问已上传的 .phar 文件(或任何包含 Phar 元数据的文件),即使完全看不到 unserialize 调用,也会导致对象注入。PHP 8.0 移除了这种自动反序列化——现在只有显式调用 Phar::getMetadata() 才会反序列化。因此,在大量仍在使用的 PHP 7.x 环境中,此漏洞属于严重问题;而在 PHP 8.x 中,除非代码自行调用 getMetadata(),否则无需担忧。排除或确认此漏洞前,先检查运行时版本。
  • 修复时优先使用 json_decode;对所有非可信数据上的 unserialize 都应标记,即使看不到明显的利用链组件——下一次更新依赖项时可能就会引入它们。
LFI / RFI 和流包装器
  • 将用户输入传入 include、require、include_once、require_once。
  • 会彻底改变情况的包装器: php://filter/...(读取源代码;以及通过 convert.iconv/压缩过滤器实现的已知 RCE 利用链)、php://input(类似 RFI 的请求正文包含)、data://(内联载荷)、phar://(对象注入)、expect://、zip://。启用 allow_url_include 会将 LFI 变成远程 RFI。
  • 文件读取危险点(file_get_contents、readfile、fopen、highlight_file)结合目录遍历会泄露源代码和机密信息。
SQL 注入
  • 将字符串拼接的输入传给旧版 mysql_query/mysqli_query。
  • $wpdb->query("... $var ...") 未使用 $wpdb->prepare() — 即使存在 ->prepare,但在占位符之外进行插值,仍然可以被注入。
  • 使用 PDO/mysqli 时,若通过构造字符串而非绑定参数,则存在风险。对表名/列名使用占位符(这些名称无法绑定)是常见的真实漏洞。
类型转换和魔术哈希身份验证绕过
  • == 和 != 是宽松比较。 strcmp/hash_equals/=== 是安全的形式。经典绕过方式:if (md5($input) == $stored),两个输入的哈希值都为 0e[0-9]+“魔术哈希”时会比较相等,因为两个数字字符串会按数字比较(0e123 == 0e456 → 0.0 == 0.0)。
  • 版本很重要,也可能造成陷阱。 PHP 8.0 更改了数字与字符串的比较规则:0 == "foo" 在 PHP 7 中为 true,在 PHP 8 中为 false,因此在 PHP 7 上有效的 in_array(0, $userStrings) 或 0 == $token 绕过,在 PHP 8 上会失效。但 0e 魔术哈希绕过在 PHP 8 中仍然有效,因为两边都是数字字符串,仍会按数字比较。排除或确认类型转换漏洞前,请先检查目标 PHP 版本。
  • 在 PHP 7 中,将数组传给 strcmp($_GET['x'], $secret) 会返回 NULL(宽松比较时等于 0)——可绕过身份验证;在 PHP 8 中则会抛出 TypeError。相同代码,不同版本,结论不同。
超全局变量信任和可变变量
  • extract($_GET/$_POST/$_REQUEST) 允许请求设置任意局部变量 — 覆盖身份验证标志、配置,以及任何尚未初始化的内容。
  • $$var / ${$key} 可变变量、未传入结果数组的 parse_str(会写入当前作用域)、import_request_variables(已在 5.4 中移除)—— 都是带有 register_globals 风格的变量注入方式。
SSRF 和文件上传
  • 对用户提供的 URL 使用 file_get_contents/curl/fopen 会造成 SSRF — 请通过 exploiting-ssrf 指引利用分析。
  • 文件上传:检查目标位置是否在 Web 根目录之外、扩展名是否不是由攻击者指定(双扩展名、.phtml、.php5、旧版 PHP 中的空字节),以及服务器是否会执行该类型的文件。在 Web 可访问目录中,若 MIME 已验证但扩展名由攻击者控制,则会导致 RCE。

生态系统背景

  • WordPress: nonce 用于防护 CSRF,并非授权机制 — nonce 有效不代表用户有权执行操作;请查找缺失的 current_user_can() 检查。插值时必须使用 $wpdb->prepare。常见漏洞包括 unfiltered_html、edit_* 权限,以及未经过身份验证的 AJAX/REST(wp_ajax_nopriv_*、permission_callback => '__return_true')。
  • Magento: unserialize 相关历史漏洞较多;布局 XML 注入、管理后台路径和补丁级别都会影响已知 CVE 是否可利用。
  • Laravel: 批量赋值($fillable/$guarded)、Blade {!! !!}(不转义)与 {{ }}(转义),以及泄露的 APP_KEY 可能导致 Cookie/decrypt 对象注入。

报告前验证

应用 auditing-code-for-vulnerabilities 的检查:追踪源到危险点,确认路径可达(身份验证、路由,以及 — 尤其是 — 类型转换和已移除函数相关漏洞所涉及的 PHP 版本),并证明影响,而不是只作断言。无法触达可利用 gadget 的 unserialize,或 PHP 8 上的 /e 正则,属于加固建议,而非严重发现 — 请明确指出是哪一种。

应拒绝的错误说法

  • “没有 unserialize,就不会有对象注入。” phar:// 会通过常规文件函数触发反序列化。检查所有路径可能受用户影响的文件操作。
  • “它用了 ==,用于哈希检查没问题。” 对哈希使用 == 会导致魔术哈希绕过。只有 hash_equals/=== 才安全,而且 PHP 8 中仍可绕过。
  • “比较漏洞有效,我确认过了。” 是哪个 PHP 版本?0 == "x" 和 strcmp(array) 在 PHP 8.0 中改变了判定结果。请说明版本。
  • “调用了 prepare(),所以查询是安全的。” 只有占位符中的值是安全的。插值的表名/列名,以及拼接在占位符周围的文本,仍然可以被注入。
  • “nonce 检查通过了,所以已获授权。” WordPress nonce 是 CSRF 令牌。授权检查是另外的 current_user_can(),你必须找到它。
  • “上传会验证 MIME 类型。” MIME 类型可以伪造;如果攻击者能控制扩展名,且该目录会执行 PHP,那么 MIME 类型就无关紧要。
  • “这是框架类,漏洞利用链 gadget 不在这里。” POP 链 gadget 本来就存在于依赖项中。易受攻击的文件中没有危险代码很正常,不能据此免责。

阅读外部来源

以 Markdown 格式获取公开公告、规范和供应商报告:

curl -sL "https://defuddle.md/<url>"      # scheme in the path is optional

这会剔除网页的多余内容——对于以文字为主的页面,令牌数大约减少 78%——并返回全文而非摘要,因此你可以搜索内容,并相信未找到相关内容的结果。

它不适用于三种情况。获取 JSON 和 API 响应时应直接获取原始内容,因为可读性提取会破坏结构化数据。获取需要身份验证或由 JavaScript 渲染的页面时也应直接获取,因为它会以匿名方式检索页面。切勿通过此方式访问对手的基础设施(钓鱼链接、C2、恶意软件托管)、客户拥有的主机或测试任务 URL——请求会离开你的机器,发送给第三方;如果访问的是正在运行的对手基础设施,还会暴露你的行动,让对方察觉。

有些网站会屏蔽提取器,并返回错误信息而非页面内容——例如 freedesktop.org 返回的 {"error":"Failed to fetch: 418 I'm a teapot"}。这表示获取请求被拒绝,并不表示来源称该内容不存在。在据此得出任何结论前,请直接重新获取该 URL。

参考资料

  • auditing-code-for-vulnerabilities — 通用方法论,以及本技能所依托的审查关卡
  • hunting-web-backdoors — 搜寻人为植入的恶意代码,而非漏洞
  • exploiting-deserialization — 找到 unserialize/phar:// 漏洞点后,构建 POP 链
  • exploiting-ssrf — 利用用户可控 URL 获取功能
  • testing-web-applications — 对正在运行的应用进行黑盒测试

评论

支持 Markdown