本文目录导读:

PHP 安全设计是一个系统工程,不能只靠“加一个函数”来解决,其核心思想是:永远不要信任用户的输入。
以下是 PHP 安全设计的核心原则,按照重要程度和实践场景分类:
核心防御原则(输入与输出)
这是 Web 安全的基础,几乎所有的漏洞(SQL注入、XSS、命令注入)都是因为没有做好这两点。
过滤输入(Filter Input)
- 含义:接收用户数据时,验证它是否符合预期格式。
- 做法:
- 类型检查:
is_numeric(),ctype_digit(),gettype()。 - 正则/规则验证:邮箱用
filter_var($email, FILTER_VALIDATE_EMAIL),URL 用FILTER_VALIDATE_URL。 - 白名单:如果参数只能是
a,b,c,则直接判断in_array($input, ['a', 'b', 'c'])。 - 长度限制:用
strlen()或mb_strlen()限制最大长度。
- 类型检查:
转义输出(Escape Output)
- 含义:数据输出到不同上下文(HTML, JavaScript, SQL, URL)时,要进行对应的转义。
- 做法:
- 输出到 HTML 体:使用
htmlspecialchars($data, ENT_QUOTES | ENT_HTML5, 'UTF-8')。这是防止 XSS 的最基本动作。 - 输出到 HTML 属性:同上,但要确保属性值是双引号包围的。
- 输出到 JavaScript:不要直接用 PHP 拼接 JS 字符串,使用
json_encode()将数据转为 JSON 字符串,然后在 JS 中解析。 - 输出到 URL:使用
urlencode()或rawurlencode()。 - 输出到 SQL:使用参数化查询,不要手动转义字符串。
- 输出到 HTML 体:使用
纵深防御(各个攻击面的具体防护)
SQL 注入 —— 使用 Prepared Statements
-
原则:绝对不要拼接 SQL 字符串。
-
做法:使用 PDO 或 MySQLi 的预处理语句。
// 正确做法 $stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email'); $stmt->execute(['email' => $userInput]); // 数据库驱动会处理转义 // 错误做法(高危) $sql = "SELECT * FROM users WHERE email = '" . $userInput . "'";
跨站脚本攻击 —— CSP + 转义
- 原则:除了转义输出,还应设置 HTTP 头。
- Content-Security-Policy:在响应头中限制资源加载来源。
// 只允许加载同源的脚本 header("Content-Security-Policy: script-src 'self'"); - HttpOnly Cookie:防止 XSS 窃取会话。
setcookie('session_id', $sessionId, ['httponly' => true, 'samesite' => 'Strict']);
跨站请求伪造 —— 验证来源
- 原则:任何执行写操作(修改、删除、转账)的请求,都必须验证是用户主动发出的。
- 做法:
- CSRF Token:在表单中生成一个随机 Token,存储在 Session 中,提交时对比。
- SameSite Cookie:设置
SameSite=Strict或Lax。 - 验证 Referer:检查 HTTP Referer 头,但可能被篡改。
文件上传 —— 最危险的入口之一
- 原则:永远不要信任文件的扩展名和 MIME 类型。
- 做法:
- 检查真实类型:使用
finfo_file()检查文件魔数(Magic Bytes),而不仅仅是$_FILES['file']['type']。 - 重命名文件:上传后不要保留用户原来的文件名,生成随机文件名(如
md5(time() . rand()) . 'jpg')。 - 限制路径:将文件存储到 Web 根目录之外,通过 PHP 脚本读取下载(便于控制权限和防直接执行)。
- 禁用执行权限:在
nginx/apache配置中,禁止 uploads 目录执行 PHP。
- 检查真实类型:使用
文件包含漏洞(LFI/RFI)
-
原则:避免动态文件包含。
-
做法:
- 如果必须动态包含,使用白名单映射。
// 危险做法 include($_GET['page'] . '.php');
// 安全做法 $allowed_pages = ['home', 'about', 'contact']; $page = in_array($_GET['page'], $allowed_pages) ? $_GET['page'] : 'home'; include($page . '.php');
- 禁用 `allow_url_include`(默认已禁,但需检查)。 - 如果必须动态包含,使用白名单映射。
配置与运行环境安全
禁用危险函数
- 在
php.ini的disable_functions中禁用以下函数(如果不需要):exec,system,passthru,shell_exec,popen,proc_open(命令执行)eval,assert(代码执行)file_put_contents,fputs,fwrite(结合路径遍历可能写 shell)phpinfo(信息泄露)error_reporting(生产环境应关闭显示错误)
错误处理
- 生产环境:
display_errors = Off,log_errors = On。 - 使用异常:用
try/catch捕获错误,返回统一的 JSON 或错误页面,避免泄露路径和 SQL 语句。
会话安全
- Session ID:使用
session_regenerate_id(true)在登录后重新生成。 - 超时:设置较短的 Session 过期时间,并结合
session.gc_maxlifetime。 - Httponly + Secure + SameSite:Cookie 设置如上。
数据库权限最小化
- 不要用
root连接数据库。 - 创建专门的应用账号,只授予
SELECT,INSERT,UPDATE,DELETE权限,严禁赋予FILE,CREATE,DROP,ALTER权限。
代码架构层面的设计
业务逻辑安全
- RABC(基于角色的访问控制):不要只在前端或 Session 里判断角色,要在后端每步操作都校验。
- 限额与限流:对“发送验证码”、“登入尝试”、“API 调用”进行频率限制,防止暴力破解。
- 幂等性:支付、提现等操作,使用唯一请求 ID 防止重复提交。
依赖管理
- Composer:定期运行
composer audit检查第三方包是否存在已知漏洞(CVE)。 - 更新:保持 PHP 版本和框架版本为最新的安全稳定版。
检查清单(快速自查)
| 攻击类型 | 检查要点 | 常用函数/配置 |
|---|---|---|
| SQL 注入 | 是否使用了 Prepared Statements? | PDO, MySQLi |
| XSS | 输出到 HTML 是否使用了 htmlspecialchars? | htmlspecialchars(), strip_tags() |
| CSRF | 操作是否校验 Token? | $_SESSION['token'] 比较 |
| 命令注入 | 是否禁用了 shell_exec 等函数? | escapeshellarg(), disable_functions |
| 文件上传 | 是否检查了文件魔数和重命名? | finfo_file(), move_uploaded_file() |
| 信息泄露 | 是否关闭了 display_errors? | ini_set('display_errors', 'Off') |
| 路径遍历 | 是否存在 的拼接? | realpath(), basename() |
| 代码执行 | 是否使用了 eval/assert? | 避免使用。 |
| 目录遍历 | 是否过滤了文件名中的 ? | basename() + 白名单 |
最核心的一句话是:输入视为有害,输出必有转义,逻辑必有校验,配置遵循最小化。 在这之上,配合现代的框架(Laravel, Symfony, ThinkPHP 等),它们内置了 CSRF 保护、ORM 防注入、模板引擎自动转义(Blade, Twig),可以帮你减少大量低级漏洞,但业务逻辑和配置层面的安全,仍然需要你自己把控。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播