Django 1.6 最佳实践: 服务器和代码安全 (1)

在我们的博客中, 记录了我们在开发过程中所使用的技术和遇到的问题, 希望作为其他开发和设计者的一个学习交流平台.

Django 1.6 最佳实践: 服务器和代码安全 (1)


django自身提供的安全相关的工具, 文档, 核心代码使django一直保持着不错的安全记录. 当然这也需要django的开发人员了解和掌握着这些工具才能做到.

本篇中包含了一些使Django项目更安全的基本信息.

1. 服务器安全

要确保django项目的安全, 首先需要阙波服务器的安全. 服务器的安全涉及的范围太广, 在这里不做深入讨论. 如果你使用的是Ubuntu 12.04, 那可以参考一下这篇文章.

2. 了解Django安全特性

django 1.6自身的安全特性包括:

  • Cross-site scripting (XSS) 保护
  • Cross-site request forgery (CSRF) 保护
  • SQL 注入保护
  • Clickjacking 保护
  • 支持 SSL/HTTPS 和安全 cookies
  • 默认密码储存使用 PBKDF2 算法和 SHA256 hash
  • 自动 HTML escaping
  • 针对 XML bomb 攻击优化的分析器
  • 加强的JSON, YAML, XML 序列化/去序列化工具

大多数Django的安全特性不需要开启即可工作. 但还有一些需要我们加以设置才行. 在我们重点讲一下这些需要设置的安全特性前, 请先阅读django官网的安全专题: https://docs.djangoproject.com/en/1.6/topics/security/.

3. 关闭DEBUG

正式服务器上运行的django项目应当设置DEBUG=False. 这样, 不法分子便无法从debug信息中找到对他们有用的信息.

在设置DEBUG=False后, 一定要正确设置ALLOWED_HOSTS, 避免出现 SuspiciousOperation 错误.

4. 妥善保管Security keys

如果侵入者获得了django的security key, 那么就意味着你将会冒更多的安全风险. API key和其他信息也应当妥善保管, 并不要放入版本管理系统中.

具体的做法可以参见之前的博文, Django 1.6 最佳实践: 如何设置django项目的设置(settings.py)和部署文件(requirements.txt)中的 2. 将关键信息和设置文件分离..

5. 使用HTTPS

如果有必要, 可以选择使用HTTPS. 但是Static资源还是应该以http传输, 否则用户可能会得到"insecure resources"警告.

如果用户使用http访问, 应该将他们导向https. 我们可以通过设置web server或django middleware完成. 我们偏向于使用web server完成这一设置. 如果想使用middleware的话, 我们推荐 django-sslify 或 django-secure, django-sslify只是将http连接导向https, 而django-secure则能检查项目中的其他安全设置.

当然, 在设置https之前, 你需要从正规的聚到购买SSL证书.

使用安全cookies

你的项目应当能通知浏览器使用安全cookies, 即永远不通过http传输cookies. 在settings.py中:

    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True

使用HSTS

HSTS全称HTTP Strict Transport Security, 通常是通过web server设置的.

当开启HSTS后, 页面传输时的response会包含一个HTTP头部, 通知HSTS兼容的浏览器网站只接受HTTPS. 然后HSTS兼容的浏览器会重定向HTTP到HTTPS. 如果HTTPS无法连通, 连接则会中断.

    Strict-Transport_security: max-age=3153600; includeSubDomains

一些设置HSTS的建议:

  • 设置includeSubDomains mode能阻止入侵者利用未加密的次域名的cookies入侵主站.
  • 开始时设置一个小的max-age, 例如3600(一小时). 因为一旦设置好了之后, 你无法重置用户浏览器中的记录.
  • 确定一切都ok之后, 再将max-age设置为3153600(12个月)或63072000(24个月).

6. 使用ALLOWED_HOSTS

在django 1.6中提供了ALLOWED_HOSTS设置, 只允许列出的host和domain传输. 如果没有设置的话, 会出现SuspiciousOperation. 这是django为了避免假HTTP host 头部而设计的. 我们建议不要再ALLOWED_HOSTS中使用通配符.

7. 开启CSRF保护

django自身带有的csrf保护十分好用, 当在开发时没有开启的话, 甚至会给出提示. 我们推荐一直开启该保护, 除非在创建机器访问的API时, 像Django-rest-framework和django-tastypie都提供该功能. 因为每个API请求都必须提供验证信息, 这两个framework不依赖HTTP cookies来验证. 所以在使用这些framework时CSRF保护并不是问题.

在AJAX post数据时也应当使用CSRF保护, 此时你需要设置X-CSRFToken HTTP头部. django官方文档给了我们一段示范代码: https://docs.djangoproject.com/en/1.6/ref/contrib/csrf/#ajax. 也可以参见之前的博文: Django 1.6 最佳实践: 如何在 Django Template 中正确使用 REST API的4. AJAX和CSRF.

8. XSS 攻击

当用户引入有攻击性的JavaScript, 并直接在template中呈现时, 会存在XSS攻击. 万幸的是, django会自动屏蔽<, >, ', "" 和 &. 但我们还是建议:

  • 不使用mark_safe来跳过template默认机制
  • 不要允许用户设置HTML tag attribute (属性)
  • 使用JSON encoding, 而不直接呈现python结构

9. 地方python注入攻击

有时, 我们会执行python的eval()直接从数据库中读取python dict. 如果数据库中含有有危险的python代码, 那么这一代吗就可能随时随地被执行. 因此我们必须小心一下情况:

  • python自带的eval(), exec()和execfile(), 因为如果有危害代码传入这些方法中, 则会给系统能够很大的安全隐患.
  • python标准库中能执行命令的代码, 例如使用pickle将用户提供的信息去序列化操作.
  • python第三方模块中能执行命令的代码, 例如使用PyYAML时, 应该使用safe_load().而不是load()

小心cookie-based session

通常django项目都使用database-based或cache-based session, 这些session都是将一个值存在cookie中, 然后通过该值获取真正的session信息. 这样做的好处是, 只有一个值传给用户, 使黑客想要绕过django的session机制变得困难.

但是django session也可以设置成cookie-based, 这就意味着session的数据完全是存在用户的cookie中, 也会导致:

  • 用户可以看到session的内容
  • 如果黑客获得了SECRET_KEY, 并且session数据是JSON-based的, 那么黑客便能创建假的session数据
  • 如果黑客获得了SECRET_KEY, 并且session数据是pickle-based的, 那么黑客不仅能创建假的session数据, 还能执行恶意代码.

另外需要考虑的是, cookie-based session的数据是存在用户端的, 用户和服务器之间的数据传输可能会消耗过多的带宽, 从而导致瓶颈产生.

总之, 应尽量避免使用cookie-based session.


原文链接: http://www.weiguda.com/blog/35/