zoukankan      html  css  js  c++  java
  • XSS、CSRF、以及SQL注入

    xss攻击(跨站脚本)
    -- XSS攻击是向网页中注入恶意脚本,用户浏览网页时,在用户浏览器中执行恶意脚本的攻击。
    -- XSS分类,反射型xss ,存储型xss
    -- 反射型xss又称为非持久型xss,攻击者通过电子邮件等方式将包含注入脚本的链接发送给受害者,
    受害者通过点击链接,执行注入脚本,达到攻击目的。
    -- 持久型xss跟反射型的最大不同是攻击脚本将被永久的存放在目标服务器的数据库和文件中,多见于论坛
    攻击脚本连同正常信息一同注入到帖子内容当中,当浏览这个被注入恶意脚本的帖子的时候,恶意脚本会被执行
    -- 防范措施 1 输入过滤 2 输出编码 3 cookie防盗
    1,输入过滤 用户输入进行检测 不允许带有js代码
    2,输出编码 就是把我们的脚本代码变成字符串形式输出出来
    3,cookie加密
    向页面注入恶意的代码,这些代码被浏览器执行
    XSS攻击能做些什么:
    1.窃取cookies
    2.读取用户未公开的资料,如果:邮件列表或者内容、系统的客户资料,联系人列表

    xss和csrf的区别:
    相同之处:不攻击服务器端而攻击正常访问网站的用户
    不同:
    1.CSRF是伪造请求,冒充用户在站内的正常操作
    2.XSS攻击的主要目的则是,想办法获取目标攻击网站的cookie
    XSS是实现CSRF的诸多途径中的一条,通过XSS来实现的CSRF称为XSRF
    CSRF(Cross-site request forgery),中文名称:跨站请求伪造
    CSRF原理

    示例:

    A在银行有一笔存款,通过对银行的网站发送请求 http://bank.example/withdraw?account=A&amount=10000&for=B 可以使A 把 10000 的存款转到 B 的账号下。
    通常情况下,该请求发送到网站后,服务器会先验证该请求是否来自一个合法的 session,并且该 session 的用户A已经成功登陆。
    黑客C自己在该银行也有账户,他知道上文中的 URL 可以把钱进行转帐操作。C可以自己发送一个请求给银行:http://bank.example/withdraw?account=A&amount=1000000&for=C。
    但是这个请求来自 C而非 A,他不能通过安全认证,因此该请求不会起作用。
    这时,C想到使用 CSRF 的攻击方式,他先自己做一个网站,在网站中放入如下代码: src=”http://bank.example/withdraw?account=A&amount=1000000&for=C ”,
    并且通过广告等诱使A 来访问他的网站。当 Bob 访问该网站时,上述 url 就会从A的浏览器发向银行,而这个请求会附带 A浏览器中的 cookie 一起发向银行服务器。
    大多数情况下,该请求会失败,因为他要求A的认证信息。但是,如果 A 当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的 session 尚未过期,浏览器的 cookie 之中含有A的认证信息。这时这个 url 请求就会得到响应,钱将从A的账号转移到C的账号,而 Bob 当时毫不知情。
    等以后 A发现账户钱少了,即使他去银行查询日志,他也只能发现确实有一个来自于他本人的合法请求转移了资金,没有任何被攻击的痕迹。

      防御CSRF攻击:

           目前防御 CSRF 攻击主要有三种策略:验证 HTTP Referer 字段;在请求地址中添加 token 并验证;在 HTTP 头中自定义属性并验证

    (1)验证 HTTP Referer 字段
    根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。
    比如需要访问 http://bank.example/withdraw?account=A&amount=1000000&for=C,用户必须先登陆 bank.example
    而如果黑客要对银行网站实施 CSRF 攻击,他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到银行时,该请求的 Referer 是指向黑客自己的网站。
    (2)在请求地址中添加 token 并验证
    在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
    token 可以在用户登陆后产生并放于 session 之中,然后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。
    对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。 
    而对于 POST 请求来说,要在 form 的最后加上 <input type=”hidden” name=”csrftoken” value=”tokenvalue”/>,
    这样就把 token 以参数的形式加入请求了
    (3)在 HTTP 头中自定义属性并验证
    这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。
    通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。

    Django 提供的 CSRF 防护机制

    django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。
    而对于django中设置防跨站请求伪造功能有分为全局和局部。
    全局:中间件 django.middleware.csrf.CsrfViewMiddleware
    局部:
    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
    @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
    django.middleware.csrf.CsrfViewMiddleware
    当在settings中关闭它时,在页面上提交form表单时,不会进行校验。
    当开启它时,在页面上提交form表单时,会生成特殊的字符串进行校验
    这个中间件做的事情:
    1.在render返回页面的时候,在页面中塞了一个隐藏的input标签
    用法:我们在页面上form表单里面写上
    { % csrf_token %}
    会生成下面的标签,每次请求时,得到的值都不相同。如果打开csrf后,在form表单里不写{ % csrf_token %},请求会执行不了
    < input type = "hidden" name = "csrfmiddlewaretoken" value = "8gthvLKulM7pqulNl2q3u46v1oEbKG7BSwg6qsHBv4zf0zj0UcbQmpbAdijqyhfE" >
    2. 当你提交POST数据的时候,它帮你做校验,如果校验不通过就拒绝这次请求

    django中token防御的整体思路

    第一步:django第一次响应来自某个客户端的请求时,后端随机产生一个token值,把这个token放到cookie中交给前端页面;
    第二步:下次前端需要发起请求的时候会携带者这个token,一起传给后端;Cookies:{csrftoken:xxxxx}
    第三步:1.如果是通过表单发送post请求,后端会验证cookie中的csrftoken值和表单中的csrfmiddlewaretoken是否一致
    2.如果是ajax发送的post请求,后端会验证cookie中的csrftoken值和请求头中的X-CSRFtoken中的值是否一致

    实现csrf保护

    1.form提交时加上 { % csrf_token %}
    2.在ajax中提交时:取到csrf的 var csrfToken = $("[name='csrfmiddlewaretoken']").val();
    加到传输的数据中 data: {
    csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(), },
     $.ajax({
                    url: "/login/", // 进行二次验证
                    type: "post",
                    dataType: "json",
                    data: {
                            "usr":"root",
                            "pwd":"123"
                         csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(), 
                    },

    3.将csrftoken值放到请求头中,键值为X-CSRFtoken
    cookie中同样存在csrftoken,$.cooke("csrftoken")获取: headers:{ "X-CSRFtoken":$.cookie("csrftoken")},
     $("#btn1").click(function () {
                $.ajax({
                    url:"/login/",
                    type:"POST",
                    data:{"usr":"root","pwd":"123"},
                    headers:{ "X-CSRFtoken":$.cookie("csrftoken")},
                    success:function (arg) {
                    }
                })
            })

    csrf在前端的key为:X-CSRFtoken,到后端的时候django会自动添加HTTP_,并且最后为HTTP_X_CSRFtoken
    在后端打印csrftoken值
    print(settings.CSRF_HEADER_NAME)
    4.若是多个ajax一起触发,每次都请求有点麻烦,在ajax里有一个触发前的机制。
    $.ajaxSetup({
                   beforeSend:function (xhr,settings) {
                       xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken'));
                   }
                });
                在ajax之前的验证提交。参数是固定的。

    但是这样写有个弊端,就是所有的ajax不管是get还是post,还是其他的请求都会走一遍ajax,
    若有get提交,不想让它请求的,在django里有装饰器这个参数来设置。


    转账问题,当csrf关闭时
    <h1>正经网站</h1>
    <form action="/transfer/" method="post">  #提交后执行transfer函数
        <p>转出:
            <input type="text" name="from">
        </p>
        <p>转入:
            <input type="text" name="to">
        </p>
        <p>金额:
            <input type="text" name="money">
        </p>
        <p>
            <input type="submit" value="转账">
        </p>
    </form>
    转账函数:
    def transfer(request):
        if request.method=="POST":
            person_from=request.POST.get("from")
            person_to=request.POST.get("to")
            person_money=request.POST.get("money")
            ret="{} 给 {} 转了 {}钱".format( person_from,person_to,person_money)
            print(ret)
            return HttpResponse("转账成功")
        return render(request,"transfer.html")
    正经网站
    <h1>钓鱼网站</h1>
    <form action="http://127.0.0.1:8000/transfer/" method="post">  #提交后,执行正经网站的转账函数
        <p>转出:
            <input type="text" name="from">
        </p>
        <p>转入:
            <input type="text" name="">  #这个输入会在页面显示,但是不会给后端,实际给都后端的是下面隐藏的这个标签
            <input type="text" name="to" style="display: none" value="jerd"> #不管输入的是谁,都会把钱转给jerd
        </p>
       <p>金额:
            <input type="text" name="money">
       </p>
        <p>
            <input type="submit" value="转账">
        </p>
    </form>  
    将正经网站设置为8000端口,钓鱼网站设置8888端口,在钓鱼网站上输入,会通过正经网站转账成功
    小单 给 jerd 转了 10000000钱
    钓鱼网站
    转账问题,打开csrf
    <h1>正经网站</h1>
    <form action="/transfer/" method="post">  #提交后执行transfer函数
        {% csrf_token %} 打开csrf后,不使用它,会拒绝请求
        查看页面元素,页面会生成,每次刷新,值都会变化。提交后,会把这个值传给后端,后端根据这个值的正确性,判断是不是钓鱼网站
        <input name="csrfmiddlewaretoken" type="hidden" value="ieDyadHpEkB3zIdzfwbgp6VH1DLQENMt1CkznNpOWX9FOnrPRMfHJdr7S638oKDN">
        <p>转出:
            <input type="text" name="from">
        </p>
        <p>转入:
            <input type="text" name="to">
        </p>
        <p>金额:
            <input type="text" name="money">
        </p>
        <p>
            <input type="submit" value="转账">
        </p>
    </form>
    再次使用钓鱼网站转账,就拒绝请求
    正经网站

    为什么用户登录后会遇到CSRF验证失败?

    出于安全原因,每次用户登录时都会轮换CSRF令牌。在登录之前生成表单的任何页面都将具有旧的无效CSRF令牌并需要重新加载。如果用户在登录后使用后退按钮,或者他们登录其他浏览器选项卡,则可能会发生这种情况。

     

    SQL注入

    通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,实现无帐号登录,甚至篡改数据库。

    例1:

    select * from user where id=100 ,表示查询id为100的用户信息,

    如果id=100变为 id=100 or 2=2,sql将变为:select * from user where id=100 or 2=2,将把所有user表的信息查询出来,这就是典型的sql注入。

    例2:

    sql = "SELECT * FROM user WHERE username='"+username+"' AND password='"+password+"'";

    如果用户的输入的用户名如下,密码任意:

    myuser' or 'foo' = 'foo' --

    那么我们的SQL变成了如下所示:

    SELECT * FROM user WHERE username='myuser' or 'foo' = 'foo' --'' AND password='xxx'

    在SQL里面–是注释标记,所以查询语句会在此中断。这就让攻击者在不知道任何合法用户名和密码的情况下成功登录了。

     

    防止SQL注入的解决方案

    1)对用户的输入进行校验,使用正则表达式过滤传入的参数

    2)使用参数化语句,不要拼接sql,也可以使用安全的存储过程

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

    4)检查数据存储类型

    5)重要的信息一定要加密

    
    
     
     
  • 相关阅读:
    HDFS集群优化篇
    JavaScript基础知识-流程控制之if语句
    JavaScript基础知识-代码块
    Linux下查看某个进程打开的文件数-losf工具常用参数介绍
    Linux下查看线程数的几种方法汇总
    Linux网卡调优篇-禁用ipv6与优化socket缓冲区大小
    UGUI Text(Label)
    Vuforia Android 6 Camera Error
    轻量级C#编辑器RoslynPad((基于Roslyn编译器))
    [AR]Vumark(下一代条形码)
  • 原文地址:https://www.cnblogs.com/zgf-666/p/9136321.html
Copyright © 2011-2022 走看看