Web 安全三大漏洞靶场作业全整理:PHP 核心函数与防御方案汇总

目录

[SQL 注入靶场作业整理:PHP 函数与漏洞防御全汇总](#SQL 注入靶场作业整理:PHP 函数与漏洞防御全汇总 "#SQL%20%E6%B3%A8%E5%85%A5%E9%9D%B6%E5%9C%BA%E4%BD%9C%E4%B8%9A%E6%95%B4%E7%90%86%EF%BC%9APHP%20%E5%87%BD%E6%95%B0%E4%B8%8E%E6%BC%8F%E6%B4%9E%E9%98%B2%E5%BE%A1%E5%85%A8%E6%B1%87%E6%80%BB")

[一、靶场中涉及的 PHP 核心函数整理](#一、靶场中涉及的 PHP 核心函数整理 "#%E4%B8%80%E3%80%81%E9%9D%B6%E5%9C%BA%E4%B8%AD%E6%B6%89%E5%8F%8A%E7%9A%84%20PHP%20%E6%A0%B8%E5%BF%83%E5%87%BD%E6%95%B0%E6%95%B4%E7%90%86")

[1. mysql_query()](#1. mysql_query() "#1.%20mysql_query()")

[2. addslashes()](#2. addslashes() "#2.%20addslashes()")

[3. mysql_real_escape_string()](#3. mysql_real_escape_string() "#3.%20mysql_real_escape_string()")

[二、各类 SQL 注入漏洞的防御方式](#二、各类 SQL 注入漏洞的防御方式 "#%E4%BA%8C%E3%80%81%E5%90%84%E7%B1%BB%20SQL%20%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E%E7%9A%84%E9%98%B2%E5%BE%A1%E6%96%B9%E5%BC%8F")

核心原理回顾

[1. 联合查询注入(GET/POST 字符型 / 数字型)](#1. 联合查询注入(GET/POST 字符型 / 数字型) "#1.%20%E8%81%94%E5%90%88%E6%9F%A5%E8%AF%A2%E6%B3%A8%E5%85%A5%EF%BC%88GET%2FPOST%20%E5%AD%97%E7%AC%A6%E5%9E%8B%20%2F%20%E6%95%B0%E5%AD%97%E5%9E%8B%EF%BC%89")

[2. 布尔盲注](#2. 布尔盲注 "#2.%20%E5%B8%83%E5%B0%94%E7%9B%B2%E6%B3%A8")

[3. 时间盲注](#3. 时间盲注 "#3.%20%E6%97%B6%E9%97%B4%E7%9B%B2%E6%B3%A8")

[4. 报错注入](#4. 报错注入 "#4.%20%E6%8A%A5%E9%94%99%E6%B3%A8%E5%85%A5")

[5. Cookie / 请求头注入(User-Agent、Referer 注入)](#5. Cookie / 请求头注入(User-Agent、Referer 注入) "#5.%20Cookie%20%2F%20%E8%AF%B7%E6%B1%82%E5%A4%B4%E6%B3%A8%E5%85%A5%EF%BC%88User-Agent%E3%80%81Referer%20%E6%B3%A8%E5%85%A5%EF%BC%89")

[6. 二次注入](#6. 二次注入 "#6.%20%E4%BA%8C%E6%AC%A1%E6%B3%A8%E5%85%A5")

[7. 宽字节注入](#7. 宽字节注入 "#7.%20%E5%AE%BD%E5%AD%97%E8%8A%82%E6%B3%A8%E5%85%A5")

三、全类型通用防御总结

XSS

[一、靶场中用到的 PHP 函数整理](#一、靶场中用到的 PHP 函数整理 "#%E4%B8%80%E3%80%81%E9%9D%B6%E5%9C%BA%E4%B8%AD%E7%94%A8%E5%88%B0%E7%9A%84%20PHP%20%E5%87%BD%E6%95%B0%E6%95%B4%E7%90%86")

[1. _GET 超全局变量](#1. _GET 超全局变量 "#1.%20%24_GET%20%E8%B6%85%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F")

[2. echo 输出函数](#2. echo 输出函数 "#2.%20echo%20%E8%BE%93%E5%87%BA%E5%87%BD%E6%95%B0")

[3. strlen() 函数](#3. strlen() 函数 "#3.%20strlen()%20%E5%87%BD%E6%95%B0")

[4.htmlspecialchars() ------ 核心防御函数 (Level 3 出现)](#4.htmlspecialchars() —— 核心防御函数 (Level 3 出现) "#4.htmlspecialchars()%20%E2%80%94%E2%80%94%20%E6%A0%B8%E5%BF%83%E9%98%B2%E5%BE%A1%E5%87%BD%E6%95%B0%20(Level%203%20%E5%87%BA%E7%8E%B0)")

[5. str_replace() ------ 危险的黑名单替换 (Level 4 - Level 8 出现)](#5. str_replace() —— 危险的黑名单替换 (Level 4 - Level 8 出现) "#5.%20str_replace()%20%E2%80%94%E2%80%94%20%E5%8D%B1%E9%99%A9%E7%9A%84%E9%BB%91%E5%90%8D%E5%8D%95%E6%9B%BF%E6%8D%A2%20(Level%204%20-%20Level%208%20%E5%87%BA%E7%8E%B0)")

[6. strtolower() ------ 大小写统一 (Level 6 & Level 8 出现)](#6. strtolower() —— 大小写统一 (Level 6 & Level 8 出现) "#6.%20strtolower()%20%E2%80%94%E2%80%94%20%E5%A4%A7%E5%B0%8F%E5%86%99%E7%BB%9F%E4%B8%80%20(Level%206%20%26%20Level%208%20%E5%87%BA%E7%8E%B0)")

[7. strpos() ------ 字符串查找 (Level 9 出现)](#7. strpos() —— 字符串查找 (Level 9 出现) "#7.%20strpos()%20%E2%80%94%E2%80%94%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%9F%A5%E6%89%BE%20(Level%209%20%E5%87%BA%E7%8E%B0)")

[8. ini_set() 函数](#8. ini_set() 函数 "#8.%20ini_set()%20%E5%87%BD%E6%95%B0")

[二、三类 XSS 漏洞的防御方式](#二、三类 XSS 漏洞的防御方式 "#%E4%BA%8C%E3%80%81%E4%B8%89%E7%B1%BB%20XSS%20%E6%BC%8F%E6%B4%9E%E7%9A%84%E9%98%B2%E5%BE%A1%E6%96%B9%E5%BC%8F")

[1. 反射型 XSS(Reflected XSS)](#1. 反射型 XSS(Reflected XSS) "#1.%20%E5%8F%8D%E5%B0%84%E5%9E%8B%20XSS%EF%BC%88Reflected%20XSS%EF%BC%89")

漏洞核心

完整防御方案

[2. 存储型 XSS(Stored XSS)](#2. 存储型 XSS(Stored XSS) "#2.%20%E5%AD%98%E5%82%A8%E5%9E%8B%20XSS%EF%BC%88Stored%20XSS%EF%BC%89")

​编辑

漏洞核心

完整防御方案

[3. DOM 型 XSS(DOM Based XSS)](#3. DOM 型 XSS(DOM Based XSS) "#3.%20DOM%20%E5%9E%8B%20XSS%EF%BC%88DOM%20Based%20XSS%EF%BC%89")

​编辑

漏洞核心

完整防御方案

文件上传

[一、靶场中使用到的 PHP 函数汇总](#一、靶场中使用到的 PHP 函数汇总 "#%E4%B8%80%E3%80%81%E9%9D%B6%E5%9C%BA%E4%B8%AD%E4%BD%BF%E7%94%A8%E5%88%B0%E7%9A%84%20PHP%20%E5%87%BD%E6%95%B0%E6%B1%87%E6%80%BB")

[1. 一句话木马 & 代码执行类(危险函数)](#1. 一句话木马 & 代码执行类(危险函数) "#1.%20%E4%B8%80%E5%8F%A5%E8%AF%9D%E6%9C%A8%E9%A9%AC%20%26%20%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E7%B1%BB%EF%BC%88%E5%8D%B1%E9%99%A9%E5%87%BD%E6%95%B0%EF%BC%89")

[2. 文件上传处理核心函数](#2. 文件上传处理核心函数 "#2.%20%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E5%A4%84%E7%90%86%E6%A0%B8%E5%BF%83%E5%87%BD%E6%95%B0")

[3. 文件类型 & 图片校验类函数](#3. 文件类型 & 图片校验类函数 "#3.%20%E6%96%87%E4%BB%B6%E7%B1%BB%E5%9E%8B%20%26%20%E5%9B%BE%E7%89%87%E6%A0%A1%E9%AA%8C%E7%B1%BB%E5%87%BD%E6%95%B0")

[4. 文件名 & 字符串处理类(黑名单校验核心)](#4. 文件名 & 字符串处理类(黑名单校验核心) "#4.%20%E6%96%87%E4%BB%B6%E5%90%8D%20%26%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%A4%84%E7%90%86%E7%B1%BB%EF%BC%88%E9%BB%91%E5%90%8D%E5%8D%95%E6%A0%A1%E9%AA%8C%E6%A0%B8%E5%BF%83%EF%BC%89")

[5. 其他文件操作函数](#5. 其他文件操作函数 "#5.%20%E5%85%B6%E4%BB%96%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C%E5%87%BD%E6%95%B0")

二、各关卡漏洞类型、原理与防御方式

[Pass-01:前端 JS 校验绕过](#Pass-01:前端 JS 校验绕过 "#Pass-01%EF%BC%9A%E5%89%8D%E7%AB%AF%20JS%20%E6%A0%A1%E9%AA%8C%E7%BB%95%E8%BF%87")

[Pass-02:MIME 类型(Content-Type)校验绕过](#Pass-02:MIME 类型(Content-Type)校验绕过 "#Pass-02%EF%BC%9AMIME%20%E7%B1%BB%E5%9E%8B%EF%BC%88Content-Type%EF%BC%89%E6%A0%A1%E9%AA%8C%E7%BB%95%E8%BF%87")

[Pass-03:黑名单不全 + Apache 后缀解析绕过](#Pass-03:黑名单不全 + Apache 后缀解析绕过 "#Pass-03%EF%BC%9A%E9%BB%91%E5%90%8D%E5%8D%95%E4%B8%8D%E5%85%A8%20%2B%20Apache%20%E5%90%8E%E7%BC%80%E8%A7%A3%E6%9E%90%E7%BB%95%E8%BF%87")

[Pass-04:.htaccess 配置文件绕过](#Pass-04:.htaccess 配置文件绕过 "#Pass-04%EF%BC%9A.htaccess%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%BB%95%E8%BF%87")

Pass-05:大小写绕过

Pass-06:空格绕过

Pass-07:点号绕过

[Pass-08:::DATA 文件流绕过](#Pass-08:::DATA 文件流绕过 "#Pass-08%EF%BC%9A%3A%3A%24DATA%20%E6%96%87%E4%BB%B6%E6%B5%81%E7%BB%95%E8%BF%87")

Pass-13:文件头魔数校验绕过

[Pass-14:getimagesize 图片尺寸校验绕过](#Pass-14:getimagesize 图片尺寸校验绕过 "#Pass-14%EF%BC%9Agetimagesize%20%E5%9B%BE%E7%89%87%E5%B0%BA%E5%AF%B8%E6%A0%A1%E9%AA%8C%E7%BB%95%E8%BF%87")

[Pass-15:exif_imagetype EXIF 校验绕过](#Pass-15:exif_imagetype EXIF 校验绕过 "#Pass-15%EF%BC%9Aexif_imagetype%20EXIF%20%E6%A0%A1%E9%AA%8C%E7%BB%95%E8%BF%87")

Pass-16:二次渲染绕过

Pass-17:条件竞争(时间差)绕过

三、文件上传漏洞通用防御总结


SQL 注入靶场作业整理:PHP 函数与漏洞防御全汇总

一、靶场中涉及的 PHP 核心函数整理

结合课程里 Less-1 到 Less-32 的所有关卡,共出现 3 个与 SQL 注入直接相关的关键 PHP 函数,对应课件里的源码与漏洞场景如下:

1. mysql_query()

  • 出现关卡:Less-1 ~ Less-4、Less-11 等所有基础注入关卡
  • 函数功能:PHP 早期操作 MySQL 的原生函数,作用是向数据库发送并执行一条 SQL 语句,是所有查询的执行入口。
  • 漏洞关联:这是 SQL 注入最终生效的核心节点。靶场后端代码将用户输入的 id、用户名直接拼接到 SQL 字符串中,再传给mysql_query()执行,用户输入的恶意语法会被数据库当成正常命令运行。
  • 对应源码片段:
php 复制代码
$sql = "SELECT * FROM users WHERE id='$id' LIMIT 0,1";

$result = mysql_query($sql);

2. addslashes()

  • 出现关卡:Less-32 宽字节注入关卡(关卡标题明确标注 Bypass addslashes())
  • 函数功能:自动在单引号'、双引号"、反斜杠\、NULL 字符前添加反斜杠\,开发者原本想用它转义特殊字符,阻止单引号闭合,从而防御 SQL 注入。
  • 漏洞关联:该函数不感知数据库编码格式。当网站使用 GBK 宽字节编码时,输入%df'会被函数处理为%df%5c%27(自动补充转义用的\,对应字节%5c);GBK 编码会将%df%5c识别为一个汉字,相当于 "吃掉" 了转义反斜杠,后面的单引号恢复闭合能力,从而形成宽字节注入。

3. mysql_real_escape_string()

  • 出现关卡:Less-24 二次注入关卡
  • 函数功能:比addslashes()更严谨的转义函数,会根据当前数据库的字符集转义 SQL 特殊字符,常规场景下可以防御普通 SQL 注入。
  • 漏洞关联:仅能防御 "一次注入"。注册用户名时,函数会将admin'#中的单引号转义后写入数据库;但数据最终存入数据库时,会还原为原始的admin'#。后续修改密码等功能直接从数据库读取用户名拼接 SQL,未做二次转义,最终触发二次注入。

二、各类 SQL 注入漏洞的防御方式

核心原理回顾

这张图对应课件第一页讲的 SQL 注入本质:用户输入本该是普通数据,却被错误拼接进 SQL 语句,变成了 SQL 语法的一部分。

  • 正常流程:用户传入 id=1 → 后端拼接为正常 SQL → 数据库仅返回 id=1 的单条数据
  • 注入流程:用户传入1 or 1=1 → 后端直接字符串拼接 → 数据库执行恶意条件 → 返回全表数据

1. 联合查询注入(GET/POST 字符型 / 数字型)

  • 对应关卡:Less-1~Less-4、Less-11(POST 登录框注入)
  • 漏洞特点:页面存在明确的数据回显位,可通过union select直接将查询结果显示在页面上,是最直观的注入类型。
  • 防御方案:
    1. 核心防御:使用预处理语句(PDO / MySQLi prepare)

彻底禁止字符串拼接 SQL,将 SQL 语句模板与用户数据分开发送给数据库;用户数据永远只会被识别为数据,不会成为 SQL 语法,这是防御 SQL 注入的黄金标准,可同时防御绝大多数注入类型。

  1. 输入类型强校验

数字型参数(如 id)强制使用intval()转为整数,从根源杜绝拼接可能。

  1. 数据库最小权限原则

业务数据库账号仅分配当前库的必要权限,禁止访问information_schema系统库,即使存在注入也难以拖库。

2. 布尔盲注

  • 对应关卡:Less-5
  • 漏洞特点:页面无数据回显,仅存在 "正常显示" 与 "空白 / 错误" 两种状态,攻击者通过and 条件的真假反馈逐字符猜解数据库内容。
  • 防御方案:
    1. 统一错误页面,无论 SQL 执行成功或失败,前端返回完全一致的页面,不提供真假判断依据。
    2. 接口添加访问频率限制,拦截自动化猜解脚本。
    3. 底层使用预处理语句,从语法层面阻断注入逻辑。

3. 时间盲注

  • 对应关卡:Less-9
  • 漏洞特点:页面无任何状态差异,攻击者通过sleep()等延迟函数的响应时间差,判断 SQL 条件是否成立,隐蔽性极强。
  • 防御方案:
    1. 禁用数据库sleep()、benchmark()等高风险延迟函数。
    2. 后端接口设置最大执行超时,异常延迟请求直接中断返回。
    3. 以预处理语句作为根本防御手段。

4. 报错注入

  • 对应关卡:Less-5(extractvalue、updatexml、floor 三种报错手法)
  • 漏洞特点:利用数据库函数的语法错误,将查询结果夹带在报错信息中回显,属于 "有回显" 的注入变种。
  • 防御方案:
    1. 生产环境必须关闭详细错误回显,统一返回通用错误提示,绝对禁止将数据库报错暴露给前端。
    2. 限制 XML 相关高危函数的使用权限。
    3. 预处理 + 输入校验双保险。
  • 对应关卡:Less-18、Less-20
  • 漏洞特点:注入点不在 URL 和表单,而在 Cookie、User-Agent、Referer 等请求头中;后端将这些值直接拼接进 SQL(如保存日志、查询用户身份)。
  • 防御方案:
    1. 所有客户端输入一视同仁:URL、表单、Cookie、请求头都必须做校验与预处理,不能默认 "请求头不可篡改"。
    2. 日志写入数据库使用参数化语句,禁止字符串拼接。
    3. Cookie 增加签名校验,防止恶意篡改。

6. 二次注入

  • 对应关卡:Less-24
  • 原理流程图(对应课件 "先存后用" 的逻辑):

二次注入原理流程图

这张图完整对应课件讲解的二次注入流程:

  1. 第一步:注册时输入admin'#,转义函数对单引号做了转义,数据成功入库;但数据库里最终保存的仍是原始的admin'#。
  2. 第二步:修改密码等业务场景,直接从数据库读取用户名拼接 SQL,未做二次转义,单引号成功闭合触发注入。
  • 防御方案:
    1. 所有 SQL 执行场景都使用预处理,无论数据来自用户输入还是数据库查询。
    2. 摒弃 "入库数据就是安全数据" 的错误认知,数据出库复用也必须做安全处理。
    3. 用户名、昵称等字段做白名单限制,禁止包含单引号、#、--等 SQL 关键字。

7. 宽字节注入

  • 对应关卡:Less-32
  • 漏洞特点:利用addslashes()自动添加的反斜杠,与前置字节拼接成宽字节汉字,"吃掉" 转义符,让单引号恢复闭合能力。
  • 防御方案:
    1. 彻底废弃addslashes(),使用mysql_real_escape_string()并明确指定数据库字符集为 UTF-8。
    2. 数据库、PHP、前端全链路统一使用 UTF-8 编码,不使用 GBK 等宽字节编码。
    3. 终极方案:使用 PDO 预处理,完全不依赖转义函数,从机制上杜绝此类问题。

三、全类型通用防御总结

  1. 首选方案:PDO 预处理语句,是最彻底、最可靠的防御手段
  2. 输入校验:优先使用白名单校验,而非黑名单过滤
  3. 错误隐藏:生产环境禁止暴露数据库详细报错信息
  4. 权限最小化:数据库账号仅分配业务必需的最低权限
  5. 辅助防护:部署 WAF Web 应用防火墙,拦截常见注入 payload

XSS

一、靶场中用到的 PHP 函数整理

1. $_GET 超全局变量

  • 功能:接收客户端通过 URL 参数以 GET 方式提交的数据,是 Web 应用最基础的输入入口。
  • 靶场应用 :level1~level10、level16 等绝大多数关卡,通过name、keyword等参数接收用户输入,是所有反射型 XSS 的输入源头。
  • 对应文档图片 :

2. echo 输出函数

  • 功能:向 HTML 页面输出字符串内容,直接拼接到页面源码中。
  • 靶场应用:所有关卡的输出点,将用户输入渲染到页面标题、搜索结果、input 输入框值等位置;未做编码时,用户输入的脚本会被浏览器直接解析执行。
  • 对应文档图片 :
    • 反射型 XSS 流程图里的echo "<h2 align=center>欢迎用户".$str."</h2>";源码片段
    • level2 页面中输出搜索结果的<h2>标签源码截图

3. strlen() 函数

  • 功能:统计字符串的字节长度。
  • 靶场应用:每一关页面底部显示「payload 的长度」,用于统计用户提交输入的字符数。
  • 对应文档图片 :各关卡页面底部payload的长度: xx的展示区域

4.htmlspecialchars() ------ 核心防御函数 (Level 3 出现)

  • 作用: 将 HTML 特殊字符(如 <、>、&、")转换为 HTML 实体(如 &lt;、&gt;)。浏览器在渲染时只会将它们当作普通文本显示,而不会将其解析为可执行的 HTML 标签或 JavaScript 代码。

  • 靶场利用点:

    • 早期版本的 htmlspecialchars() 默认只转义双引号("),不转义单引号(')。

    • 在 Level 3 中,当你发现 < 和 > 被过滤,但输入 <input value='你的输入'> 时,可以通过单引号闭合属性:' onfocus=alert(123) x=' 来绕过。

5. str_replace() ------ 危险的黑名单替换 (Level 4 - Level 8 出现)

  • 作用: 字符串替换函数。格式为 str_replace("被替换的字符", "替换成的字符", $目标变量)。

  • 靶场利用点: 开发人员常把它当黑名单用,但这往往千疮百孔。

    • Level 4 过滤了 < 和 >: 利用事件属性绕过(如 " onfocus=alert(123) autofocus=")。

    • Level 5 过滤了 <script> 和 on(变为 o_n): 转换为利用 href 属性结合伪协议绕过,如 "><a href=javascript:alert(123)>。

    • Level 7 进行了关键字删除: 采用双写绕过 ,如 oonnfocus 或 scscriptipt,替换函数执行一次后,剩下的字符刚好拼成完整的恶意 payload。

6. strtolower() ------ 大小写统一 (Level 6 & Level 8 出现)

  • 作用: 将字符串转化为小写。

  • 靶场利用点:

    • 在 Level 6 中,因为没有 使用此函数,所以可以通过大小写混写绕过限制,如 " ONfocus=alert(123) 或 <sCrIpT>。

    • 在 Level 8 中加入了此函数,导致大小写绕过失效,从而逼迫你使用了 HTML 实体编码 (如 &#x73; 代表 s)来绕过关键字检测。

7. strpos() ------ 字符串查找 (Level 9 出现)

  • 作用: 查找字符串在另一字符串中首次出现的位置。

  • 靶场利用点:

    • Level 9 代码 if(false===strpos($str7, 'http://')) 要求输入中必须包含 http://。

    • 绕过方式:将其作为 JavaScript 的单行注释附在 Payload 后面。如:javascript:alert(123)//http://。

8. ini_set() 函数

  • 功能:动态修改 PHP 运行时的配置项。
  • 靶场应用 :多数关卡开头ini_set("display_errors",0);,关闭 PHP 错误提示,避免错误信息泄露服务器源码与路径。

二、三类 XSS 漏洞的防御方式

1. 反射型 XSS(Reflected XSS)

漏洞核心

恶意脚本随单次请求传入、随本次响应返回,不存入数据库;需要诱导用户点击恶意链接触发,一次性生效。

完整防御方案
  1. 输出编码(核心措施) 所有用户可控内容输出到 HTML 页面时,必须使用带完整参数的htmlspecialchars():

    php 复制代码
    htmlspecialchars($data, ENT_QUOTES, 'UTF-8');

    ENT_QUOTES会同时转义单引号和双引号,彻底避免属性闭合绕过。

  2. 输入白名单校验 对输入做格式校验(比如姓名只能是中英文 + 数字),不符合格式直接拒绝,比黑名单过滤更可靠。

  3. 不依赖黑名单过滤 仅靠str_replace替换script、on等关键字不可靠,可通过大小写、双写、HTML 编码等多种方式绕过。


2. 存储型 XSS(Stored XSS)

漏洞核心

恶意脚本被写入数据库永久保存,所有访问该内容的用户都会触发;危害远大于反射型,不需要诱导点击,访问即中招。

完整防御方案
  1. 输出编码(核心措施) 和反射型一致,从数据库取出的所有用户内容,渲染到 HTML 时必须用htmlspecialchars(..., ENT_QUOTES, 'UTF-8')做实体编码。

    注意:写入数据库时不需要转义 HTML 实体,只在输出到页面时转义,避免数据重复转义。

  2. 输入侧校验 提交内容时做格式校验,限制长度、允许的内容范围;如果必须使用富文本,要用专业的白名单过滤库(不能自己写黑名单)。

  3. 深度防御

    • 配置 CSP(内容安全策略),限制页面可执行的脚本来源,即使存在 XSS 也无法加载恶意脚本
    • 关键 Cookie 设置HttpOnly属性,防止 XSS 盗取用户 Cookie

3. DOM 型 XSS(DOM Based XSS)

漏洞核心

完全发生在客户端浏览器,恶意 Payload 不需要出现在服务器响应中;前端 JS 直接从 URL(hash/search)、本地存储等读取数据,未经处理写入innerHTML、document.write等危险位置。

  • 常见可控来源(Source):location.hash、location.search、document.URL
  • 常见危险操作点(Sink):innerHTML、document.write()、eval()
完整防御方案
  1. 前端输出处理(核心措施)
    • 插入纯文本优先使用textContent替代innerHTML,纯文本不会被解析为 HTML
    • 必须使用 innerHTML 时,先对内容做 HTML 实体编码,或使用成熟的 XSS 净化库(如 DOMPurify)
  2. 禁止危险操作 避免把用户可控数据传入eval()、setTimeout()等可执行字符串代码的函数;避免直接把用户数据拼接到href、src等属性中。
  3. 服务端辅助 对 URL 参数做输入校验,同时配置 CSP 策略做深度防御。

文件上传

一、靶场中使用到的 PHP 函数汇总

1. 一句话木马 & 代码执行类(危险函数)

对应你笔记里「PHP 一句话木马」「免杀变形」章节的截图,是 Webshell 的核心组成。

| 函数名 | 核心作用 | 出现场景 | | --- | --- | --- | | eval() | 将字符串当作 PHP 代码执行,一句话木马最核心函数 | 基础木马 ,所有关卡木马的核心逻辑 | | assert() | 断言函数,同样可执行 PHP 代码 | 木马变形免杀,配合回调函数间接调用 | | system() | 直接执行操作系统命令(如 whoami、ipconfig) | 木马传参 cmd=system('whoami'),调用系统命令 | | phpinfo() | 输出 PHP 环境配置信息 | 上传后测试文件是否能被 PHP 解析器正常执行 | | call_user_func() | 回调函数,动态调用指定函数 | 木马变形:间接调用危险函数,绕过关键字检测 | | base64_decode() | Base64 解码 | 编码隐藏木马:将关键字编码后再解码执行,绕过 WAF 关键字查杀 |

对应你笔记的图片:

补充原理示意图:

PHP一句话木马执行原理

2. 文件上传处理核心函数

对应每一关 PHP 源码里的上传基础逻辑,所有关卡通用。

| 函数 / 超全局变量 | 核心作用 | | --- | --- | | $_FILES | 超全局变量,获取上传文件的全部信息(文件名、临时路径、类型、大小等) | | move_uploaded_file() | 将上传的临时文件移动到目标保存目录,PHP 文件上传的核心函数 | | isset() | 判断变量是否存在,用于检测用户是否点击上传按钮 | | file_exists() | 判断目录 / 文件是否存在,用于检查上传目录是否存在 |

3. 文件类型 & 图片校验类函数

对应笔记第 13-15 关的校验源码、魔数对照表。

| 函数名 | 核心作用 | 出现关卡 | | --- | --- | --- | | fopen() | 打开文件句柄 | Pass-13 自定义getReailFileType函数,打开文件读取头部 | | fread() | 读取指定长度的文件字节 | Pass-13 读取文件前 2 字节,判断魔数 | | fclose() | 关闭文件句柄 | 读取文件头后释放资源 | | unpack() | 将二进制数据解包为数组 | Pass-13 把 2 字节魔数转为数字,判断是 jpg/png/gif | | getimagesize() | 获取图片尺寸,同时返回图片类型常量 | Pass-14 通过图片宽高和类型判断合法性 | | image_type_to_extension() | 将图片类型常量转为后缀名 | Pass-14 配合getimagesize获取合法后缀 | | exif_imagetype() | 读取文件头魔数判断图片类型(需开启 exif 扩展) | Pass-15 更专业的魔数校验,需要在 php.ini 开启扩展 |

对应你笔记的图片:

4. 文件名 & 字符串处理类(黑名单校验核心)

对应笔记第 3-8 关的黑名单绕过逻辑,每少一个函数就对应一种绕过方法。

| 函数名 | 核心作用 | 对应绕过关卡 | | --- | --- | --- | | strrchr() | 截取最后一个.后的字符串,提取文件扩展名 | 所有黑名单关卡 | | strtolower() | 将字符串转为小写 | Pass-5 无此函数,可用.PHP大写后缀绕过 | | str_ireplace() | 不区分大小写替换字符串 | 用于去除::$DATA等特殊后缀 | | trim() | 去除字符串首尾空格 | Pass-6 无此函数,可用.php 后缀加空格绕过 | | deldot() | 自定义函数,删除文件名末尾的点 | Pass-7 无此函数,可用.php.后缀加点绕过 | | in_array() | 判断值是否在数组中 | 黑白名单校验核心逻辑 | | date() + rand() | 生成日期 + 随机数 | 组合生成唯一文件名,防止文件覆盖 |

5. 其他文件操作函数

| 函数名 | 核心作用 | 出现场景 | | --- | --- | --- | | file_put_contents() | 向文件写入内容,可创建新文件 | Pass-17 条件竞争:在文件被删除前写入一个永久木马 |

二、各关卡漏洞类型、原理与防御方式

Pass-01:前端 JS 校验绕过

对应笔记图片:

  • 页面弹窗:「该文件不允许上传,请上传 jpg/png/gif 类型的文件」
  • JS 源码截图:checkFile() 函数在浏览器端提取后缀判断

漏洞原理:

校验完全在浏览器前端执行,服务端没有二次校验。禁用 JS 或抓包修改文件名即可直接绕过。

绕过方式:BurpSuite 抓包,把文件名从.png改回.php再放行。

防御方式:

  1. 前端校验仅做用户体验优化,服务端必须做二次校验
  2. 永远不能信任客户端侧的任何校验结果

Pass-02:MIME 类型(Content-Type)校验绕过

对应笔记图片:

  • PHP 源码截图:判断$_FILES'upload_file''type'是否为三种图片类型
  • Burp 抓包修改Content-Type字段的截图

漏洞原理:

只校验 HTTP 请求头里的Content-Type字段,该字段由客户端完全可控,抓包修改即可绕过。

绕过方式:抓包把Content-Type改为image/png,文件名保持.php。

防御方式:

  1. 不能信任客户端传来的Content-Type,必须服务端检测文件真实内容
  2. 配合文件头魔数、图片二次渲染做多重校验

Pass-03:黑名单不全 + Apache 后缀解析绕过

对应笔记图片:

  • 黑名单数组:仅禁止.asp/.aspx/.php/.jsp
  • Apache 解析特性说明:.php3/.php5也会被当作 PHP 执行

漏洞原理:

  1. 黑名单过滤不完整,遗漏了 Apache 可识别的 PHP 变体后缀
  2. Apache 多后缀解析特性:从右往左识别后缀,遇到不认识的就继续往左解析

**绕过方式:**文件名改为.php5、.php3等变体后缀。

防御方式:

  1. 放弃黑名单,改用白名单机制,只允许指定后缀上传
  2. 关闭中间件多后缀解析功能,强制只按最后一个后缀解析
  3. 上传后文件统一重命名,禁止保留原始文件名

Pass-04:.htaccess 配置文件绕过

对应笔记图片:

  • 超长黑名单列表,封死了几乎所有 PHP 相关后缀
  • .htaccess文件内容截图:SetHandler application/x-httpd-php

漏洞原理:

黑名单未禁止.htaccess文件,攻击者可上传 Apache 目录级配置文件,让当前目录下所有文件(包括图片)都用 PHP 解析器执行。

补充示意图:

.htaccess文件上传绕过原理

绕过方式:先上传.htaccess配置文件,再上传图片马,图片会被当作 PHP 执行。

防御方式:

  1. 白名单中禁止.htaccess、.user.ini等配置文件
  2. Apache 全局配置设置 AllowOverride None,禁止目录级配置生效
  3. 上传目录关闭 PHP 解析权限

Pass-05:大小写绕过

对应笔记图片:

  • 源码截图:黑名单只有小写.php,代码中无strtolower()转小写步骤

漏洞原理:

Windows 系统对文件名大小写不敏感,.php和.PHP是同一个文件;但黑名单只校验小写,未做大小写转换。

**绕过方式:**文件名改为.PHP、.Php等大小写混合形式。

防御方式:

  1. 提取后缀后统一用strtolower()转小写再校验
  2. 优先使用白名单机制

Pass-06:空格绕过

对应笔记图片:

  • Burp 抓包截图:文件名末尾加空格 .php
  • 源码中缺少trim()首尾去空步骤

漏洞原理:

Windows 系统会自动去除文件名末尾的空格,而校验时带空格的后缀不在黑名单中。

**绕过方式:**抓包在文件名后缀后加空格。

防御方式:

  1. 校验前先用trim()去除文件名首尾空白字符
  2. 对文件名做规范化处理后再校验

Pass-07:点号绕过

对应笔记图片:

  • 源码截图:缺少deldot()删除末尾点的步骤
  • 文件名.php.的抓包示例

漏洞原理:

Windows 系统会自动去掉文件名末尾的点,.php.最终保存为.php;但校验时点号后缀不在黑名单中。

绕过方式:文件名末尾加一个点 .php.。

防御方式:

  1. 校验前删除文件名末尾所有点号
  2. 规范化文件名路径,规避 Windows 系统特性绕过

Pass-08:::$DATA 文件流绕过

对应笔记图片:

  • NTFS 文件流说明截图:index.txt::$DATA是默认数据流
  • 抓包文件名test.php::$DATA示例

漏洞原理:

Windows NTFS 文件系统中,::$DATA代表默认数据流,加上后系统仍按原文件保存;但黑名单中没有这种后缀形式。

绕过方式:文件名后追加::$DATA。

防御方式:

  1. 校验前去除文件名中的::$DATA等特殊流标识
  2. 用严格的白名单正则匹配文件名,只允许字母、数字、点、下划线

Pass-13:文件头魔数校验绕过

对应笔记图片:

  • 自定义getReailFileType函数源码:只读前 2 字节判断魔数
  • Burp 抓包截图:文件内容开头加GIF89a
  • 完整魔数对照表

漏洞原理:

只校验文件开头的魔数字节,攻击者在木马文件开头加上图片文件头,就能骗过检测,后半部分仍是 PHP 代码。

绕过方式:

  1. 木马文件开头加GIF89a(GIF 文件头标识)
  2. 用命令 copy /b 图片.png + 木马.php 图片马.png 制作图片马

防御方式:

  1. 不能只校验文件头,需配合二次渲染、图片重绘
  2. 对上传图片重新编码生成,清除附加的恶意内容

Pass-14:getimagesize 图片尺寸校验绕过

对应笔记图片:

  • 源码截图:getimagesize() + image_type_to_extension() 校验
  • 十六进制编辑器打开图片的截图

漏洞原理:

getimagesize()读取图片尺寸信息,只要图片结构完整就能通过。尾部追加 PHP 代码的图片马仍保留完整图片结构,可以绕过。

绕过方式:普通图片马即可绕过。

防御方式:

  1. 使用 GD 库对图片进行二次渲染(重绘),破坏附加代码
  2. 上传目录禁止 PHP 执行权限,即使有图片马也无法解析

Pass-15:exif_imagetype EXIF 校验绕过

对应笔记图片:

  • 源码截图:exif_imagetype() 函数校验
  • php.ini 开启php_exif.dll的修改截图

漏洞原理:

本质仍是魔数校验,只是用 PHP 官方扩展实现,比自定义函数更规范,但图片马依然可以绕过。

绕过方式:正常图片马即可绕过。

**防御方式:**同第 14 关,二次渲染 + 目录禁止执行权限。

Pass-16:二次渲染绕过

对应笔记图片:

  • 关卡说明:GD 库对图片二次渲染,会清除大部分附加数据

漏洞原理:

二次渲染会将图片解码再重新编码,尾部追加的代码会被清除。但图片中部分区块(如 GIF 注释块、PNG 特定数据块)渲染后保持不变,可将木马藏在这些稳定区域。

绕过方式:找到图片渲染前后不变的字节区域,将 PHP 代码写入该位置。

防御方式:

  1. 使用成熟图片处理库做严格二次渲染
  2. 强制统一图片格式、压缩质量,最大化清除额外数据
  3. 上传目录必须关闭脚本执行权限

Pass-17:条件竞争(时间差)绕过

对应笔记图片:

、

  • Burp Intruder 设置截图:上传包和访问包各发送 5000 次
  • 访问结果截图:大量 404 中找 200 成功请求
  • file_put_contents() 函数说明截图

漏洞原理:

服务端逻辑是「先保存文件 → 再校验后缀 → 不合法就删除」,保存和删除之间存在极短时间窗口。攻击者高并发上传 + 访问,就能在删除前执行代码,写入永久木马。

绕过方式:

  1. 木马内容用file_put_contents()生成一个新的永久木马文件
  2. Burp Intruder 同时高并发发送上传和访问请求,抢占时间窗口

防御方式:

  1. 先校验文件合法性,校验通过后再移动到目标目录
  2. 先保存到临时不可访问目录,校验通过后再重命名到公开目录
  3. 限制上传频率,防御高并发攻击

三、文件上传漏洞通用防御总结

结合所有关卡,企业级防御的核心原则:

  1. 白名单优先:永远用白名单限制允许的文件类型,不使用黑名单
  2. 多重校验:后缀名 + MIME + 文件头 + 二次渲染 多层校验
  3. 强制重命名:上传后文件统一随机重命名,禁止保留原始文件名
  4. 目录隔离:上传目录单独存放,关闭该目录的脚本执行权限
  5. 路径安全:禁止路径穿越,固定保存路径,不使用用户传入的路径
  6. 权限最小化:上传目录设置只读权限,禁止执行、禁止列目录
相关推荐
T.O.P_KING1 小时前
Falco vs. Tetragon:云原生运行时安全选型指南
安全·云原生
leizhen198408091 小时前
Vibe Coding:门槛降了,但判断力成了新的门槛(漫画)
人工智能·安全
guohuang2 小时前
让机器人安全失败:点云中断、TF 超时和控制器崩溃怎么测
git·安全·机器人
sejinan3 小时前
新版!IPTV直播源列表 V1.7 正式发布:接口大厅与会员定制生态解读
开发语言·php
持敬chijing3 小时前
白盒测试与代码审计-JS 数据逆向
javascript·网络·安全·web安全·网络安全·网络攻击模型·安全威胁分析
白帽攻防录12 小时前
SRC 挖洞:PostScript 打印机驱动双 RCE,打印服务器怎么变成内网跳板
开发语言·网络安全·php·内网安全
xixiaoyunya14 小时前
Python 异步编程入门:用 asyncio 轻松实现并发任务
开发语言·python·php
FairGuard手游加固14 小时前
手游加固怎么做?SO、IL2CPP、AssetBundle 与运行时保护详解
安全·游戏·unity