JWT笔记(2)

上文对JWT模块进行了一个简单的分析.这篇文章稍微做出一些深入的了解.

一,Header篡改攻击

因为JWT的Header是强制有效并且是明文传输(Base64URL编码,几乎等同于明文).那么恶意用户可以很容易地用以下方式进行攻击.

假设恶意用户Bob按如下的数据结构伪造Token:

header: {alg:none} payLoad: {user:root}

生成的Token类似:

eyJhbGciOiJub25lIn0.eyJzdWIiOiJ1c2VyMTIzIiwic2Vzc2lvbiI6ImNoNzJnc2IzMjAwMDB1ZG9jbDM2M2VvZnkiLCJuYW1lIjoiUHJldHR5IE5hbWUiLCJsYXN0cGFnZSI6Ii92aWV3cy9zZXR0aW5ncyJ9.

注意这个Token是没有signature字段的,它只有header, payload.这个Token的所用的加密算法是none, payLoad是root用户.如果authentication端的代码不够健壮的话,它有可能直接调用JWT库进行解析,从而让这个请求通过验证.

二, JWT Token生成方法

JWT Token的头部和payload都是按照baseURL64算法转化而来的,可以理解为是明文,所以关键就是signature.

其中一个生成方式如下,这个函数的输入是payload和alg,参数payload实际上就是token的header.payload部分.而alg是生成秘钥所采用的

加密算法,其首先用一个hash类将payload转化为一个hash表,然后调用go语言的库函数.假设加密算法是RS256的话,其最后所调用的

就是go语言的SignPKCS1v15()函数.这个函数干的事实际上就是rsa加密.

func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
	var hash crypto.Hash
	glog.V(1).Infof("gakki we are trying sign %s\n", string(payload))
	switch alg {
	case RS256, PS256:
		hash = crypto.SHA256
	case RS384, PS384:
		hash = crypto.SHA384
	case RS512, PS512:
		hash = crypto.SHA512
	default:
		return Signature{}, ErrUnsupportedAlgorithm
	}

	hasher := hash.New()

	// According to documentation, Write() on hash never fails
	_, _ = hasher.Write(payload)
	hashed := hasher.Sum(nil)
	glog.V(1).Infof("the hashed is %#v\n", hashed)
	var out []byte
	var err error

	switch alg {
	case RS256, RS384, RS512:
		out, err = rsa.SignPKCS1v15(randReader, ctx.privateKey, hash, hashed)
	case PS256, PS384, PS512:
		out, err = rsa.SignPSS(randReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{
			SaltLength: rsa.PSSSaltLengthAuto,
		})
	}
    	if err != nil {
		return Signature{}, err
	}
	glog.V(1).Infof("the out is %#v\n", out)
	return Signature{
		Signature: out,
		protected: &rawHeader{},
	}, nil
}

猜你喜欢

转载自www.cnblogs.com/elnino/p/9135254.html
jwt
今日推荐