在之前的博客《一文理解JWT在鉴权登录的运用》先容了JWT在鉴权登录中的利用。但是不恰当地利用 JWT 可能会对运用程序安全产生负面影响。
本文将针对JWT在鉴权登录业务场景下的安全进行讲解。
由于JWT的载荷部分是可以被明文获取的,因此,如果有效载荷中存在敏感信息的话,就会发生信息透露。

情由同上。
3. 利用“刷新令牌”机制由于JWT是公开传输的,获取了令牌的黑客能够连续利用该JWT访问运用程序,以是利用最好双JWT机制降落安全风险。利用方法在《一文理解JWT在鉴权登录的运用》有详细讲解。
4. 增加JWT的业务参数,用于校验可以在Payload中增加一些业务上的字段,用于校验当前JWT是否被滥用。例如增加设备号,用户uuid、权限的信息,可以与高下文的信息进行对照,提高爬虫的门槛与接口安全性。
5. 始终验证并过滤从用户吸收的数据kid是JWT header中的一个可选参数,它用于指定加密算法的密钥。由于该参数可以由用户输入,系统并不知道用户想要读取的到底是不是密钥文件。如果在没有对参数进行过滤的条件下,攻击者是可以读取到系统的任意文件的、造成SQL注入或命令注入等漏洞。
{ "alg" : "HS256", "typ" : "jwt", "kid" : "/etc/passwd"}{ "alg" : "HS256", "typ" : "jwt", "kid" : "key11111111' || union select 'secretkey' -- "}
以是,验证并过滤从用户吸收的数据是必要的。
6. 提高对称加密的秘钥强度如果加密的密钥强度较弱的话,攻击者可以直接通过蛮力攻击办法来破解密钥,可以利用PyJWT、John Ripper或c-jwt-cracker进行破解测试。PyJWT库详细地址看参考文档4。c-jwt-cracker库集体地址看参考文档5。
秘钥不定期的变革。这对用户来说不太方便,由于他们将不得不再次通过身份验证,但这有助于避免安全问题的发生。
7. 做事端增加授权署名算法的白名单署名算法可以确保JWT在传输过程中不会被恶意用户所修改,但头部中的alg字段却可以改为None,即不该用署名算法。这样的话,当signature设置为空时,后端将不实行署名验证。
将alg字段改为none后,系统就会天生这样形式的JWT,然后将其提交给做事器并通过校验:
base64UrlEncode(header) + "." + base64UrlEncode(payload)
以是,有必要在做事端增加已授权算法的白名单,并删除所有与做事端上授权算法不同的署名算法的JWT。
8. 最好只利用一个署名算法在利用非对称算法进行令牌署名的情形下,署名应利用私钥,而署名验证应利用公钥。由于利用JWT的某些库包含逻辑缺点——当收到用对称算法署名的令牌时,将利用公钥作为验证署名的secret。由于公钥并不是秘密数据,因此黑客可能会得到公共做事密钥并用于签署自己的令牌。
以是,当网站采取非对称加密验证,且不对署名算法进行限定的话,存在这样的漏洞:
通过一定手段,获取到非对称加密的公钥,将alg字段改为对称加密算法。利用公钥对JWT进行署名,发送给做事端。做事端会将对称加密的公钥作为验证署名的秘钥,利用对称加密算法对吸收的JWT进行验证。为相识释这个问题,以下实验部分节选自参考文档7的部分内容:
利用非对称加密算法RS256,新建一个JWT如下:
header:{ "alg": "RS256", "typ": "JWT"}payload:{ "id": "1337", "username": "bizone", "iat": 1594209600, "role": "user"}
转为JWT为:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEzMzciLCJ1c2VybmFtZSI6ImJpem9uZSIsImlhdCI6MTU5NDIwOTYwMCwicm9sZSI6InVzZXIifQ.YLOVSKef-paSnnM8P2JLaU2FiS8TbhYqjewLmgRJfCj1Q6rVehAHQ-lABnKoRjlEmHZX-rufHEocDxGUYiGMjMexUQ3zt-WqZITvozJ4pkvbV-mJ1nKj64NmqaR9ZkBWtmF-PHJX50eYjgo9rzLKbVOKYOUa5rDkJPHP3U0aaBXFP39zsGdOTuELv436WXypIZBeRq2yA_mDH13TvzegWCK5sjD4Gh177bCq57tBYjhGIQrDypVe4cWBPlvwFlmG8tdpWGu0uFp0GcbTAfLUlbTSuGROj88BY0XeUs0iqmGlEICES3uqNx7vEmdT5k_AmL436SLedE0VHcyxve5ypQ
在这种情形下,利用RS256算法署名,将须要公钥和私钥。
公钥:
-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQAB-----END PUBLIC KEY-----
私钥:
-----BEGIN RSA PRIVATE KEY-----MIIEogIBAAKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQABAoIBACiARq2wkltjtcjskFvZ7w1JAORHbEufEO1Eu27zOIlqbgyAcAl7q+/1bip4Z/x1IVES84/yTaM8p0goamMhvgry/mS8vNi1BN2SAZEnb/7xSxbflb70bX9RHLJqKnp5GZe2jexw+wyXlwaM+bclUCrh9e1ltH7IvUrRrQnFJfh+is1fRon9Co9Li0GwoN0x0byrrngU8Ak3Y6D9D8GjQA4Elm94ST3izJv8iCOLSDBmzsPsXfcCUZfmTfZ5DbUDMbMxRnSo3nQeoKGC0Lj9FkWcfmLcpGlSXTO+Ww1L7EGq+PT3NtRae1FZPwjddQ1/4V905kyQFLamAA5YlSpE2wkCgYEAy1OPLQcZt4NQnQzPz2SBJqQN2P5u3vXl+zNVKP8w4eBv0vWuJJF+hkGNnSxXQrTkvDOIUddSKOzHHgSg4nY6K02ecyT0PPm/UZvtRpWrnBjcEVtHEJNpbU9pLD5iZ0J9sbzPU/LxPmuAP2Bs8JmTn6aFRspFrP7W0s1Nmk2jsm0CgYEAyH0X+jpoqxj4efZfkUrg5GbSEhf+dZglf0tTOA5bVg8IYwtmNk/pniLG/zI7c+GlTc9BBwfMr59EzBq/eFMI7+LgXaVUsM/sS4Ry+yeK6SJx/otIMWtDfqxsLD8CPMCRvecC2Pip4uSgrl0MOebl9XKp57GoaUWRWRHqwV4Y6h8CgYAZhI4mh4qZtnhKjY4TKDjxQYufXSdLAi9v3FxmvchDwOgn4L+PRVdMwDNms2bsL0m5uPn104EzM6w1vzz1zwKz5pTpPI0OjgWN13Tq8+PKvm/4Ga2MjgOgPWQkslulO/oMcXbPwWC3hcRdr9tcQtn9Imf9n2spL/6EDFId+Hp/7QKBgAqlWdiXsWckdE1Fn91/NGHsc8syKvjjk1onDcw0NvVi5vcba9oGdElJX3e9mxqUKMrw7msJJv1MX8LWyMQC5L6YNYHDfbPF1q5L4i8j8mRex97UVokJQRRA452V2vCO6S5ETgpnad36de3MUxHgCOX3qL382Qx9/THVmbma3YfRAoGAUxL/Eu5yvMK8SAt/dJK6FedngcM3JEFNplmtLYVLWhkIlNRGDwkg3I5Ky18Ae9n7dHVueyslrb6weq7dTkYDi3iOYRW8HRkIQh06wEdbxt0shTzAJvvCQfrBjg/3747WSsf/zBTcHihTRBdAv6OmdhV4/dD5YBfLAkLrd+mX7iE=-----END RSA PRIVATE KEY-----
为验证JWT有效性,利用参考文档2的网站如下图:
header:{ "typ": "JWT", "alg": "HS256"}payload:{ "id": "1337", "username": "bizone", "iat": 1594209600, "role": "admin"}
转化为JWT的头部和载荷部分如下:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjEzMzciLCJ1c2VybmFtZSI6ImJpem9uZSIsImlhdCI6MTU5NDIwOTYwMCwicm9sZSI6ImFkbWluIn0
现在只须要利用公钥读取署名。
首先,把密钥转移到十六进制表示法,如下图。
然后利用openssl天生一个署名,如下图。
将值e1r1nwnso-h7h5woycbnm6c1zzy-0hu2vwpwgmpk2g添加到网站上的“secret”中(记住选中“secret base64 encoded”),终极的JWT如下:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjEzMzciLCJ1c2VybmFtZSI6ImJpem9uZSIsImlhdCI6MTU5NDIwOTYwMCwicm9sZSI6ImFkbWluIn0.E1R1nWNsO-H7h5WoYCBnm6c1zZy-0hu2VwpWGMVPK2g
正如网站显示的结果,JWT成功地通过了验证。
以是,最好只利用一种加密办法,防止类似的安全漏洞。
9. 选择有名且可靠的JWT库网上有不少对JWT库的选型比拟,由于这种建议具有时效性,本文不做推举。
参考文档:
https://github.com/auth0/java-jwthttps://jwt.io/https://docs.aws.amazon.com/zh_cn/acm/latest/userguide/import-certificate-format.htmlhttps://github.com/jpadilla/pyjwthttps://github.com/brendan-rius/c-jwt-crackerhttps://skysec.top/2018/05/19/2018CUMTCTF-Final-Web/#Pastebin/https://cyberpolygon.com/materials/security-of-json-web-tokens-jwt/