daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

index.md (10299B)


      1 ---
      2 title: "Insecure Randomness"
      3 topic: "Insecure Randomness"
      4 topicSlug: "insecure-randomness"
      5 sourcePath: "Insecure Randomness/README.md"
      6 sourceUrl: "https://github.com/swisskyrepo/PayloadsAllTheThings/blob/3ac27901c711/Insecure%20Randomness/README.md"
      7 sha: "3ac27901c711"
      8 isReadme: true
      9 ---
     10 
     11 # Insecure Randomness
     12 
     13 > Insecure randomness refers to the weaknesses associated with random number generation in computing, particularly when such randomness is used for security-critical purposes. Vulnerabilities in random number generators (RNGs) can lead to predictable outputs that can be exploited by attackers, resulting in potential data breaches or unauthorized access.
     14 
     15 ## Summary
     16 
     17 * [Methodology](#methodology)
     18 * [Time-Based Seeds](#time-based-seeds)
     19 * [GUID / UUID](#guid--uuid)
     20     * [GUID Versions](#guid-versions)
     21 * [Mongo ObjectId](#mongo-objectid)
     22 * [Uniqid](#uniqid)
     23 * [mt_rand](#mt_rand)
     24 * [Custom Algorithms](#custom-algorithms)
     25 * [References](#references)
     26 
     27 ## Methodology
     28 
     29 Insecure randomness arises when the source of randomness or the method of generating random values is not sufficiently unpredictable. This can lead to predictable outputs, which can be exploited by attackers. Below, we examine common methods that are prone to insecure randomness, including time-based seeds, GUIDs, UUIDs, MongoDB ObjectIds, and the `uniqid()` function.
     30 
     31 ## Time-Based Seeds
     32 
     33 Many random number generators (RNGs) use the current system time (e.g., milliseconds since epoch) as a seed. This approach can be insecure because the seed value can be easily predicted, especially in automated or scripted environments.
     34 
     35 ```py
     36 import random
     37 import time
     38 
     39 seed = int(time.time())
     40 random.seed(seed)
     41 print(random.randint(1, 100))
     42 ```
     43 
     44 The RNG is seeded with the current time, making it predictable for anyone who knows or can estimate the seed value.
     45 By knowing the exact time, an attacker can regenerate the correct random value, here is an example for the date `2024-11-10 13:37`.
     46 
     47 ```python
     48 import random
     49 import time
     50 
     51 # Seed based on the provided timestamp
     52 seed = int(time.mktime(time.strptime('2024-11-10 13:37', '%Y-%m-%d %H:%M')))
     53 random.seed(seed)
     54 
     55 # Generate the random number
     56 print(random.randint(1, 100))
     57 ```
     58 
     59 ## GUID / UUID
     60 
     61 A GUID (Globally Unique Identifier) or UUID (Universally Unique Identifier) is a 128-bit number used to uniquely identify information in computer systems. They are typically represented as a string of hexadecimal digits, divided into five groups separated by hyphens, such as `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.
     62 
     63 ### GUID Versions
     64 
     65 Version identification: `xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx`
     66 The four-bit M and the 1- to 3-bit N fields code the format of the UUID itself.
     67 
     68 | Version | Notes                                                         |
     69 | ------- | ------------------------------------------------------------- |
     70 | 0       | Only `00000000-0000-0000-0000-000000000000`                   |
     71 | 1       | based on time, or clock sequence                              |
     72 | 2       | reserved in the RFC 4122, but omitted in many implementations |
     73 | 3       | based on a MD5 hash                                           |
     74 | 4       | randomly generated                                            |
     75 | 5       | based on a SHA1 hash                                          |
     76 
     77 ### Tools
     78 
     79 * [intruder-io/guidtool](https://github.com/intruder-io/guidtool) - A tool to inspect and attack version 1 GUIDs
     80 
     81     ```ps1
     82     $ guidtool -i 95f6e264-bb00-11ec-8833-00155d01ef00
     83     UUID version: 1
     84     UUID time: 2022-04-13 08:06:13.202186
     85     UUID timestamp: 138691299732021860
     86     UUID node: 91754721024
     87     UUID MAC address: 00:15:5d:01:ef:00
     88     UUID clock sequence: 2099
     89     
     90     $ guidtool 1b2d78d0-47cf-11ec-8d62-0ff591f2a37c -t '2021-11-17 18:03:17' -p 10000
     91     ```
     92 
     93 ## Mongo ObjectId
     94 
     95 Mongo ObjectIds are generated in a predictable manner, the 12-byte ObjectId value consists of:
     96 
     97 * **Timestamp** (4 bytes): Represents the ObjectId’s creation time, measured in seconds since the Unix epoch (January 1, 1970).
     98 * **Machine Identifier** (3 bytes): Identifies the machine on which the ObjectId was generated. Typically derived from the machine's hostname or IP address, making it predictable for documents created on the same machine.
     99 * **Process ID** (2 bytes): Identifies the process that generated the ObjectId. Typically the process ID of the MongoDB server process, making it predictable for documents created by the same process.
    100 * **Counter** (3 bytes): A unique counter value that is incremented for each new ObjectId generated. Initialized to a random value when the process starts, but subsequent values are predictable as they are generated in sequence.
    101 
    102 Token example
    103 
    104 * `5ae9b90a2c144b9def01ec37`, `5ae9bac82c144b9def01ec39`
    105 
    106 ### Tools
    107 
    108 * [andresriancho/mongo-objectid-predict](https://github.com/andresriancho/mongo-objectid-predict) - Predict Mongo ObjectIds
    109 
    110     ```ps1
    111     ./mongo-objectid-predict 5ae9b90a2c144b9def01ec37
    112     5ae9bac82c144b9def01ec39
    113     5ae9bacf2c144b9def01ec3a
    114     5ae9bada2c144b9def01ec3b
    115     ```
    116 
    117 * Python script to recover the `timestamp`, `process` and `counter`
    118 
    119     ```py
    120     def MongoDB_ObjectID(timestamp, process, counter):
    121         return "%08x%10x%06x" % (
    122             timestamp,
    123             process,
    124             counter,
    125         )
    126 
    127     def reverse_MongoDB_ObjectID(token):
    128         timestamp = int(token[0:8], 16)
    129         process = int(token[8:18], 16)
    130         counter = int(token[18:24], 16)
    131         return timestamp, process, counter
    132 
    133 
    134     def check(token):
    135         (timestamp, process, counter) = reverse_MongoDB_ObjectID(token)
    136         return token == MongoDB_ObjectID(timestamp, process, counter)
    137 
    138     tokens = ["5ae9b90a2c144b9def01ec37", "5ae9bac82c144b9def01ec39"]
    139     for token in tokens:
    140         (timestamp, process, counter) = reverse_MongoDB_ObjectID(token)
    141         print(f"{token}: {timestamp} - {process} - {counter}")
    142     ```
    143 
    144 ## Uniqid
    145 
    146 Token derived using `uniqid` are based on timestamp and they can be reversed.
    147 
    148 * [Riamse/python-uniqid](https://github.com/Riamse/python-uniqid/blob/master/uniqid.py) is based on a timestamp
    149 * [php/uniqid](https://github.com/php/php-src/blob/master/ext/standard/uniqid.c)
    150 
    151 Token examples
    152 
    153 * uniqid: `6659cea087cd6`, `6659cea087cea`
    154 * sha256(uniqid): `4b26d474c77daf9a94d82039f4c9b8e555ad505249437c0987f12c1b80de0bf4`, `ae72a4c4cdf77f39d1b0133394c0cb24c33c61c4505a9fe33ab89315d3f5a1e4`
    155 
    156 ### Tools
    157 
    158 ```py
    159 import math
    160 import datetime
    161 
    162 def uniqid(timestamp: float) -> str:
    163     sec = math.floor(timestamp)
    164     usec = round(1000000 * (timestamp - sec))
    165     return "%8x%05x" % (sec, usec)
    166 
    167 def reverse_uniqid(value: str) -> float:
    168     sec = int(value[:8], 16)
    169     usec = int(value[8:], 16)
    170     return float(f"{sec}.{usec}")
    171 
    172 tokens = ["6659cea087cd6" , "6659cea087cea"]
    173 for token in tokens:
    174     t = float(reverse_uniqid(token))
    175     d = datetime.datetime.fromtimestamp(t)
    176     print(f"{token} - {t} => {d}")
    177 ```
    178 
    179 ## mt_rand
    180 
    181 Breaking mt_rand() with two output values and no bruteforce.
    182 
    183 * [ambionics/mt_rand-reverse](https://github.com/ambionics/mt_rand-reverse) - Script to recover mt_rand()'s seed with only two outputs and without any bruteforce.
    184 
    185 ```ps1
    186 ./display_mt_rand.php 12345678 123
    187 712530069 674417379
    188 
    189 ./reverse_mt_rand.py 712530069 674417379 123 1
    190 ```
    191 
    192 ## Custom Algorithms
    193 
    194 Creating your own randomness algorithm is generally not recommended. Below are some examples found on GitHub or StackOverflow that are sometimes used in production, but may not be reliable or secure.
    195 
    196 * `$token = md5($emailId).rand(10,9999);`
    197 * `$token = md5(time()+123456789 % rand(4000, 55000000));`
    198 
    199 ### Tools
    200 
    201 Generic identification and sandwich attack:
    202 
    203 * [AethliosIK/reset-tolkien](https://github.com/AethliosIK/reset-tolkien) - Insecure time-based secret exploitation and Sandwich attack implementation Resources
    204 
    205     ```ps1
    206     reset-tolkien detect 660430516ffcf -d "Wed, 27 Mar 2024 14:42:25 GMT" --prefixes "attacker@example.com" --suffixes "attacker@example.com" --timezone "-7"
    207     reset-tolkien sandwich 660430516ffcf -bt 1711550546.485597 -et 1711550546.505134 -o output.txt --token-format="uniqid"
    208     ```
    209 
    210 ## References
    211 
    212 * [Breaking PHP's mt_rand() with 2 values and no bruteforce - Charles Fol - January 6, 2020](https://web.archive.org/web/20200106202157/https://www.ambionics.io/blog/php-mt-rand-prediction)
    213 * [Cracking Time-Based Tokens: A Glimpse from a Workshop During leHACK 2025-Singularity - 4m1d0n - June 30, 2025](https://4m1d0n.github.io/retex-insecure-time-token-sandwich-attack/)
    214 * [Exploiting Weak Pseudo-Random Number Generation in PHP’s rand and srand Functions - Jacob Moore - October 18, 2023](https://web.archive.org/web/20250919151004/https://medium.com/@moorejacob2017/exploiting-weak-pseudo-random-number-generation-in-phps-rand-and-srand-functions-445229b83e01)
    215 * [IDOR through MongoDB Object IDs Prediction - Amey Anekar - August 25, 2020](https://web.archive.org/web/20200826103440/https://techkranti.com/idor-through-mongodb-object-ids-prediction)
    216 * [In GUID We Trust - Daniel Thatcher - October 11, 2022](https://web.archive.org/web/20221013100900/https://www.intruder.io/research/in-guid-we-trust)
    217 * [Multi-sandwich attack with MongoDB Object ID or the scenario for real-time monitoring of web application invitations: a new use case for the sandwich attack - Tom CHAMBARETAUD (@AethliosIK) - July 18, 2024](https://web.archive.org/web/20260201082729/https://www.aeth.cc/public/Article-Reset-Tolkien/multi-sandwich-article-en.html)
    218 * [Secret basé sur le temps non sécurisé et attaque par sandwich - Analyse de mes recherches et publication de l’outil “Reset Tolkien” - Tom CHAMBARETAUD (@AethliosIK) - April 2, 2024](https://web.archive.org/web/20240408172738/https://www.aeth.cc/public/Article-Reset-Tolkien/secret-time-based-article-fr.html) *(FR)*
    219 * [Unsecure time-based secret and Sandwich Attack - Analysis of my research and release of the “Reset Tolkien” tool - Tom CHAMBARETAUD (@AethliosIK) - April 2, 2024](https://web.archive.org/web/20250531084109/https://www.aeth.cc/public/Article-Reset-Tolkien/secret-time-based-article-en.html) *(EN)*