Create rule S4347: Secure random number generators must not output predictable values #8992
Labels
Area: CFG/SE
CFG and SE related issues.
Area: Security
Related to Vulnerability and Security Hotspot rules
Type: New Rule
Implementation for a rule that HAS been specified.
Milestone
Why
As part of MMF-3716, we want to close the gap between C# and other languages regarding cryptography-related rules support. S4347 is one of the rules that is not currently supported by this analyzer.
What
S4347 aims to detect when a secure random number generator is used in a way where the output can become predictable. This is usually because it is not initialized correctly, or it is provided with a seed value that results in predictable output.
Detection Logic
.NET Framework and .NET Core
The random generators inside
System.Security.Cryptography
have no way to set a seed and are therefore always unpredictable.BouncyCastle.NET
Most of BouncyCastle's random number generators will create unpredictable output by default. There are only a small number of scenarios (see below) where a predictable random generator can be created. Each of these scenarios requires an unpredictable seed to be set before the random generator can create unpredictable output.
Ideally, these random generators would be seeded with at least 16 bytes of unpredictable material. This prevents a brute-force attack from guessing which seeds were used to create a set of given random values.
However, given the low expected impact of this rule (see below), the initial implementation will consider any
byte[]
,Span<byte>
orReadOnlySpan<byte>
to be unpredictable as long as it wasn't created from static data.The following methods are examples of how a seed can be created from static data:
new byte[] { /* static values */ }
byte[] System.Text.Encoding.GetBytes(string)
where thestring
is staticbyte[] System.Convert.FromBase64String(string)
where thestring
is staticbyte[] Guid.ToByteArray()
except where theGuid
was created byGuid.NewGuid()
Scenario 1:
SecureRandom
S4347 should be raised when the following conditions are met.
SecureRandom
instance is created by callingOrg.BouncyCastle.Security.SecureRandom.GetInstance(string algorithm, bool autoSeed)
whereautoSeed
=false
.SetSeed(...)
where the parameter is considered unpredictable (see above)..NextBytes(...)
.Next(...)
.NextInt()
.NextLong()
.NextDouble()
Scenario 2:
IRandomGenerator
S4347 should be raised when the following conditions are met.
IRandomGenerator
instance is created using one of the following constructors:new Org.BouncyCastle.Crypto.Prng.DigestRandomGenerator(Org.BouncyCastle.Crypto.IDigest digest)
new Org.BouncyCastle.Crypto.Prng.VmpcRandomGenerator()
.AddSeedMaterial(...)
where the parameter is considered unpredictable (see above)..NextBytes(...)
methods.Scenario 3:
IRandomGenerator
wrapped bySecureRandom
S4347 should be raised when the following conditions are met.
IRandomGenerator
instance (generator
) is created using one of the following constructors:new Org.BouncyCastle.Crypto.Prng.DigestRandomGenerator(Org.BouncyCastle.Crypto.IDigest digest)
new Org.BouncyCastle.Crypto.Prng.VmpcRandomGenerator()
SecureRandom
instance (rng
) is created to wrapgenerator
, using one of the following constructors:new Org.BouncyCastle.Security.SecureRandom(generator)
new Org.BouncyCastle.Security.SecureRandom(generator, autoSeedLength)
whereautoSeedLength
is less than 16.generator
using either of the following methods:generator.AddSeedMaterial(...)
rng.SetSeed(...)
generator.NextBytes(...)
rng.NextBytes(...)
rng.Next(...)
rng.NextInt()
rng.NextLong()
rng.NextDouble()
Highlighting and Error Message
The primary highlight should be the RNG instance plus the function name that generates the random value, e.g.
rng1.NextBytes
.A secondary highlight should be added to the location where the RNG was created, either via
SecureRandom.GetInstance
ornew ___RandomGenerator
.For scenario 3, another secondary highlight should be added to the location where
new SecureRandom(...)
is called.Use the following error message:
Expected Impact
SourceGraph does not reveal any public code where noncompliant patterns are in use.
The primary reason for implementing this rule is to ensure coverage for compliance schemes.
Associated RSPEC
When this change is in place, please merge the associated RSPEC content: RSPEC PR #3837
The text was updated successfully, but these errors were encountered: