ctfshow-web进阶-命令执行绕过技巧(web71-web74)
1. 命令执行漏洞基础与CTF常见场景
命令执行漏洞(Command Execution)是Web安全中一种高危漏洞,它允许攻击者在服务器上执行任意系统命令。在CTF比赛中,这类题目通常会模拟真实环境中开发者未对用户输入进行严格过滤的场景。
我刚开始接触CTF时,遇到的第一道命令执行题就是个典型例子:题目只过滤了"flag"这个关键词,但允许直接执行system函数。当时我傻乎乎地输入system("cat flag.php"),结果页面返回一片空白——原来题目把输出内容中的字母数字都替换成了问号。这种"看似能执行却看不到结果"的情况,在CTF中非常常见。
PHP中常见的危险函数包括:
system():执行系统命令并输出结果exec():执行命令但不输出结果shell_exec():通过shell执行命令- 反引号
`:与shell_exec等效 passthru():直接输出命令执行结果
2. web71:exit()函数的妙用
这道题的突破点在于输出缓冲区的处理。题目源码中使用了ob_get_contents()获取输出缓冲区内容,然后用preg_replace替换所有字母数字为问号。但如果在命令执行后立即调用exit(),就能提前终止脚本,避免后续的替换操作。
我实际测试时发现几个关键点:
exit()必须紧跟在有效操作后面- 使用
include比直接读文件更可靠 - 目录遍历时
scandir()比ls更稳定
有效payload示例:
// 列出根目录文件 c=var_export(scandir('/'));exit(); // 包含flag文件 c=include("/flag.txt");exit();这种绕过方式的本质是利用了PHP的执行流程控制。当exit()执行时,它会:
- 立即终止当前脚本执行
- 刷新所有输出缓冲区
- 跳过后续所有代码逻辑
3. web72:open_basedir绕过技巧
这道题新增了open_basedir限制,它限定了PHP脚本能访问的目录范围。默认配置通常只允许访问/var/www/html及其子目录。我在实际渗透测试中遇到过多次这种情况,有几种经典绕过方法:
3.1 glob://伪协议绕过
glob://是PHP的一个伪协议,它可以绕过部分目录限制。通过DirectoryIterator类可以遍历目录:
c=$a=new DirectoryIterator("glob:///*"); foreach($a as $f) { echo($f->__toString().' '); } exit();这个payload的工作原理是:
- 创建
DirectoryIterator实例扫描根目录 - 遍历输出所有文件和目录名
- 用
exit()避免输出被污染
3.2 UAF漏洞利用
当常规方法失效时,题目可能需要使用UAF(Use After Free)漏洞。下面这个经典payload利用了PHP的对象销毁机制:
c=?><?php function pwn($cmd) { // 省略具体实现... // 包含内存操作和函数地址泄露 } pwn("cat /flag0.txt"); ?>这种方法的原理比较复杂,简单来说:
- 通过PHP对象销毁触发UAF
- 泄露内存中的函数地址
- 构造虚假的闭包对象
- 最终执行系统命令
4. web73:进阶目录遍历技巧
这道题延续了之前的限制,但flag位置变成了/flagc.txt。除了使用web72的方法,还可以尝试:
4.1 直接数组索引访问
c=echo(scandir("/")[6]);exit();这种方法的优点是:
- 不需要复杂遍历
- 直接定位目标文件
- 适用于已知flag位置的情况
4.2 include直接包含
c=include('/flagc.txt');exit(0);注意点:
- 文件路径必须是绝对路径
- 文件内容必须是合法PHP代码
- 如果flag是纯文本,需要确保PHP不会将其当作代码解析
5. web74:终极绕过实战
这道题禁用了scandir()函数,但我们可以组合之前的技巧:
5.1 opendir+glob组合
c=$a=opendir("glob:///*"); while(($file=readdir($a))!==false){ echo $file."<br>"; }; exit();5.2 文件包含终极方案
c=include("/flagx.txt");exit();在实际CTF比赛中,我总结出几个通用原则:
- 先尝试最简单的
include/require - 目录受限时用
glob://伪协议 - 输出受限时用
exit()提前终止 - 函数被禁时找替代方案(如
DirectoryIterator代替scandir)
6. 防御方案与实战建议
从防御角度看,开发者应该:
- 使用
escapeshellarg()处理所有命令参数 - 设置严格的
open_basedir限制 - 禁用危险函数(在php.ini中设置
disable_functions) - 对输出内容进行适当编码
对于CTF选手,我建议:
- 熟记常见PHP危险函数
- 掌握伪协议的各种用法
- 了解PHP的异常处理机制
- 积累各种绕过技巧的实际payload
在真实渗透测试中,命令执行漏洞的危害极大。我曾在一个实际案例中发现,通过精心构造的命令可以绕过多层防御,最终获取服务器权限。这也提醒我们,在开发中必须对用户输入保持高度警惕。
