Full Report
Much of the time, breaking randomness requires fancy math. This post is about using the situational awareness of the random function to exploit the system. In this case, the author of the post was targeting a password reset token. In C#, the PRNG is considered "insecure," meaning it's not truly random. It has a set path it goes on, and the randomness really relies on the seed. If no seed is provided, then the TickCount is used. This is the number of milliseconds since the machine was booted. What's interesting about this, is that the seed is calculated for each call to random()! In the .NET framework, there is a note about this. "As a result, different Random objects that are created in close succession by a call to the parameterless constructor have identical default seed values and, therefore, produce identical sets of random numbers." So, if calls to random are made within the same 1ms, they will produce the same output. If you have your own password reset token and tried resetting another user's, it all went well then they should be the same. Is this even possible to reproduce? 1ms is tight! Using the single packet attack documented by James Kettle, this is possible in Burp Suite. Use Burp's repeater groups to reset both passwords at the same time. There are still a lot of false positives while doing this, though. This exact issue affects Python's UUID implementation. They have also seen similar types of things used in CTFs. The end of the post demonstrates how to break this algorithm using math, and it even reveals a bug in the C# implementation (a weird integer overflow). An excellent write-up for a bug they found!
Analysis Summary
# Vulnerability: Predictable Password Reset Tokens Due to C# `Random` Initialization Timing
## CVE Details
- CVE ID: N/A (This appears to be a class of application logic flaw, not a specific assigned CVE for the use of the PRNG itself, though similar issues might have CVEs.)
- CVSS Score: High (Likely high due to potential for account takeover, specific score not provided based on context.)
- CWE: CWE-331 (Inadequate Seeding of a Pseudo-Random Number Generator), CWE-382 (Use of a Pseudo-Random Number Generator When a Cryptographically Secure One is Required)
## Affected Systems
- Products: C# applications utilizing the parameterless constructor of `System.Random()` for generating security tokens (e.g., password reset tokens). This specifically impacts libraries or applications built on the **.NET Framework** version that uses `Environment.TickCount` as the default seed source for `new Random()`. modern .NET implementations using Xoshiro128StarStar may not be affected if they do not seed by time in the same manner.
- Versions: Undetermined, but applies to legacy or specific configurations of the .NET Framework where `new Random()` relies on `Environment.TickCount`.
- Configurations: Instances where security-critical values (like password reset tokens) are generated using `new Random()` without an explicit, high-entropy seed, and where multiple calls occur within a 1ms interval.
## Vulnerability Description
The vulnerability stems from the default constructor of the C# `System.Random` class: `public Random() : this(Environment.TickCount)`. If two or more `Random` objects are instantiated in rapid succession (within the same millisecond), they both receive the identical seed value (`Environment.TickCount`). Because the pseudo-random number generator (PRNG) sequence is deterministic once seeded, these instances will produce the exact same sequence of "random" numbers, resulting in duplicated security tokens (such as password reset tokens). This issue is exacerbated when the application trusts this PRNG for security purposes.
## Exploitation
- Status: PoC available (The author demonstrated reproduction using Burp Suite Repeater Groups).
- Complexity: Medium (Requires precise timing control, utilizing techniques like the single packet attack, but requires no mathematical inversion of the PRNG algorithm initially.)
- Attack Vector: Network (Requires sending network requests to the vulnerable service).
## Impact
- Confidentiality: High (If an administrator or target user's token is predicted, session information may be compromised.)
- Integrity: High (Allows an attacker to impersonate a target user, particularly if they control one account involved in the collision to predict the token of another.)
- Availability: Low (No direct impact on system availability from token prediction alone.)
## Remediation
### Patches
- Specific patch versions are not listed, but the recommended remediation is to switch to a cryptographically secure PRNG for security tokens, such as `System.Security.Cryptography.RandomNumberGenerator`.
- For .NET Core/.NET 5+, applications should be aware that the default `Random` implementation has been updated (e.g., to use Xoshiro128StarStar and potentially a better seeding mechanism), though proper use of secure RNGs is always preferred.
### Workarounds
1. **Use Cryptographically Secure RNG:** Inject an explicit, securely generated seed or, preferably, use classes designated for cryptographic randomness (e.g., `RandomNumberGenerator.GetInt32(min, max)` in modern .NET).
2. **Introduce Intentional Delay:** If the use of `new Random()` cannot immediately be removed, introduce a controlled, system-independent delay between token generations to increase temporal separation beyond the 1ms resolution of `TickCount`.
3. **Audit Implementation:** Ensure that if manual seeding is required, the seed source is external and high-entropy, not derived from the system clock resolution that can be easily duplicated.
## Detection
- Indicators of Compromise: Receipt of duplicate tokens by two different target email addresses resulting from requests made in close temporal proximity.
- Detection Methods and Tools: Application fuzzing tools (like Burp Suite Repeater Groups executing race attacks) can test the 1ms timing window across multiple identical requests. Monitoring logs for requests that complete within a tightly constrained RTT window might indicate exploitation attempts.
## References
- Vendor Advisories: N/A (Issue found internally via application logic analysis.)
- Relevant Links:
- Doyensec Blog Post (Defanged): hXXps://blog.doyensec.com/2025/08/19/trivial-c-sharp-random-exploitation.html
- Single Packet Attack Documentation (Defanged): hXXps://portswigger.net/research/the-single-packet-attack-making-remote-race-conditions-local