现在比较流行的网站攻击方式有sql注入,xss跨站脚本攻击,csrf跨站请求伪造,一句话木马等等

django非常强大,对这些攻击都做了防范

sql注入,通过在sql语句中插入非法的sql语句来实现爆库。在django中,封装了models模型对象,一般来说不用担心sql注入。除非使用了MySQLdb模块,用传统的方法进行数据库的查询等操作。

django的模板系统默认提供了转意功能,传到html文件里面的变量是经过转意的,一般来说不需要担心xss。

如果你正在编写一个模板而不知道是否要关闭自动转意,那就为所有需要转意的变量添加一个escape过滤器。 当自动转意开启时,使用escape过滤器似乎会两次转意数据,但其实没有任何危险。因为escape过滤器不作用于被转意过的变量。

{{ test|escape }}

如果想关闭自动转意可以使用safe过滤器

{{ test|safe }}

如果是很多变量可以使用

标签autoescape来包装整个模板

Auto-escaping is on by default. Hello {{ name }}

{% autoescape off %}
    This will not be auto-escaped: {{ data }}.

    Nor this: {{ other_data }}
    {% autoescape on %}
        Auto-escaping applies again: {{ name }}
    {% endautoescape %}
{% endautoescape %}

on是开启转意,off是关闭转意

django中的setting里面INSTALL_APP里面有

django.middleware.csrf.CsrfViewMiddleware模块,可以对CSRF进行防范

CSRF 防护

django.contrib.csrf 开发包能够防止遭受跨站请求伪造攻击 (CSRF).

CSRF, 又叫会话跳转,是一种网站安全攻击技术。 当某个恶意网站在用户未察觉的情况下将其从一个已经通过身份验证的站点诱骗至一个新的 URL 时,这种攻击就发生了,因此它可以利用用户已经通过身份验证的状态。 乍一看,要理解这种攻击技术比较困难,因此我们在本节将使用两个例子来说明。

一个简单的 CSRF 例子

example.com/logout。

example.com .

很明显,登出一个邮件网站也不是什么严重的安全问题。但是同样的攻击可能针对任何相信用户的站点,比如在线银行和电子商务网站。这样的话可能在用户不知情的情况下就下订单付款了。

稍微复杂一点的CSRF例子

POST方法进行状态变更操作也易受到 CSRF 攻击。

<form> 中加入了以下隐藏的字段:

<input type="hidden" name="confirm" value="true">

confirm。

<iframe> 中,然后使用 Javascript 自动提交该表单。

防止 CSRF

<iframe> ,它将不会产生负面效果。

POST 的form标签一个隐藏字段,它的值是保密的并根据用户进程的 ID 生成。 这样,从服务器端访问表单时,可以检查该保密的字段。不吻合时可以引发一个错误。

这正是 Django CSRF 防护层完成的工作,正如下面的小节所介绍的。

使用CSRF中间件

CsrfMiddleware ,该类实现了 CSRF 防护功能。

MIDDLEWARE_CLASSES设置中,你就完成了工作。 参见第十五章的“MIDDLEWARE_CLASSES顺序”小节以了解更多。

CsrfMiddleware 的工作模式。 它完成以下两项工作:

  1. csrfmiddlewaretoken ,值为当前会话 ID 加上一个密钥的散列值。 如果未设置会话 ID ,该中间件将 不会 修改响应结果,因此对于未使用会话的请求来说性能损失是可以忽略的。

  1. HTTP 错误。 403 错误页面的内容是检测到了跨域请求伪装。 终止请求。 

该步骤确保只有源自你的站点的表单才能将数据 POST 回来。

GET 请求而产生负面效应,你必须自己来确保这一点。

POST 请求无法受到保护,但它们也不 需要 受到保护,因为恶意网站可用任意方法来制造这种请求。

application/xml+xhtml 的页面才会被修改。

CSRF中间件的局限性

CsrfMiddleware 的运行需要 Django 的会话框架。 (参阅第 14 章了解更多关于会话的内容。)如果你使用了自定义会话或者身份验证框架手动管理会话 cookies,该中间件将帮不上你的忙。

csrfmiddlewaretoken是否插入到了表单中。

http://en.wikipedia.org/wiki/CSRF 。

总结一下如何django防范CSRF

django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

全局:

中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。

@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

注意:from django.views.decorators.csrf import csrf_exempt,csrf_protect

默认setting文件中

MIDDLEWARE里的django.contrib.csrf.middleware.CsrfMiddleware是开启的

我们需要在视图函数中使用render传入request和模板,然后在html表单里面加上{% csrf_token %}即可开启csrf防御

 

Internet并不安全。

现如今,每天都会出现新的安全问题。 我们目睹过病毒飞速地蔓延,大量被控制的肉鸡作为武器来攻击其他人,与垃圾邮件的永无止境的军备竞赛,以及许许多多站点被黑的报告。

作为Web开发人员,我们有责任来对抗这些黑暗的力量。 每一个Web开发者都应该把安全看成是Web编程中的基础部分。 不幸的是,要实现安全是困难的。

Django试图减轻这种难度。 它被设计为自动帮你避免一些web开发新手(甚至是老手)经常会犯的错误。 尽管如此,需要弄清楚,Django如何保护我们,以及我们可以采取哪些重要的方法来使得我们的代码更加安全。

首先,一个重要的前提: 我们并不打算给出web安全的一个详尽的说明,因此我们也不会详细地解释每一个薄弱环节。 在这里,我们会给出Django所面临的安全问题的一个大概。

Web安全现状

如果你从这章中只学到了一件事情,那么它会是:

在任何条件下都不要相信浏览器端提交的数据。

你从不会知道HTTP连接的另一端会是谁。 可能是一个正常的用户,但是同样可能是一个寻找漏洞的邪恶的骇客。

从浏览器传过来的任何性质的数据,都需要近乎狂热地接受检查。 这包括用户数据(比如Web表单提交的内容)和带外数据(比如,HTTP头、cookies以及其他信息)。 要修改那些浏览器自动添加的元数据,是一件很容易的事。

在这一章所提到的所有的安全隐患都直接源自对传入数据的信任,并且在使用前不加处理。 你需要不断地问自己,这些数据从何而来。

SQL注入

POST 数据或者URL地址),加入一些其他的SQL片段。 未加处理的网站会将这些信息在后台数据库直接运行。

这种危险通常在由用户输入构造SQL语句时产生。 例如,假设我们要写一个函数,用来从通信录搜索页面收集一系列的联系信息。 为防止垃圾邮件发送器阅读系统中的email,我们将在提供email地址以前,首先强制用户输入用户名。

def user_contacts(request):
    user = request.GET['username']
    sql = "SELECT * FROM user_contacts WHERE username = '%s';" % username
    # execute the SQL here...

备注

在这个例子中,以及在以下所有的“不要这样做”的例子里,我们都去除了大量的代码,避免这些函数可以正常工作。 我们可不想这些例子被拿出去使用。

尽管,一眼看上去,这一点都不危险,实际上却不尽然。

 。 此时,查询的字符串会构造如下:

SELECT * FROM user_contacts WHERE username = '' OR 'a' = 'a';

OR 子句,使得每一行数据都被返回。

 ,我们最终将得到这样的查询:

SELECT * FROM user_contacts WHERE username = ''; DELETE FROM user_contacts WHERE 'a' = 'a';

哦!我们整个通信录名单去哪儿了? 我们整个通讯录会被立即删除

解决方案

尽管这个问题很阴险,并且有时很难发现,解决方法却很简单: 绝不信任用户提交的数据,并且在传递给SQL语句时,总是转义它。

Django的数据库API帮你做了。 它会根据你所使用的数据库服务器(例如PostSQL或者MySQL)的转换规则,自动转义特殊的SQL参数。

举个例子,在下面这个API调用中:

foo.get_list(bar__exact="' OR 1=1")

Django会自动进行转义,得到如下表达:

SELECT * FROM foos WHERE bar = '\' OR 1=1'

完全无害。

这被运用到了整个Django的数据库API中,只有一些例外:

  • where 参数。 (参考 附录 C。) 这个参数故意设计成可以接受原始的SQL。

  • 使用底层数据库API的查询。 (详见第十章)

以上列举的每一个示例都能够很容易的让您的应用得到保护。 在每一个示例中,为了避免字符串被篡改而使用 绑定参数 来代替。这样,本节开始的例子应该写成这样:

from django.db import connection

def user_contacts(request):
    user = request.GET['username']
    sql = "SELECT * FROM user_contacts WHERE username = %s"
    cursor = connection.cursor()
    cursor.execute(sql, [user])
    # ... do something with the results

execute 方法采用了一个SQL字符串作为其第二个参数,这个SQL字符串包含若干’%s’占位符,execute方法能够自动对传入列表中的参数进行转义和插入。 你应该用* always* 这种方式构造自定义的SQL。

django.db.backend.quote_name ,这个函数能够根据当前数据库引用结构对这些标识符进行转义。

跨站点脚本 (XSS)

<script> 标签形式的任意HTML代码。

攻击者通常利用XSS攻击来窃取cookie和会话信息,或者诱骗用户将其私密信息透漏给被人(又称 钓鱼 )。

这种类型的攻击能够采用多种不同的方式,并且拥有几乎无限的变体,因此我们还是只关注某个典型的例子吧。 让我们来想想这样一个极度简单的Hello World视图:

from django.http import HttpResponse

def say_hello(request):
    name = request.GET.get('name', 'world')
    return HttpResponse('<h1>Hello, %s!</h1>' % name)

http://example.com/hello/?name=Jacob ,被呈现的页面将会包含一以下这些:

<h1>Hello, Jacob!</h1>

http://example.com/hello/?name=<i>Jacob</i> 时又会发生什么呢?

<h1>Hello, <i>Jacob</i>!</h1>

当然,一个攻击者不会使用<i>标签开始的类似代码,他可能会用任意内容去包含一个完整的HTML集来劫持您的页面。 这种类型的攻击已经运用于虚假银行站点以诱骗用户输入个人信息,事实上这就是一种劫持XSS的形式,用以使用户向攻击者提供他们的银行帐户信息。

如果您将这些数据保存在数据库中,然后将其显示在您的站点上,那么问题就变得更严重了。 例如,一旦MySpace被发现这样的特点而能够轻易的被XSS攻击,后果不堪设想。 某个用户向他的简介中插入JavaScript,使得您在访问他的简介页面时自动将其加为您的好友,这样在几天之内,这个人就能拥有上百万的好友。 在几天的时间里,他拥有了数以百万的朋友。

现在,这种后果听起来还不那么恶劣,但是您要清楚——这个攻击者正设法将  的代码而不是MySpace的代码运行在  的计算机上。 这显然违背了假定信任——所有运行在MySpace上的代码应该都是MySpace编写的,而事实上却不如此。

MySpace是极度幸运的,因为这些恶意代码并没有自动删除访问者的帐户,没有修改他们的密码,也并没有使整个站点一团糟,或者出现其他因为这个弱点而导致的其他噩梦。

解决方案

解决方案是简单的: 总是转义可能来自某个用户的任何内容。

为了防止这种情况,Django的模板系统自动转义所有的变量值。 让我们来看看如果我们使用模板系统重写我们的例子会发生什么

# views.py

from django.shortcuts import render_to_response

def say_hello(request):
    name = request.GET.get('name', 'world')
    return render_to_response('hello.html', {'name': name})

# hello.html

<h1>Hello, {{ name }}!</h1>

http://example.com/hello/name=Jacob`` 的请求将导致下面的页面:

<h1>Hello, &lt;i&gt;Jacob&lt;/i&gt;!</h1>

我们在第四章涵盖了Django的自动转义,一起想办法将其关闭。 甚至,如果Django真的新增了这些特性,您也应该习惯性的问自己,一直以来,这些数据都来自于哪里呢? 没有哪个自动解决方案能够永远保护您的站点百分之百的不会受到XSS攻击。

伪造跨站点请求

伪造跨站点请求(CSRF)发生在当某个恶意Web站点诱骗用户不知不觉的从一个信任站点下载某个URL之时,这个信任站点已经被通过信任验证,因此恶意站点就利用了这个被信任状态。

16章

会话伪造/劫持

这不是某个特定的攻击,而是对用户会话数据的通用类攻击。 这种攻击可以采取多种形式:

中间人 攻击:检索所在有线(无线)网络,监听会话数据。

伪造会话 :攻击者利用会话ID(可能是通过中间人攻击来获得)将自己伪装成另一个用户。

这两种攻击的一个例子可以是在一间咖啡店里的某个攻击者利用店内的无线网络来捕获某个会话cookie,然后她就可以利用那个cookie来假冒原始用户。 她便可以使该cookie来模拟原始用户。

伪造cookie :就是指某个攻击者覆盖了在某个cookie中本应该是只读的数据。 ` 第十四章 <../chapter14/>`__ 详细介绍了cookies如何工作,以及要点之一的是,它在你不知道的情况下无视浏览器和恶意用户私自改变cookies。

LoggedInAsUser=jacob 这样的方式来保存cookie由来已久,使用这样的cookie是再简单不过的了。

一个更微妙的层面上,然而,相信在cookies中存储的任意信息绝对不是一个好主意。 你永远不知道谁一直在作怪。

会话滞留 :攻击者诱骗用户设置或者重设置该用户的会话ID。

http://example.com/?PHPSESSID=fa90197ca25f6ab40bb1374c510d7a32 等)中传递会话标识符。攻击者欺骗用户点击一个硬编码会话ID的链接,这回导致用户转到那个会话。

会话滞留已经运用在钓鱼攻击中,以诱骗用户在攻击者拥有的账号里输入其个人信息。 他可以稍后登陆账户并且检索数据。

会话中毒 :攻击者通过用户提交设置会话数据的Web表单向该用户会话中注入潜在危险数据。

一个经典的例子就是一个站点在某个cookie中存储了简单的用户偏好(比如一个页面背景颜色)。 攻击者可以诱骗用户点击一个链接来提交背景颜色,实际上包含了一个XSS攻击。 如果颜色没有转义,那么就可以再把恶意代码注入到用户环境中。

解决方案

有许多基本准则能够保护您不受到这些攻击:

不要在URL中包含任何session信息。

Django的session框架(参见` 第十四章 <../chapter14/>`__ )根本不会容许session包含在URL中。

不要直接在cookie中保存数据。 相反,存储一个在后台映射到session数据存储的session ID。

request.session ),它会自动进行处理。 这个session框架仅在cookie中存储一个session ID,所有的session数据将会被存储在数据库中。

如果需要在模板中显示session数据,要记得对其进行转义。 可参考之前的XSS部分,对所有用户提交的数据和浏览器提交的数据进行转义。 对于session信息,应该像用户提交的数据一样对其进行处理。

任何可能的地方都要防止攻击者进行session欺骗。

尽管去探测究竟是谁劫持了会话ID是几乎不可能的事儿,Django还是内置了保护措施来抵御暴力会话攻击。 会话ID被存在哈希表里(取代了序列数字),这样就阻止了暴力攻击,并且如果一个用户去尝试一个不存在的会话那么她总是会得到一个新的会话ID,这样就阻止了会话滞留。

True ,这样就能够使Django只通过HTTPS发送会话cookie。

邮件头部注入

邮件头部注入 :SQL注入的兄弟,是一种通过劫持发送邮件的Web表单的攻击方式。 攻击者能够利用这种技术来通过你的邮件服务器发送垃圾邮件。 在这种攻击面前,任何方式的来自Web表单数据的邮件头部构筑都是非常脆弱的。

让我们看看在我们许多网站中发现的这种攻击的形式。 通常这种攻击会向硬编码邮件地址发送一个消息,因此,第一眼看上去并不显得像面对垃圾邮件那么脆弱。

但是,大多数表单都允许用户输入自己的邮件主题(同时还有from地址,邮件体,有时还有部分其他字段)。 这个主题字段被用来构建邮件消息的主题头部。

 是换行符)的东西。 这有可能使得所构建的邮件头部变成:

To: hardcoded@example.com
Subject: hello
cc: spamvictim@example.com

就像SQL注入那样,如果我们信任了用户提供的主题行,那样同样也会允许他构建一个头部恶意集,他也就能够利用联系人表单来发送垃圾邮件。

解决方案

我们能够采用与阻止SQL注入相同的方式来阻止这种攻击: 总是校验或者转义用户提交的内容。

django.core.mail.send_mail 来处理包含换行符的主题时,Django将会抛出BadHeaderError异常。

SateMIMEText 类来看看Django是如何做到这一点的。

目录遍历

目录遍历 :是另外一种注入方式的攻击,在这种攻击中,恶意用户诱骗文件系统代码对Web服务器不应该访问的文件进行读取和/或写入操作。

例子可以是这样的,某个视图试图在没有仔细对文件进行防毒处理的情况下从磁盘上读取文件:

def dump_file(request):
    filename = request.GET["filename"]
    filename = os.path.join(BASE_PATH, filename)
    content = open(filename).read()

    # ...

../../../../../etc/passwd。

任何不做适当转义地读取文件操作,都可能导致这样的问题。 允许  操作的视图同样容易发生问题,而且结果往往更加可怕。

http://example.com/person/poke/1 这样的URL直接加载模块和调用函数。 结果是,精心构造的URL,可以自动地调用任意的代码,包括数据库的清空脚本。

解决方案

如果你的代码需要根据用户的输入来读写文件,你就需要确保,攻击者不能访问你所禁止访问的目录。

备注

不用多说,你 永远 不要在编写可以读取任何位置上的文件的代码!

django.views.static 中)。这是相关代码:

import os
import posixpath

# ...

path = posixpath.normpath(urllib.unquote(path))
newpath = ''
for part in path.split('/'):
    if not part:
        # strip empty path components
        continue

    drive, part = os.path.splitdrive(part)
    head, part = os.path.split(part)
    if part in (os.curdir, os.pardir):
        # strip '.' and '..' in path
        continue

    newpath = os.path.join(newpath, part).replace('\\', '/')

static.serve 函数,但也受到了上面这段代码的保护),因此这种危险对于核心代码的影响就要小得多。

更进一步,URLconf抽象层的使用,意味着不经过你明确的指定,Django 决不会 装载代码。 通过创建一个URL来让Django装载没有在URLconf中出现的东西,是不可能发生的。

暴露错误消息

在开发过程中,通过浏览器检查错误和跟踪异常是非常有用的。 Django提供了漂亮且详细的debug信息,使得调试过程更加容易。

然而,一旦在站点上线以后,这些消息仍然被显示,它们就可能暴露你的代码或者是配置文件内容给攻击者。

还有,错误和调试消息对于最终用户而言是毫无用处的。 Django的理念是,站点的访问者永远不应该看到与应用相关的出错消息。 如果你的代码抛出了一个没有处理的异常,网站访问者不应该看到调试信息或者 任何 代码片段或者Python(面向开发者)出错消息。 访问者应该只看到友好的无法访问的页面。

当然,开发者需要在debug时看到调试信息。 因此,框架就要将这些出错消息显示给受信任的网站开发者,而要向公众隐藏。

解决方案

正如我们在第12章所提到的,Django的`` DEBUG`` 设置控制这些错误信息的显示。 当你准备部署时请确认把这个设置为:`` False`` 。

Off 选项,这个会在Django被加载以前去除出错消息。

安全领域的总结

我们希望关于安全问题的讨论,不会太让你感到恐慌。 Web是一个处处布满陷阱的世界,但是只要有一些远见,你就能拥有安全的站点。

永远记住,Web安全是一个不断发展的领域。如果你正在阅读这本书的停止维护的那些版本,请阅读最新版本的这个部分来检查最新发现的漏洞。 事实上,每周或者每月花点时间挖掘Web应用安全,并且跟上最新的动态是一个很好的主意。 花费很少,但是对你网站和用户的保护确是无价的。

 

摘自django book2.0中文版第二十章安全

相关文章:

  • 2021-10-25
  • 2021-11-24
  • 2021-06-16
  • 2022-12-23
  • 2022-02-23
  • 2022-12-23
猜你喜欢
  • 2021-11-16
  • 2021-08-12
  • 2022-12-23
  • 2021-08-31
  • 2021-06-20
相关资源
相似解决方案