django csrf,xss,sql注入

tanrong 2019-12-20

一、csrf跨站请求伪造(Cross-site request forgery)

CSRF的攻击原理:简单说就是利用了高权限帐号(如管理员)的登录状态或者授权状态去做一些后台操作,但实际这些状态并没有被我们直接获取到(获取那是XSS干的事)。

CSRF能够攻击的根本原因是:服务器无法识别你的来源是否可靠。

防御CSRF攻击:服务端验证请求的token一致性

CSRF攻击的核心原理就是利用用户验证信息储存cookie中,发送请求,使得服务器无法判断真伪,而token之所以能够拦截,就是因为它是CSRF攻击过程中几乎不可能伪造的东西。

实现原理:在服务端生成一个随机的token,加入到HTTP请求参数中,服务器拦截请求,查看发送的token和服务端的是否一致,若一致,则允许请求;若不一致,则拒绝请求。

django项目setting.py里MIDDLEWARE就自带有django.middleware.csrf.CsrfViewMiddleware,再配合模板里的表单以post方式提交时添加的{% csrf_token %}就是采用此原理实现。但是有的项目采用前后端分离,就需要后端手动生成token发送给前端。

关于生成token:可以参考https://www.cnblogs.com/hooo-1102/p/12048232.html

二、xss跨站脚本攻击(Cross Site Scripting)

xss的攻击原理:通过对网页注入可执行代码且成功地被浏览器 执行,达到攻击的目的,形成了一次有效XSS攻击,一旦攻击成功,它可以获取用户的联系人列表,然后向联系人发送虚假诈骗信息,可以删除用户的日志等等,有时候还和其他攻击方式同时实施比如SQL注入攻击服务器和数据库、Click劫持、相对链接劫持等实施钓鱼,它带来的危害是巨大的,是web安全的头号大敌

下面举个栗子,比较简单:

前端:

django csrf,xss,sql注入

后端:

json_str = request.body
    if not json_str:
      result = {‘code‘:302, ‘error‘: ‘Please give me data‘}
      return JsonResponse(result)

    json_obj = json.loads(json_str)

    title = json_obj.get(‘title‘)

    if not title:
      result = {‘code‘:303, ‘error‘: ‘Please give me title !!‘}
      return JsonResponse(result)
    #防止xss cross site script 攻击
    title = html.escape(title)

对前端传过来的title进行了html.excape()处理,可以对相应的字符进行转义,标题下面的大文本框是第三方的,应该做了相应的处理,不需要我们再进行转义

django csrf,xss,sql注入

三、sql注入

所谓SQL注入就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串(注入本质上就是把输入的字符串变成可执行的程序语句),最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。在Web应用漏洞中,SQL Injection 漏洞的风险要高过其他所有的漏洞。

举个栗子:

前端就是一个简单的登录表单,

后端

from django.shortcuts import render, HttpResponse, redirect
from django.views.generic.base import View

class LoginNotSafeView(View):
    def get(self, request):
        return render(request, ‘login.html‘)
    def post(self, request):
        user_name = request.POST.get("username", "")
        pass_word = request.POST.get("password", "")

        import pymysql
        conn = pymysql.connect(host=‘127.0.0.1‘, port=3306, user=‘root‘, password=‘123456‘, db=‘mxonline‘,charset=‘utf8‘ )
        cursor = conn.cursor()
        # 黑客可通过user或者password输入数据库语句对数据非法利用
        sql_select = " select * from users_userprofile where username=‘{0}‘ and passworf=‘{1}‘ ".format(user_name, pass_word)
        result = cursor.execute(sql_select)
        for i in cursor.fetchall():
            # 数据库所有查询结果
            pass

如果在前端的username框中填写admin,password为123,

上面

sql_select = " select * from users_userprofile where username=‘{0}‘ and passworf=‘{1}‘

相当于

select * from users_userprofile where username=admin and passworf=123

但是如果在前端username框中填写admin or admin=admin #,password为123

现在就成这样了:

select * from users_userprofile where username=admin or admin = admin # and passworf=123

这里的#相当于把后面的所有查询包括password查询给注释,并且

or admin = admin

的查询永远是正确的,所以sql攻击注入就完成了

 

防御sql注入攻击:

  总是使用Django自带的数据库API

  对用户的输入进行校验,可以通过正则表达式限制长度;对单引号和双"-"进行转换等。

  不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。

  不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。

相关推荐