跳转到内容

Xss Csrf Sql注入防护规范

常见 Web 漏洞防护


[Requirement] 采用输出编码 + CSP + HttpOnly Cookie 三层防御,禁止依赖任何单一手段。

[Requirement] 所有用户可控内容在渲染到 HTML 时必须做上下文相关的转义,禁止直接拼接。

[Requirement] 渲染到 HTML 文本节点时转义 < > & " ' 五个字符。

上下文转义规则工具
HTML 文本<→&lt; >→&gt; &→&amp;模板引擎默认转义
HTML 属性"→&quot; '→&#39;用双引号包裹属性值
JavaScript用 JSON.stringify 输出,禁止字符串拼接JSON.parse
URLencodeURIComponent仅编码参数值
<!-- 错误:直接输出未转义 -->
<div>{{ user_input | safe }}</div>
 
<!-- 正确:模板引擎默认转义(Jinja2 / Vue / React 默认) -->
<div>{{ user_input }}</div>

[Caution] Vue / React 默认对插值做 HTML 转义,使用 v-html / dangerouslySetInnerHTML 必须先经过白名单过滤(如 DOMPurify)。

[Requirement] 生产环境必须设置 Content-Security-Policy 响应头,禁止使用 unsafe-inline 和 unsafe-eval。

Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-abc123'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-ancestors 'none'; base-uri 'self'

[Standard] CSP 指令使用 nonce 或 hash 方式放行内联脚本,逐步淘汰 unsafe-inline。

[Requirement] 所有 Cookie 设置 HttpOnly; Secure; SameSite=Lax/Strict,敏感会话 Cookie 必须 HttpOnly。

Set-Cookie: session=xxx; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=3600

[Standard] 业务需要富文本时,使用白名单过滤(如 DOMPurify、bleach),仅允许 <b><i><u><a href><img src> 等安全标签,剥离 on* 事件属性和 javascript: 协议。

import bleach
 
ALLOWED_TAGS = ["b", "i", "u", "a", "img", "p", "br", "ul", "ol", "li"]
ALLOWED_ATTRS = {"a": ["href", "title"], "img": ["src", "alt"]}
 
def sanitize_html(html: str) -> str:
    return bleach.clean(html, tags=ALLOWED_TAGS, attributes=ALLOWED_ATTRS,
                        protocols=["http", "https"], strip=True)

[Requirement] 所有会修改状态的请求(POST/PUT/PATCH/DELETE)必须防御 CSRF,GET 必须保持幂等。

[Standard] 采用 SameSite Cookie + CSRF Token 双重防御;现代浏览器 SameSite 是基础,CSRF Token 是补充。

[Requirement] 会话 Cookie 设置 SameSite=Lax(允许从外部链接 GET 带 Cookie)或 SameSite=Strict(完全禁止跨站带 Cookie),按业务选择。

SameSite 值跨站 GET 带 Cookie跨站 POST 带 Cookie适用场景
Strict否否高安全后台
Lax是否大多数站点
None是是需跨站的场景,必须 Secure

[Standard] 服务端生成随机 Token 存于会话,渲染到表单隐藏字段或响应头,提交时校验。

<form method="POST" action="/update">
  <input type="hidden" name="csrf_token" value="{{ csrf_token }}">
  ...
</form>
# 服务端校验
def verify_csrf(request):
    token = request.headers.get("X-CSRF-Token") or request.form.get("csrf_token")
    if not token or token != session.get("csrf_token"):
        raise CSRFError("CSRF token 校验失败")

[Standard] 校验 Origin / Referer 头,跨域请求必须在白名单内。

[Caution] 禁止用 GET 请求执行修改操作(如 /delete?id=1),GET 容易被 CSRF 且会被浏览器缓存/记录。


[Requirement] 所有数据库操作必须使用参数化查询(预编译语句 / ORM),禁止字符串拼接 SQL。

# 正确:参数化查询
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
 
# 错误:字符串拼接(SQL 注入)
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
# 正确:ORM 查询
User.query.filter(User.id == user_id).first()
 
# 错误:ORM 也可能注入(用 text 拼接)
session.execute(text(f"SELECT * FROM users WHERE name = '{name}'"))

[Standard] LIKE 查询的通配符 % _ 必须转义,动态字段名必须用白名单校验,不能直接拼接。

# LIKE 转义
safe_name = name.replace("%", r"\%").replace("_", r"\_")
cursor.execute("SELECT * FROM users WHERE name LIKE %s ESCAPE '\\'", (f"%{safe_name}%",))
 
# 动态排序字段白名单
ALLOWED_SORT = {"id", "created_at", "name"}
sort_field = sort_field if sort_field in ALLOWED_SORT else "id"
cursor.execute(f"SELECT * FROM users ORDER BY {sort_field} ASC")

[Standard] 优先使用 ORM(SQLAlchemy、MyBatis)的查询构造器,ORM 默认使用参数化查询。

[Caution] 即使使用 ORM,使用 text() / raw() / execute("原生 SQL") 时仍需参数化,不能拼接。

[Requirement] 应用数据库账号只授予业务所需权限(SELECT/INSERT/UPDATE/DELETE),禁止授予 DROP/ALTER/GRANT 等权限。

[Requirement] 禁止使用 root / 超级管理员账号连接数据库。


[Requirement] 文件操作禁止直接拼接用户输入的路径,必须校验最终路径在允许目录内。

import os
 
BASE_DIR = "/data/uploads"
 
def safe_path(filename: str) -> str:
    # 去除路径分隔符和 ..
    safe_name = os.path.basename(filename)
    full = os.path.normpath(os.path.join(BASE_DIR, safe_name))
    if not full.startswith(BASE_DIR + os.sep):
        raise ValueError("非法路径")
    return full

[Requirement] 禁止使用 os.system / subprocess(shell=True) 执行含用户输入的命令,必须用 shell=False 并传列表参数。

# 正确
subprocess.run(["convert", input_path, output_path], shell=False, check=True)
 
# 错误:命令注入
os.system(f"convert {input_path} {output_path}")

[Standard] 服务端发起 HTTP 请求时,禁止请求内网地址(127.0.0.1、10.x、172.16-31.x、192.168.x、metadata 域名),需做内网黑名单校验。

[Caution] 禁止使用 pickle.loads / Java ObjectInputStream 反序列化不可信数据,应使用 JSON / Protobuf 等安全格式。


[Standard] 在 CI 流水线中集成静态代码扫描工具,扫描 SQL 注入、XSS、命令注入等漏洞。

语言工具
PythonBandit、Semgrep
JavaSpotBugs + FindSecBugs、SonarQube
JavaScriptESLint(security 规则)、Semgrep
Gogosec

[Default] 上线前对核心接口做渗透测试或使用 OWASP ZAP / Burp Suite 做动态扫描。

[Requirement] CI 中必须扫描第三方依赖漏洞(SCA):Python 用 pip-audit / safety,Node 用 npm audit / Snyk,Java 用 OWASP Dependency-Check。

[Requirement] 高危漏洞(CVSS ≥ 7.0)的依赖必须升级或打补丁,不允许上线。

[Requirement] 扫描发现的漏洞按严重级别分级处理:

级别处理时限责任人
严重(Critical)立即修复,阻断发布模块负责人
高危(High)3 个工作日内模块负责人
中危(Medium)7 个工作日内开发
低危(Low)下个迭代开发