安全注意事项¶
Web 应用通常面临所有种类的安全问题,并且很难把所有事做的正确。 Flask 试图 为你解决这些事情中的一些,但你仍需要关心更多的问题。
跨站脚本(XSS)¶
跨站脚本攻击的概念是在一个网站的上下文中注入任意的 HTML (以及附带的 JavaScript )。 开发者需要正确地转义文本,使其不能包含任意 HTML 标签来避免 这种攻击。 有关详细信息,请参阅有关跨网站脚本的维基百科文章。
Flask 配置 Jinja2 自动转义所有值,除非显式地指明不转义。 这就排除了模板导 致的所有 XSS 问题,但是你仍需要在其它的地方小心:
- 生成 HTML 而不使用 Jinja2
- 在用户提交的数据上调用了
Markup
- 从上传的文件发出HTML,从不这样做,请使用
Content-Disposition: 附件
- 发送上传的文本文件。 一些浏览器使用基于开头几个字节的 content-type 猜测,所以用户可能欺骗浏览器执行 HTML
另一件非常重要的事情是未用引号包裹的属性。 虽然 Jinja2 可以通过转义 HTML 来保护你免受 XSS 问题,仍有一种情况,它不能保护你: 属性注入的 XSS 。 为了 应对这种攻击媒介,确保当在属性中使用 Jinja 表达式时,始终用单引号或双引号 包裹属性:
<a href="{{ href }}">the text</a>
为什么这是必要的? 因为如果你不这么做,攻击者可以容易地注入自制的 JavaScript 处理器。 譬如一个攻击者可以注入这段 HTML+JavaScript:
onmouseover=alert(document.cookie)
当用户鼠标经过这个链接, 会在警告窗口里把 cookie 显示给用户。 一个精明的 攻击者可能也会执行其它的 JavaScript 代码,而不是把 cookie 显示给用户。 同 CSS 注入联系在一起,攻击者甚至使得元素填满整个页面,这样用户鼠标在页面 上的任何地方都会触发攻击。
跨站点请求伪造(CSRF)¶
另一个大问题是 CSRF 。 这是一个非常复杂的话题,我不会在此详细介绍,而只会 提及 CSRF 是什么和理论上如何避免它。
如果你的验证信息存储在 cookie 中,你有隐式的状态管理。 “已登入”状态由一个 cookie 控制,并且这个 cookie 在每个页面的请求中都会发送。 不幸的是,在第三 方站点触发的请求中也会发送这个 cookie 。 如果你不注意这点,一些人可能会通过 社会工程学来诱导你应用的用户在他们不知道的情况下做一些蠢事。
假设您有一个特定网址,当您发送POST
请求时,将删除用户的个人资料(例如http://example.com/user/delete
)。 如果一个攻击者现在创造一个页面来用 JavaScript 发送这个 post 请求,他们只是诱骗一些用户加载那个页面,而他们 的资料最终会被删除。
想象你在运行 Facebook ,有数以百万计的并发用户,并且某人放出一些小猫图片 的链接。 当用户访问那个页面欣赏毛茸茸的猫的图片时,他们的资料就被删除。
你怎么能防止这种情况? 基本上,对于每个修改服务器上内容的请求,你应该使用 一次性令牌,并存储在 cookie 里, 并且 在发送表单数据的同时附上它。 在服务器再次接收数据之后,你要比较两个令牌,并确保它们相等。
为什么 Flask 没有为你这么做? 理想情况下,这应该是表单验证框架做的事,而 Flask 中并不存在表单验证。