zoukankan      html  css  js  c++  java
  • Django自身安全机制-XSS和CSRF

    XSS攻击

    什么是XSS攻击

    XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。比如这些代码包括HTML代码和客户端脚本。攻击者利用XSS漏洞旁路掉访问控制——例如同源策略(same origin policy)。这种类型的漏洞由于被黑客用来编写危害性更大的网络钓鱼(Phishing)攻击而变得广为人知。对于跨站脚本攻击,黑客界共识是:跨站脚本攻击是新型的“缓冲区溢出攻击“,而JavaScript是新型的“ShellCode”。
     

    实施XSS攻击需要具备两个条件:

      一、需要向web页面注入恶意代码;

      二、这些恶意代码能够被浏览器成功的执行。

    解决办法:

      1、一种方法是在表单提交或者url参数传递前,对需要的参数进行过滤。
      2、在后台对从数据库获取的字符串数据进行过滤,判断关键字。
      3、设置安全机制。
      django框架:内部机制默认阻止了。它会判定传入的字符串是不安全的,就不会渲染而以字符串的形式显示。如果手贱写了safe,那就危险了,若想使用safe,那就必须在后台对要渲染的字符串做过滤了。所以在开发的时候,一定要慎用安全机制。尤其是对用户可以提交的并能渲染的内容!!!

    - 示例:

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title></title>
     6 </head>
     7 <body>
     8     <form method="POST" action="/comment/">
     9         <h4>评论</h4>
    10         <input type="text" name="content"/>
    11         <input type="submit" value="提交" />{{ error }}
    12     </form>
    13 </body>
    14 </html>
    评论提交页面
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title></title>
     6 </head>
     7 <body>
     8     <h1>评论内容</h1>
     9     {% for item in msg %}
    10         <div>{{ item|safe }}</div>
    11     {% endfor %}
    12 </body>
    13 </html>
    评论显示页面
     1 from django.shortcuts import render
     2 msg = []
     3 def comment(request):
     4         if request.method == "GET":
     5         return render(request,'comment.html')
     6     else:
     7         v = request.POST.get('content')
     8         if "script" in v:
     9             return render(request,'comment.html',{'error': '小比崽子还黑我'})
    10         else:
    11             msg.append(v)
    12             return render(request,'comment.html')
    13 
    14 def index(request):
    15     return render(request,'index.html',{'msg':msg})
    16 
    17 def test(request):
    18     from django.utils.safestring import mark_safe
    19     temp = "<a href='http://www.baidu.com'>百度</a>"
    20     newtemp = mark_safe(temp)
    21     return render(request,'test.html',{'temp':newtemp}
    后台处理

    CSRF跨站请求伪造

    什么是 CSRF

      CSRF, Cross Site Request Forgery, 跨站点请求伪造。举例来讲,某个恶意的网站上有一个指向你的网站的链接,如果某个用户已经登录到你的网站上了,那么当这个用户点击这个恶意网站上的那个链接时,就会向你的网站发来一个请求,你的网站会以为这个请求是用户自己发来的,其实呢,这个请求是那个恶意网站伪造的。

    csrf攻击过程

    1.用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;

    2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;

    3.用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;

    4.网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;

    5.浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。

    csrf的攻击之所以会成功是因为服务器端身份验证机制可以通过Cookie保证一个请求是来自于某个用户的浏览器,但无法保证该请求是用户允许的。因此,预防csrf攻击简单可行的方法就是在客户端网页上添加随机数,在服务器端进行随机数验证,以确保该请求是用户允许的。Django也是通过这个方法来防御csrf攻击的。

    在django防御csrf攻击

    原理

    在客户端页面上添加csrftoken, 服务器端进行验证,服务器端验证的工作通过'django.middleware.csrf.CsrfViewMiddleware'这个中间层来完成。在django当中防御csrf攻击的方式有两种, 1.在表单当中附加csrftoken 2.通过request请求中添加X-CSRFToken请求头。注意:Django默认对所有的POST请求都进行csrftoken验证,若验证失败则403错误侍候。

    在表单中附加csrftoken

    后端

     1 from django.shortcuts import render
     2 from django.template.context_processors import csrf
     3 
     4 def ajax_demo(request):
     5      # csrf(request)构造出{‘csrf_token’: token}
     6     return render(request, 'post_demo.html', csrf(request))

    前端

     1 $('#send').click(function(){
     2                 
     3     $.ajax({
     4         type: 'POST',
     5         url:'{% url 'ajax:post_data' %}',
     6         data: {
     7                 username: $('#username').val(),
     8                 content: $('#content').val(),
     9                'csrfmiddlewaretoken': '{{ csrf_token }}'  关键点
    10             },
    11         dataType: 'json',
    12         success: function(data){
    13 
    14         },
    15         error: function(){
    16     
    17         }
    18     
    19     });
    20   });
    View Code

    通过request请求中添加X-CSRFToken请求头

    后端

    该方式需要借助于Cookie传递csrftoken, 设置Cookie的方式有两种。ps:经测试即便什么都不做,也会设置Cookie,不过官方文档说,不保证每次都有效

    1.表单中添加{%csrf_token%}这个模板标签

    1 <form id="comment_form" action="#"></form>
    2 {% csrf_token %}   就是这个
    3 <p>姓名: <input type="text" name="useranme" id="username"></p>
    4 <p>内容: <textarea name="content" id="content" rows="5" cols="30"></textarea></p>
    5 <p><input type="button", id="send" value="提交"></p>

    2.ensure_csrf_cookie装饰器

    1 from django.shortcuts import render
    2 from django.views.decorators.csrf import ensure_csrf_cookie
    3 
    4 @ensure_csrf_cookie
    5 def ajax_demo(request):
    6     return render(request, 'ajax_demo.html')
    前端
    前端要做的事情,在进行post提交时,获取Cookie当中的csrftoken并在请求中添加X-CSRFToken请求头, 该请求头的数据就是csrftoken。通过$.ajaxSetup方法设置AJAX请求的默认参数选项, 在每次ajax的POST请求时,添加X-CSRFToken请求头
     1 <script type="text/javascript">
     2     $(function(){
     3 
     4         function getCookie(name) {
     5             var cookieValue = null;
     6             if (document.cookie && document.cookie != '') {
     7                 var cookies = document.cookie.split(';');
     8                 for (var i = 0; i < cookies.length; i++) {
     9                     var cookie = jQuery.trim(cookies[i]);
    10                     // Does this cookie string begin with the name we want?
    11                     if (cookie.substring(0, name.length + 1) == (name + '=')) {
    12                         cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
    13                         break;
    14                     }
    15                 }
    16             }
    17             return cookieValue;
    18         }
    19 
    20         <!--获取csrftoken-->
    21         var csrftoken = getCookie('csrftoken');
    22         console.log(csrftoken);
    23 
    24         //Ajax call
    25         function csrfSafeMethod(method) {
    26             // these HTTP methods do not require CSRF protection
    27             return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    28         }
    29 
    30         $.ajaxSetup({
    31             crossDomain: false, // obviates need for sameOrigin test
    32             //请求前触发
    33             beforeSend: function(xhr, settings) {
    34                 if (!csrfSafeMethod(settings.type)) {
    35                     xhr.setRequestHeader("X-CSRFToken", csrftoken);
    36                 }
    37             }
    38         });
    39 
    40         $('#send').click(function(){
    41             console.log($("#comment_form").serialize());
    42 
    43             $.ajax({
    44                 type: 'POST',
    45                 url:'{% url 'ajax:post_data' %}',
    46                 data: {
    47                         username: $('#username').val(),
    48                         content: $('#content').val(),
    49                        //'csrfmiddlewaretoken': '{{ csrf_token }}'
    50                     },
    51                 dataType: 'json',
    52                 success: function(data){
    53                          
    54                     
    55                 },
    56                 error: function(){
    57 
    58                 }
    59 
    60             });
    61         });
    62 
    63 
    64     });
    65 </script>

    取消csrftoken验证

    通过csrf_exempt, 来取消csrftoken验证,方式有两种。
    1 .在视图函数当中添加csrf_exempt装饰器

    1 from django.views.decorators.csrf import csrf_exempt
    2 
    3 @csrf_exempt
    4 def post_data(request):
    5     pass

    2 .在urlconf当中

    1 from django.views.decorators.csrf import csrf_exempt
    2 urlpatterns = [
    3     url(r'^post/get_data/$', csrf_exempt(post_data), name='post_data'),
    4 
    5 ]

    django csrf注意点:

    注意一定注意:ajax POST提交的时候,csrf-token 随机字符串 直接放在data数据中的方式为:data:{csrfmiddlewaretoken:"{{ csrf_token }}"}

      若是导入自己写的JS文件,那上述方法就不能获取到Django后台发送的随机字符串,而是需要利用上面介绍的两种方式获取(页面写上{% csrf_token %},通过隐藏的input标签取value值写在POST提交的data数据中;或是从cookie中获取,写在头文件中。)

    使用django框架时: 
      每次初始化一个项目时都要看看 django.middleware.csrf.CsrfViewMiddleware 这个中间件
      每次在模板里写 form 时都需要加一个 {% csrf_token %} tag
      每次发 ajax POST 请求,都需要加一个 X_CSRFTOKEN 的 header
    流程:
      用户第一次访问页面,肯定是get请求,此时服务端就会给客户端发送一段随机字符串的数据,当客户提交数据的时候,常在POST请求中带回,就会发送随机字符串给服务端(上一次请求获取的数据)用于验证。
      服务端给客户端发送的随机字符串作为一种安全机制,客户端往服务端发送请求时再携带回来,用于匹配认证。
      可以从form表单中接收,也可以在cookies中查看,注意:这两个的随机字符串是不同的!
      如果开启了csrf认证,后台没有拿到对应的字符串的话就会报错---> 403

  • 相关阅读:
    shell脚本修改Linux系统中所有IP样例
    关闭并卸载数据库脚本
    查询编译不通过的存储过程并重新编译
    SQL函数造数据样例(一)
    类型转换和多态
    Java学习笔记(三)
    Java学习笔记二()
    Java学习笔记(一)
    1.2.零宽断言
    1.3.匹配小括号的字符(可能有小括号在一行的,也有多行的)
  • 原文地址:https://www.cnblogs.com/sun1994/p/8426996.html
Copyright © 2011-2022 走看看