### 文件上传防御方法

**1. 客户端验证**

客户端验证通常指通过 JavaScript 在前端对文件进行检查

- **优点**：可以快速、友好地提示用户，减少不必要的服务器请求，提升用户体验
- **缺点**：非常容易绕过。攻击者可以通过抓包工具（如 Burp Suite）修改 HTTP 请求，或直接禁用 JavaScript。因此，**客户端验证绝对不能作为唯一的安全措施**

常见的客户端验证包括：

- **文件扩展名验证**：检查文件的扩展名是否为允许的类型（如`.jpg`, `.png`, `.pdf`）
- **MIME类型验证**：检查文件的 MIME 类型（如 `image/jpeg`, `application/pdf`）
- **文件大小验证**：限制上传文件的大小，防止恶意文件过大导致服务器资源耗尽

**2. 服务器端验证**

服务器端验证是防御文件上传漏洞的最后一道防线，也是最可靠的

- **文件扩展名白名单验证**：**强烈推荐使用白名单**。只允许上传特定、已知的安全扩展名，如 `.jpg`, `.png`, `.gif`, `.pdf`, `.zip` 等。**绝对不要使用黑名单**，因为攻击者总能找到新的绕过方式
- **MIME 类型验证**：在服务器端验证文件头的 MIME 类型，防止攻击者通过伪造扩展名来上传恶意文件
- **文件内容检测**：对上传的文件内容进行深度检查
  - **图片**：使用 `getimagesize()` 等函数检测文件是否为真实的图片文件
  - **压缩包**：检查压缩包中的文件列表，确保没有可执行文件或恶意脚本
- **文件重命名**：在文件上传后，对其进行重命名，通常是使用一个随机字符串或加密哈希值作为文件名，并去除原始扩展名。这能有效防止攻击者通过文件名猜测 WebShell 的路径

**3. 文件存储与执行权限控制**

即使恶意文件侥幸通过了所有验证，我们仍然可以通过权限控制来阻止它被执行。

- **分离存储与执行**：将用户上传的文件存储在**非Web根目录**下。这样，即使攻击者知道文件路径，也无法通过URL直接访问或执行。
- **禁止执行权限**：将上传文件的目录设置为**不可执行**。在Nginx或Apache中，可以通过配置来禁止特定目录执行脚本文件。
  - **Nginx**：在配置文件中添加 `location` 规则，并设置 `deny all;` 或 `deny execution;`。
  - **Apache**：在 `.htaccess` 文件中添加 `php_flag engine off` 或类似的规则。
- **最小权限原则**：Web服务器进程（如Nginx、Apache）应以低权限用户运行，并确保其对上传目录只有**写入**权限，而**没有执行**权限。