安全注意事项 — Flask 文档
安全注意事项
Web 应用程序通常会面临各种安全问题,而且很难让一切都正确。 Flask 尝试为您解决其中的一些问题,但还有一些您必须照顾好自己。
跨站脚本 (XSS)
跨站点脚本是将任意 HTML(以及 JavaScript)注入网站上下文的概念。 为了解决这个问题,开发人员必须正确地转义文本,使其不能包含任意的 HTML 标签。 有关更多信息,请查看关于 跨站点脚本 的维基百科文章。
Flask 将 Jinja2 配置为自动转义所有值,除非另有明确说明。 这应该可以排除模板中引起的所有 XSS 问题,但还有其他地方需要注意:
- 不借助 Jinja2 生成 HTML
- 对用户提交的数据调用
Markup
- 从上传的文件发送 HTML,永远不要这样做,使用
Content-Disposition: attachment
标头来防止这个问题。 - 从上传的文件发送文本文件。 一些浏览器使用基于前几个字节的内容类型猜测,因此用户可以欺骗浏览器执行 HTML。
另一件非常重要的事情是未引用的属性。 虽然 Jinja2 可以通过转义 HTML 来保护您免受 XSS 问题的影响,但它无法保护您免受一件事:通过属性注入来防止 XSS。 为了应对这种可能的攻击向量,请确保在其中使用 Jinja 表达式时始终使用双引号或单引号引用您的属性:
为什么这是必要的? 因为如果您不这样做,攻击者可以轻松注入自定义 JavaScript 处理程序。 例如,攻击者可以注入这段 HTML+JavaScript:
当用户随后将鼠标移到输入上时,cookie 将在警告窗口中呈现给用户。 但是,一个好的攻击者可能会执行任何其他 JavaScript 代码,而不是向用户显示 cookie。 结合 CSS 注入,攻击者甚至可能使元素填满整个页面,这样用户只需将鼠标放在页面上的任何位置即可触发攻击。
Jinja 的转义无法防止一类 XSS 问题。 a
标签的 href
属性可以包含 javascript: URI,如果未正确保护,浏览器将在点击时执行该 URI。
为了防止这种情况,您需要设置 内容安全策略 (CSP) 响应标头。
跨站请求伪造 (CSRF)
另一个大问题是CSRF。 这是一个非常复杂的话题,我不会在这里详细概述它,只提及它是什么以及如何从理论上防止它。
如果您的身份验证信息存储在 cookie 中,则您具有隐式状态管理。 “正在登录”的状态由 cookie 控制,并且该 cookie 与每个请求一起发送到页面。 不幸的是,这包括由 3rd 方网站触发的请求。 如果您不牢记这一点,有些人可能会用社交工程欺骗您的应用程序用户,在他们不知情的情况下做一些愚蠢的事情。
假设您有一个特定的 URL,当您向其发送 POST
请求时,将删除用户的个人资料(例如 http://example.com/user/delete
)。 如果攻击者现在使用一些 JavaScript 创建一个向该页面发送 post 请求的页面,他们只需要欺骗一些用户加载该页面,他们的个人资料最终将被删除。
想象一下,您要与数百万并发用户一起运行 Facebook,有人会发送指向小猫图像的链接。 当用户访问该页面时,他们的个人资料会在他们查看毛茸茸的猫的图像时被删除。
你怎么能防止呢? 基本上,对于修改服务器上内容的每个请求,您都必须使用一次性令牌并将其存储在 cookie 和 中,并将其与表单数据一起传输。 再次收到服务器上的数据后,您必须比较两个令牌并确保它们相等。
为什么 Flask 不为你做这些? 发生这种情况的理想场所是表单验证框架,它在 Flask 中不存在。
JSON 安全
在 Flask 0.10 及更低版本中,jsonify()
没有将顶级数组序列化为 JSON。 这是因为 ECMAScript 4 中存在安全漏洞。
ECMAScript 5 关闭了这个漏洞,所以只有极旧的浏览器仍然容易受到攻击。 所有这些浏览器都有 其他更严重的漏洞 ,所以这种行为已经改变,jsonify()
现在支持序列化数组。
安全标头
浏览器识别各种响应头以控制安全性。 我们建议您查看以下每个标题以在您的应用程序中使用。 Flask-Talisman 扩展可用于为您管理 HTTPS 和安全标头。
HTTP 严格传输安全 (HSTS)
告诉浏览器将所有 HTTP 请求转换为 HTTPS,防止中间人 (MITM) 攻击。
内容安全策略 (CSP)
告诉浏览器它可以从哪里加载各种类型的资源。 应尽可能使用此标头,但需要一些工作来为您的站点定义正确的策略。 一个非常严格的政策是:
- https://csp.withgoogle.com/docs/index.html
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
X-Content-Type-Options
强制浏览器接受响应内容类型,而不是尝试检测它,这可能会被滥用以生成跨站点脚本 (XSS) 攻击。
X-Frame-Options
防止外部网站将您的网站嵌入 iframe
。 这可以防止一类攻击,其中外框的点击可以无形地转换为对页面元素的点击。 这也称为“点击劫持”。
X-XSS-保护
如果请求包含类似 JavaScript 的内容并且响应包含相同的数据,浏览器将尝试通过不加载页面来防止反射型 XSS 攻击。
HTTP 公钥固定 (HPKP)
这会告诉浏览器仅使用特定的证书密钥向服务器进行身份验证,以防止 MITM 攻击。
警告
启用此功能时要小心,因为如果您错误地设置或升级密钥,将很难撤消。
复制/粘贴到终端
隐藏字符,如退格字符 (\b
、^H
) 可能导致文本在 HTML 中呈现与将 粘贴到终端 时的解释方式不同。
例如,import y\bose\bm\bi\bt\be\b
在 HTML 中呈现为 import yosemite
,但在粘贴到终端时应用退格键,变成 import os
。
如果您希望用户从您的站点复制和粘贴不受信任的代码,例如用户在技术博客上发表的评论,请考虑应用额外的过滤,例如替换所有 \b
字符。
大多数现代终端在粘贴时都会警告并删除隐藏字符,因此这不是绝对必要的。 也可以以其他无法过滤的方式制作危险命令。 根据您网站的使用案例,通常显示有关复制代码的警告可能会很好。