satori/go.uuid 非随机 UUID 问题(CVE-2021-3538)的原因和修复

   2 min read

因为在公司业务中遇到了这个问题,所以写了这篇博客来记录出现问题的原因和修复方法。

UUID WebP

原因

satori/go.uuid 这个包在这个 commit 中改成了标准库比较原生的读取方法 Read()

// NewV4 returns random generated UUID.
func (g *rfc4122Generator) NewV4() (UUID, error) {
	u := UUID{}
	if _, err := g.rand.Read(u[:]); err != nil {
		return Nil, err
	}
	u.SetVersion(V4)
	u.SetVariant(VariantRFC4122)

	return u, nil
}

而根据标准库文档的说明,Read() 不保证一定会读完,而且没读完也不会返回错误。

这样就导致了 NewV4() 不会返回没读完的错误,而是继续运行下去,使得 UUID 的某些部分是非随机的。如:

02524e6f-65a7-4cf5-8000-0000000000002
6e3ef1c8-0000-4000-8000-0000000000001
fa07f1e9-a8a0-427f-8103-e34e000000000
2cfa392b-71d5-4000-8000-000000000000
5f16db16-56ce-4000-8000-000000000000
bac73b37-aab3-498b-8000-000000000000
da5bd82d-4f98-4b51-8000-000000000000
eb245e52-535f-4274-8350-3a7200000000
f7510000-0000-4000-8000-000000000000
5936f955-286e-47ac-8000-000000000000
0a14da92-0000-4000-8000-000000000000
80730000-0000-4000-8000-000000000000
cd2b88a5-0000-4000-8000-000000000000

修复

参考链接

NewV4: non-random uuid

CVE-2021-3538 Detail