按框架
Django 安全 — 生产环境加固实务参考
Django 生产环境加固参考:优先级清单,外加 DEBUG/ALLOWED_HOSTS、SECRET_KEY、pip CVE、生产环境安全配置、授权、注入与 SSRF。以防御为主,不含攻击步骤。
面向:在 Django 上运营应用的人。这里不讲攻击步骤——这是一份用于加固的实务参考:优先级排序的清单、分领域指引、以及自查。要看跨框架的全局,请参阅 按框架的安全防护入口。
优先级排序的加固清单
按此表自上而下执行。P0 是前提,P1 是最频繁的事故来源,P2 是持续的运营卫生。
P0 ── 前提(先做这个)
DEBUG=False + ALLOWED_HOSTS / 把 SECRET_KEY 外置 / 快速为 pip 依赖 CVE 打补丁
P1 ── 最主要的事故来源
生产环境安全配置(SSL/HSTS/Cookie)/ 授权(所有者范围)
P2 ── 运营卫生
注入与输出 / CSRF、会话、admin / SSRF、上传
| 优先级 | 控制项 | 具体做法(Django) |
|---|---|---|
| P0 | DEBUG/ALLOWED_HOSTS | 生产环境 DEBUG=False + 设置 ALLOWED_HOSTS。不暴露详细错误 |
| P0 | SECRET_KEY | 来自环境,不放在代码/仓库。泄露时轮换 |
| P0 | pip 依赖 CVE | 用 pip-audit / osv-scanner 监控;以运行中的版本判定,快速打补丁 |
| P1 | 生产环境安全配置 | SECURE_SSL_REDIRECT、SECURE_HSTS_SECONDS、SESSION_COOKIE_SECURE、CSRF_COOKIE_SECURE、SECURE_CONTENT_TYPE_NOSNIFF |
| P1 | 显式授权 | 需要登录 + 权限 + filter(user=request.user) 以做所有者范围 |
| P2 | 注入/输出 | 通过 ORM 绑定。避免 raw()/extra() 拼接。不要把输入传给 mark_safe/` |
| P2 | CSRF/会话/admin | 不要关闭 CSRF(默认)。限制 admin 的暴露 |
| P2 | SSRF/上传 | 服务端取回用允许列表 + 阻断内部 IP。校验上传,存放在公开面之外 |
1. DEBUG 与 ALLOWED_HOSTS(P0)
- 确保生产环境
DEBUG=False。开着时,错误页面会暴露配置、环境变量和堆栈跟踪,可通过故意触发错误来提取。 - 正确设置
ALLOWED_HOSTS,以防止在意料之外的主机名下运行。阻止详细错误对外显示。
2. SECRET_KEY(P0)
SECRET_KEY是签名 Cookie、会话、CSRF 令牌以及密码重置的根基。从环境变量或密钥管理服务加载它,而非代码/仓库。- 泄露时及时轮换。让它远离公开目录和 DEBUG 页面(→ 不要把密钥放进公开目录)。
3. pip 依赖 CVE(P0)
- 用 pip-audit 或 osv-scanner 机器监控已知 CVE,以运行中的版本判定,并快速打补丁(→ 监控依赖包的 CVE · 漏洞应对实务)。
- 让 Django 和 Python 保持在受支持的版本,不要放着 EOL 版本不管。
4. 生产环境安全配置(P1)
Django 的大量防御是通过 SecurityMiddleware 配置的。请为生产环境设置这些:
SECURE_SSL_REDIRECT(强制 HTTPS)·SECURE_HSTS_SECONDS(+INCLUDE_SUBDOMAINS/PRELOAD)SESSION_COOKIE_SECURE/CSRF_COOKIE_SECURE(仅 HTTPS 的 Cookie)SECURE_CONTENT_TYPE_NOSNIFF等- 运行
manage.py check --deploy以机械地暴露这些方面的缺口。
5. 授权(P1 — 最主要的来源)
常见(危险)
- 要求登录,但没有所有者范围
- queryset 查了全部,没有按 ID 过滤
- 依赖隐藏 URL / 难以猜测的 ID
- 在某些视图上忘了权限检查
正确
- 需要登录 + 显式的权限检查
- 读取也做所有者范围限定(如
filter(user=request.user)) - 在每一条读取/更新/删除路径上核验
- 授权显式构建,不交给默认值
参阅 IDOR 是什么。认证和授权是两回事;在靠近数据的地方做授权。
6. 注入与输出(P2)
- SQL:通过 ORM 绑定。不要用
raw()/extra()或字符串拼接构造查询(→ SQL 注入是什么)。 - XSS:模板默认自动转义。不要把用户输入传给
mark_safe/|safe(→ XSS 是什么)。 - 反序列化:不要加载不受信任的
pickle(可能导致代码执行)。
7. CSRF、会话、admin(P2)
- 不要关闭默认的 CSRF 防护(→ CSRF 是什么)。
- 限制 admin 的暴露(访问限制、更改 URL、多因素认证)。保留点击劫持防御(
X-Frame-Options默认)。 - 给会话应用 secure/httponly/samesite,并在登录时重新生成。
8. SSRF、上传、响应头(P2)
- 服务端取回用户提供的 URL 时,应把目标限制在允许列表,并阻断到内部 IP/元数据的访问(→ SSRF 是什么)。
- 校验上传(类型/大小),并存放在公开面之外。
- 用 安全响应头检查器 检查你自己站点的响应头。
验证:你的 Django 真的加固了吗
做完不算完——检查过才算完成。以下是针对你自己环境的防御性自查。
机械地检查缺口
python manage.py check --deploy,确认警告都已解决。生产环境不暴露 DEBUG
授权是否有效
密钥与依赖
SECRET_KEY 不在仓库里,且 pip-audit/osv 干净。本站的视角:开箱即用,但配置和授权仍归你自己
Django 默认守护了很多,但生产环境配置(DEBUG/SECRET_KEY/ALLOWED_HOSTS/SSL)和授权是你必须按环境、按应用逐一做对的东西。我们反复看到的事故,与其说是精巧的攻击,不如说是配置/运营层面的套路:“生产环境开着 debug”“某个密钥被暴露”“压根没有授权”。所以重心在于收紧生产环境配置、让密钥保持私密、并让授权显式化。把 check --deploy 纳入你的流程,是一条捷径。
接下来读
- 入口:按框架的安全防护 · Laravel 安全(生产环境 DEBUG / 密钥暴露的问题相似)
- 实操:漏洞应对实务 · 监控依赖包的 CVE · 不要把密钥放进公开目录
- 术语:IDOR 是什么 · SQL 注入 · XSS · CSRF · SSRF
- 工具:安全响应头检查器
FAQ
Q要保护 Django,第一步该做什么?
P0 的三件事:(1) 确保生产环境 DEBUG=False,并正确设置 ALLOWED_HOSTS;(2) 从环境加载 SECRET_KEY(不放在代码/仓库里),泄露时轮换;(3) 用机器监控 pip 依赖 CVE 并快速打补丁,以运行中的版本判定。接着再进入生产环境安全配置(SSL/HSTS/Cookie)与授权。manage.py check --deploy 能机械地暴露缺失的配置。
Q在生产环境放着 DEBUG=True 有什么危险?
开着 DEBUG,错误页面会显示详细内部信息——配置、环境变量、堆栈跟踪。攻击者可以故意触发错误来提取它们。在生产环境务必设置 DEBUG=False,并正确配置 ALLOWED_HOSTS。同时要阻止详细错误对外显示,并检查生产环境下的 static/media 服务方式。
Q为什么 SECRET_KEY 很重要?
SECRET_KEY 是签名 Cookie 和会话、CSRF 令牌以及密码重置的根基。一旦泄露,可能导致这些被伪造或篡改。不要放进代码或仓库——从环境变量或密钥管理服务加载,泄露时及时轮换。同时要防止它通过公开目录或 DEBUG 页面被暴露。
Q该检查哪些 Django 生产环境安全配置?
与 SecurityMiddleware 相关的那些:SECURE_SSL_REDIRECT(强制 HTTPS)、SECURE_HSTS_SECONDS(HSTS)、SESSION_COOKIE_SECURE / CSRF_COOKIE_SECURE(安全 Cookie)、SECURE_CONTENT_TYPE_NOSNIFF 等,都要按生产环境配置。运行 manage.py check --deploy 能机械地暴露这些方面的缺口。
Q如何管理 pip 依赖漏洞?
用 pip-audit 或 osv-scanner 机器监控已知 CVE,并以运行中的版本判定,快速打补丁。让 Django 和 Python 保持在受支持的版本,不要放着 EOL 版本不管。依赖的新鲜度,比精巧的攻击更能左右事故的成败。