gitlab.security_code_scan.SCS0013-1
unknown
Download Count*
License
Cryptographic algorithms provide many different modes of operation, only some of which provide message integrity. Without message integrity it could be possible for an adversary to attempt to tamper with the ciphertext which could lead to compromising the encryption key. Newer algorithms apply message integrity to validate ciphertext has not been tampered with.
Instead of using an algorithm that requires configuring a CipherMode
, an algorithm
that has built-in message integrity should be used. If using .NET Framework greater
than version 6.0 consider using ChaCha20Poly1305
or AES-256-GCM
.
For older applications, AES-256-GCM
is recommended, however it has many drawbacks:
- Slower than
ChaCha20Poly1305
. - Catastrophic failure if nonce values are re-used.
Example using ChaCha20Poly1305
:
// Generate a random key
byte[] key = new byte[32];
RandomNumberGenerator.Fill(key);
ChaCha20Poly1305 encryptor = new ChaCha20Poly1305(key);
// Note nonce values _must_ be regenerated every time they are used.
var nonce = new byte[12];
RandomNumberGenerator.Fill(nonce);
byte[] plainText = System.Text.Encoding.UTF8.GetBytes("Secret text to encrypt");
byte[] cipherText = new byte[plainText.Length];
var authTag = new byte[16];
encryptor.Encrypt(nonce, plainText, cipherText, authTag);
byte[] output = new byte[cipherText.Length];
encryptor.Decrypt(nonce, cipherText, authTag, output);
Console.WriteLine("Output: {0}", System.Text.Encoding.UTF8.GetString(output));
Example using AES-256-GCM
:
var plaintextBytes = Encoding.UTF8.GetBytes("Secret text to encrypt");
var key = new byte[32];
RandomNumberGenerator.Fill(key);
using var aes = new AesGcm(key);
var nonce = new byte[AesGcm.NonceByteSizes.MaxSize];
RandomNumberGenerator.Fill(nonce);
var cipherText = new byte[plaintextBytes.Length];
var tag = new byte[AesGcm.TagByteSizes.MaxSize];
aes.Encrypt(nonce, plaintextBytes, cipherText, tag);
// Decrypt
using (var decrypt = new AesGcm(key))
{
var decryptedBytes = new byte[cipherText.Length];
decrypt.Decrypt(nonce, cipherText, tag, decryptedBytes);
Console.WriteLine("Decrypted: {0}", Encoding.UTF8.GetString(decryptedBytes));
}
Run Locally
Run in CI
Defintion
rules:
- id: security_code_scan.SCS0013-1
languages:
- csharp
patterns:
- pattern-inside: |
using System.Security.Cryptography;
...
- metavariable-regex:
metavariable: $CIPHER
regex: ^(ECB|CBC|OFB|CFB|CTS)$
- pattern: CipherMode.$CIPHER
message: >
Cryptographic algorithms provide many different modes of operation, only
some of which provide
message integrity. Without message integrity it could be possible for an adversary to attempt
to tamper with the ciphertext which could lead to compromising the encryption key. Newer
algorithms
apply message integrity to validate ciphertext has not been tampered with.
Instead of using an algorithm that requires configuring a `CipherMode`, an algorithm
that has built-in message integrity should be used. If using .NET Framework greater
than version 6.0 consider using `ChaCha20Poly1305` or `AES-256-GCM`.
For older applications, `AES-256-GCM` is recommended, however it has many drawbacks:
- Slower than `ChaCha20Poly1305`.
- Catastrophic failure if nonce values are re-used.
Example using `ChaCha20Poly1305`:
```
// Generate a random key
byte[] key = new byte[32];
RandomNumberGenerator.Fill(key);
ChaCha20Poly1305 encryptor = new ChaCha20Poly1305(key);
// Note nonce values _must_ be regenerated every time they are used.
var nonce = new byte[12];
RandomNumberGenerator.Fill(nonce);
byte[] plainText = System.Text.Encoding.UTF8.GetBytes("Secret text to encrypt");
byte[] cipherText = new byte[plainText.Length];
var authTag = new byte[16];
encryptor.Encrypt(nonce, plainText, cipherText, authTag);
byte[] output = new byte[cipherText.Length];
encryptor.Decrypt(nonce, cipherText, authTag, output);
Console.WriteLine("Output: {0}", System.Text.Encoding.UTF8.GetString(output));
```
Example using `AES-256-GCM`:
```
var plaintextBytes = Encoding.UTF8.GetBytes("Secret text to encrypt");
var key = new byte[32];
RandomNumberGenerator.Fill(key);
using var aes = new AesGcm(key);
var nonce = new byte[AesGcm.NonceByteSizes.MaxSize];
RandomNumberGenerator.Fill(nonce);
var cipherText = new byte[plaintextBytes.Length];
var tag = new byte[AesGcm.TagByteSizes.MaxSize];
aes.Encrypt(nonce, plaintextBytes, cipherText, tag);
// Decrypt
using (var decrypt = new AesGcm(key))
{
var decryptedBytes = new byte[cipherText.Length];
decrypt.Decrypt(nonce, cipherText, tag, decryptedBytes);
Console.WriteLine("Decrypted: {0}", Encoding.UTF8.GetString(decryptedBytes));
}
```
severity: WARNING
metadata:
shortDescription: Use of a broken or risky cryptographic algorithm
category: security
cwe: CWE-327
primary_identifier: security_code_scan.SCS0013-1
secondary_identifiers:
- name: SCS0013
type: security_code_scan_rule_id
value: SCS0013
license: MIT
vulnerability_class:
- Other
Short Link: https://sg.run/5gZ0