CSRF攻击

CSRF攻击概述

CSRF(Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一。其他安全隐患,比如 SQL 脚本注入,跨站域脚本攻击等在近年来已经逐渐为众人熟知,很多网站也都针对他们进行了防御。然而,对于大多数人来说,CSRF 却依然是一个陌生的概念。即便是大名鼎鼎的 Gmail, 在 2007 年底也存在着 CSRF 漏洞,从而被黑客攻击而使 Gmail 的用户造成巨大的损失。

CSRF攻击原理

cookiecookiecookiecookiecookie

防御CSRF攻击

cookiecsrf_tokencookiecsrf_tokenbodycookiecsrf_tokencookiecsrf_tokenbodycsrf_tokenDjangoCSRFsettings.MIDDLEWARECsrfMiddlewareinputcsrf_token
MIDDLEWARE = [
  'django.middleware.security.SecurityMiddleware',
  'django.middleware.gzip.GZipMiddleware',
  'django.contrib.sessions.middleware.SessionMiddleware',
  'django.middleware.common.CommonMiddleware',
  'django.middleware.csrf.CsrfViewMiddleware',
  'django.contrib.auth.middleware.AuthenticationMiddleware',
  'django.contrib.messages.middleware.MessageMiddleware',
  'django.middleware.clickjacking.XFrameOptionsMiddleware'
]
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}"/>
{% csrf_token %}

使用ajax处理csrf防御

ajaxcsrfformcsrfmiddlewaretokenX-CSRFTokencookiecsrf token
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

var myajax = {
    'get': function (args) {
        args['method'] = 'get';
        this.ajax(args);
    },
    'post': function (args) {
        args['method'] = 'post';
        this._ajaxSetup();
        this.ajax(args);
    },
    'ajax': function (args) {
        $.ajax(args);
    },
    '_ajaxSetup': function () {
        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                if (!/^(GET|HEAD|OPTIONS|TRACE)$/.test(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
                }
            }
        });
    }
};

$(function () {
    $("#submit").click(function (event) {
        event.preventDefault();
        var email = $("input[name='email']").val();
        var money = $("input[name='money']").val();

        myajax.post({
            'url': '/transfer/',
            'data':{
                'email': email,
                'money': money
            },
            'success': function (data) {
                console.log(data);
            },
            'fail': function (error) {
                console.log(error);
            }
        });
    })
});

iframe相关知识

<iframe src="http://www.baidu.com/">
</ifrmae>
XSS攻击
XSS

XSS攻击场景

A网站jsA网站hello worldjs

XSS攻击防御

 from django.template.defaultfilters import escape
 from .models import Comment
 from django.http import HttpResponse
 def comment(request):
     content = request.POST.get("content")
     escaped_content = escape(content)
     Comment.objects.create(content=escaped_content)
     return HttpResponse('success')
 # views.py
 def index(request):
     message = "<span style='color:red;'>红色字体</span><script>alert('hello world');</script>";
     return render_template(request,'index.html',context={"message":message})
 # index.html

bleach库

bleachhtml
pip install bleach

bleach.cleanbleach.clean
import bleach
from bleach.sanitizer import ALLOWED_TAGS,ALLOWED_ATTRIBUTES

@require_http_methods(['POST'])
def message(request):
    # 从客户端中获取提交的数据
    content = request.POST.get('content')

    # 在默认的允许标签中添加img标签
    tags = ALLOWED_TAGS + ['img']
    # 在默认的允许属性中添加src属性
    attributes = {**ALLOWED_ATTRIBUTES,'img':['src']}

    # 对提交的数据进行过滤
    cleaned_content=bleach.clean(content,tags=tags,attributes=attributes)

    # 保存到数据库中
    Message.objects.create(content=cleaned_content)

    return redirect(reverse('index'))

相关介绍如下:

tagsattributesALLOWED_TAGSbleachALLOWED_ATTRIBUTESbleach

bleach更多资料

clickjacking(点击劫持)攻击
clickjacking

clickjacking攻击场景

场景一

如用户收到一封包含一段视频的电子邮件,但其中的“播放”按钮并不会真正播放视频,而是链入一购物网站。这样当用户试图“播放视频”时,实际是被诱骗而进入了一个购物网站。

场景二

按钮Aiframeiframe按钮A按钮Aiframe
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<head>
<title>点击劫持</title>
<style>
    iframe{
        opacity:0.01;
        position:absolute;
        z-index:2;
         100%;
        height: 100%;
    }
    button{
        position:absolute;
        top: 345px;
        left: 630px;
        z-index: 1;
         72px;
        height: 26px;
    }
</style>
</head>
<body>
    这个合影里面怎么会有你?
    <button>查看详情</button>
    <iframe src="http://tieba.baidu.com/f?kw=%C3%C0%C5%AE"></iframe>
</body>
</html>

页面看起来比较简陋,但是实际上可能会比这些更精致一些。当这个页面通过某种手段被传播出去后,用户如果点击了“查看详情”,实际上点击到的是关注的按钮,这样就可以增加了一个粉丝。

clickjacking防御

iframeX-Frame-OptionsX-Frame-Options
DENYiframeSAMEORIGINiframeALLOW-FROM originiframe
Djangodjango.middleware.clickjacking.XFrameOptionsMiddlewareX-Frame-OptionSAMEORIGINiframeiframe
SQL注入

所谓SQL注入,就是通过把SQL命令插入到表单中或页面请求的查询字符串中,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。 比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的。

场景

front_user
class User(models.Model):
    telephone = models.CharField(max_length=11)
    username = models.CharField(max_length=100)
    password = models.CharField(max_length=100)

sql
     def index(request):
         user_id = request.GET.get('user_id')
         cursor = connection.cursor()
         cursor.execute("select id,username from front_user where id=%s" % user_id)
         rows = cursor.fetchall()
         for row in rows:
             print(row)
         return HttpResponse('success')

 select id,username from front_user where id=1 or 1=1

 def index(request):
     username = request.GET.get('username')
     cursor = connection.cursor()
     cursor.execute("select id,username from front_user where username='%s'" % username)
     rows = cursor.fetchall()
     for row in rows:
         print(row)
     return HttpResponse('success')

 select id,username from front_user where username='zhiliao' or '1=1'

sql注入防御

sqlsqlsqlsql
 def index(request):
     user_id = "1 or 1=1"
     cursor = connection.cursor()
     cursor.execute("select id,username from front_user where id=%s",(user_id,))
     rows = cursor.fetchall()
     for row in rows:
         print(row)
     return HttpResponse('success')

sql
ORMORMsqlsql