使用MongoDB生成的_ids作为“秘密数据”(例如,OAuth令牌)

时间:2013-03-15 14:57:18

标签: mongodb

MongoDB _id字段是否足够随机/不可以充当秘密数据?

例如:如果我正在构建服务器端OAuth,我可以将_id用作用户的OAuth令牌吗?我想这样做是因为清洁和它为数据库提供的可索引性(例如,“tokens._id”=> oauth_token)。

检查MongoDB _id对象的结构,它们看起来确实是随机的,但我确实对一个恶意实体蛮力猜测它有一些挥之不去的担忧。

2 个答案:

答案 0 :(得分:11)

简而言之,没有。 Mongo ObjectIds很容易猜到。特别是,在高负载下,这些通常是连续的数字,因为时间戳,机器和进程ID不会改变。如果你看the structure of Objectid,它们由

组成
a 4-byte timestamp, 
a 3-byte machine identifier, 
a 2-byte process id, and 
a 3-byte counter, starting with a random value.
因此,它们几乎没有随机性。我经常在数据库中看到连续的id,例如,如果某个控制器操作会快速连续写入域对象和日志条目。

如果可以猜测时间戳并且机器ID是可确定的(除非你有一个庞大的集群),那么只剩下五个字节。通过查看一些生成的id,我可以将其减少到50个进程,因此有效熵在28位范围内。这仍然很难猜测,但对于访问令牌来说风险太大了。

使用加密强大的伪随机数生成器代替并从中创建令牌。例如,在.NET中,RNGCryptoServiceProvider允许创建任意长度的随机数据。

作为旁注,我建议在OAuthTokens周围添加一个额外的加密包装器,原因有两个:

a)您希望能够快速确定无效令牌。有效的加密shell可能仍包含无效令牌(已撤销或已过期的授权),但您不必每次都使用强力攻击来访问数据库。此外,客户端

b)客户可以一遍又一遍地请求令牌。虽然这不是一项要求,但我所知道的几乎所有系统每次都会返回不同的令牌(无论它们是否自我验证)。通常,这是因为令牌本身的有效期有限。这与OAuth拨款的有效期不同。

在数据库中,您真正想要存储的是授权,即某些用户向某个客户端提供的权限。如果删除此授权,则所有令牌都将失效。每次插入一个新令牌都是非常不方便的,因为用户必须删除所有令牌以有效删除应用程序授权。

答案 1 :(得分:0)

虽然非常困难但可能会有所改变。实际上,猜测大多数其他OAuth令牌可能会更好。

它如何变得非常困难的一个例子是它包含PID。如果您使用的是PHP之类的语言,那么PID将更改为每个生成的PHP进程,这意味着每个_id可能会有自己的移动PID并且完全随机,当然这取决于您使用的模式运行PHP;如果在fcgi模式下,则PID可以是常量。

mahcine id也是另一个。大多数网站都为他们的数据库自动扩展服务器集群,所以即使在高负载等情况下,唯一真正可预测的变量是很多情况下的时间戳,即便如此,因为这是在毫秒级别,它仍然不是很容易猜测;你需要确切地知道网站有多少流量来建立一个算法来合理地计算时间。当然,首先装饰该信息的唯一方法是实际获得它的_id,捕获22。

然而,考虑到这一点,我能想到强制执行_id的唯一方法是获得足够的计算能力来迭代所有可能存在的ObjectIds(考虑到变量的随机性,这里可能是数万亿/无限)一个ObjectId),然后ping你的数据库中的每个应用程序ID(你应该总是要求OAuth令牌和应用程序ID),这再次提供了另一层神秘感。

所以在我看来,是的,有些人可能会蛮力但却需要很多计算能力,甚至可能需要几年的时间才能破解不值得的东西。