基础篇讲过 php://filter 与日志包含;这篇讲三板斧失效时(Docker 日志重定向、无上传点)怎么打,附实战复盘。
0x01 四个包含函数与两个伪协议
include / include_once / require / require_once:once 保证同文件只含一次(重复定义不报错),require 失败终止;攻击面相同,区别只在报错行为。
两个常用伪协议:
// php://filter:读源码(不执行),base64 输出绕过渲染
?file=php://filter/read=convert.base64-encode/resource=config.php
// php://input:把 POST 体当 PHP 执行(需 allow_url_include=On)
?file=php://input POST: <?php system('whoami');?>
0x02 日志包含在 Docker 里为什么失效
经典路径:往 access.log 注入 <?php eval($_POST[x]);?>(UA 头最干净)再包含日志;Docker 里全灭:
- 容器日志被重定向到 stdout/stderr(
/var/log/nginx/access.log -> /dev/stdout),文件里没有真实日志; - 多数镜像不带 phpinfo,临时文件包含(
PHP_SESSION_UPLOAD_PROGRESS/PHP_VALUE)所需的临时文件名拿不到。
结论:日志包含依赖”日志落盘 + 路径可知”——Docker 化破坏前者,先看容器化程度。
0x03 php://filter chain:不需要上传的 RCE
LFI 最优雅的现代打法:convert.iconv 过滤器级联逐层”变换”出 <?php ...; exit; ?>——绕开”只能包含不能执行”,不写文件:
?file=php://filter/convert.iconv.utf-8.utf-16|convert.iconv...|convert.base64-decode/resource=data:text/plain,<payload>
生成 chain 用 php_filter_chain_generator;原理:字符集编码读写互换产生字节层面的可控变换,级联等价于任意字节序列。触发条件同 php://input(allow_url_include)。
0x04 命令行参数注入(CLI 场景的 LFI 变体)
冷门但加分:PHP CLI 运行时 $_SERVER['argv'] 收集命令行参数;按 RFC,GET 里不含 = 的参数(如 ?/config/create)被某些框架当 argv 传,可构造调用内部工具的路径(config create)。另:php -S 0.0.0.0:7788 的目录少了 index.php 就 404。
0x05 实战复盘:一次高校内网渗透
完整案例(已脱敏),链路值得背下来:
来宾网络(开放无认证)──发现──> 来宾网与内网未隔离
→ 密码喷洒(固定弱密码 + 批量用户名)攻破统一身份认证
→ 统一认证里捡到四字姓名未改密账号
→ 内网横扫(X-Scan/fscan 指纹):SQL Server 弱口令 / 永恒之蓝 / VCenter
→ SQL 注入点 os-shell:sa 被降到 network service(能跑 dir/ipconfig,传不了文件)
→ 找可写目录:ProgramData(默认隐藏 + Everyone 权限,Windows 全系标配)
→ 上传 C2 马:被 360/火绒拦截 → 换轻量免杀 loader(share code 加载)
→ 上线后导出哈希 → VCenter RCE 拿通杀密码 → 登录主站后台
细节:
- 杀软确认:上传 txt 成功、上传马消失——反推有杀软;
- 权限继承:上传的马仍继承 network service 权限,还得提权——“注入权限 ≠ 服务器权限”;
- 内部系统不打补丁:WordPress 最新 RCE、用友/金蝶历史 RCE 打内网屡试不爽;
- WAF 识别:主站扫描返回 412 是创宇盾系特征,识破后换面;
- 法律红线:师生敏感数据只证明不带走,查询日志会留痕。