安全问题要按攻击发生的位置理解。XSS 让恶意脚本进入受信任页面,CSRF 借用用户浏览器自动携带的凭证发起请求,SQL 注入把不可信输入拼进查询,WAF 则位于流量入口尝试识别和阻断可疑请求。
XSS
危险写法:
1 | preview.innerHTML = userInput |
攻击者提交的 HTML 或脚本可能在其他用户浏览器中执行。防护重点:
- 按输出上下文编码,而不是只做关键词替换。
- 默认使用安全模板插值或
textContent。 - 必须渲染富文本时使用成熟白名单净化器。
- 使用 Content Security Policy 限制脚本来源。
- 敏感 Cookie 设置
HttpOnly,降低脚本读取风险。
CSRF
如果浏览器访问目标站点时会自动携带 Cookie,恶意页面可能诱导用户发起转账或改密请求。防护包括:
- 使用 CSRF Token。
- Cookie 设置合适的
SameSite。 - 校验
Origin或Referer作为补充。 - 修改状态使用非安全方法,并要求重新认证关键操作。
使用 Authorization Header 的 Token 可以减少传统 Cookie CSRF 面,但若 Token 被不安全地暴露给 XSS,风险会转移而不是消失。
SQL 注入
不要拼接 SQL:
1 | $sql = "SELECT id, name FROM users WHERE email = '" . $_GET['email'] . "'"; |
使用参数化查询:
1 | $stmt = $pdo->prepare('SELECT id, name FROM users WHERE email = ?'); |
参数化只能保护值。动态列名、排序方向和表名应从固定白名单选择,数据库账号也要使用最小权限。
WAF 的位置和边界
1 | 用户 -> CDN/WAF -> 负载均衡 -> Web 应用 -> 数据库 |
WAF 可以根据规则、速率和威胁情报拦截部分攻击,适合补充入口防护和应急虚拟补丁,但它不了解全部业务权限,也无法可靠修复越权、逻辑漏洞、弱密码和内部调用风险。
基础防护清单
- 输入做类型、长度、格式和业务范围校验。
- 输出按 HTML、属性、URL、JavaScript 等上下文编码。
- 查询使用参数化,系统命令避免字符串拼接。
- 认证、授权、租户隔离在服务端执行。
- 上传文件校验内容、大小、存储位置和访问权限。
- 日志不记录密码、完整 Token 和敏感个人信息。
- 依赖持续更新,并用自动化扫描辅助发现风险。