New queries to detect unsafe client side encryption in Azure Storage

This commit is contained in:
Raul Garcia
2022-07-01 17:08:35 -07:00
parent e98bdbf73f
commit e43e5810cf
9 changed files with 380 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
var client = new BlobClient(myConnectionString, new SpecializedBlobClientOptions()
{
// BAD: Using an outdated SDK that does not support client side encryption version V2_0
ClientSideEncryption = new ClientSideEncryptionOptions()
{
KeyEncryptionKey = myKey,
KeyResolver = myKeyResolver,
KeyWrapAlgorihm = myKeyWrapAlgorithm
}
});
var client = new BlobClient(myConnectionString, new SpecializedBlobClientOptions()
{
// BAD: Using the outdated client side encryption version V1_0
ClientSideEncryption = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V1_0)
{
KeyEncryptionKey = myKey,
KeyResolver = myKeyResolver,
KeyWrapAlgorihm = myKeyWrapAlgorithm
}
});
var client = new BlobClient(myConnectionString, new SpecializedBlobClientOptions()
{
// GOOD: Using client side encryption version V2_0
ClientSideEncryption = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V2_0)
{
KeyEncryptionKey = myKey,
KeyResolver = myKeyResolver,
KeyWrapAlgorihm = myKeyWrapAlgorithm
}
});

View File

@@ -0,0 +1,31 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>Azure Storage .NET, Java, and Python SDKs support encryption on the client with a customer-managed key that is maintained in Azure Key Vault or another key store.</p>
<p>Current release versions of the Azure Storage SDKs use cipher block chaining (CBC mode) for client-side encryption (referred to as <code>v1</code>).</p>
</overview>
<recommendation>
<p>Consider switching to <code>v1</code> client-side encryption.</p>
</recommendation>
<example>
<p>The following example shows an HTTP request parameter being used directly in a forming a
new request without validating the input, which facilitates SSRF attacks.
It also shows how to remedy the problem by validating the user input against a known fixed string.
</p>
<sample src="UnsafeUsageOfClientSideEncryptionVersion.cs" />
</example>
<references>
<li>
<a href="http://aka.ms/azstorageclientencryptionblog">Azure Storage Client Encryption Blog.</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,75 @@
/**
* @name Unsafe usage of v1 version of Azure Storage client-side encryption (CVE-2022-PENDING).
* @description Unsafe usage of v1 version of Azure Storage client-side encryption, please refer to http://aka.ms/azstorageclientencryptionblog
* @kind problem
* @tags security
* cryptography
* external/cwe/cwe-327
* @id cs/azure-storage/unsafe-usage-of-client-side-encryption-version
* @problem.severity error
* @precision high
*/
import csharp
/**
* Holds if `oc` is creating an object of type `c` = `Azure.Storage.ClientSideEncryptionOptions`
* and `e` is the `version` argument to the contructor
*/
predicate isCreatingAzureClientSideEncryptionObject(ObjectCreation oc, Class c, Expr e) {
exists(Parameter p | p.hasName("version") |
c.getQualifiedName() in ["Azure.Storage.ClientSideEncryptionOptions"] and
oc.getTarget() = c.getAConstructor() and
e = oc.getArgumentForParameter(p)
)
}
/**
* Holds if `oc` is an object creation of the outdated type `c` = `Microsoft.Azure.Storage.Blob.BlobEncryptionPolicy`
*/
predicate isCreatingOutdatedAzureClientSideEncryptionObject(ObjectCreation oc, Class c) {
c.getQualifiedName() in ["Microsoft.Azure.Storage.Blob.BlobEncryptionPolicy"] and
oc.getTarget() = c.getAConstructor()
}
/**
* Holds if the Azure.Storage assembly for `c` is a version knwon to support
* version 2+ for client-side encryption and if the argument for the constructor `version`
* is set to a secure value.
*/
predicate isObjectCreationSafe(Class c, Expr versionExpr, Assembly asm) {
// Check if the Azure.Storage assembly version has the fix
exists(int versionCompare |
versionCompare = asm.getVersion().compareTo("12.12.0.0") and
versionCompare >= 0
) and
// and that the version argument for the constructor is guaranteed to be Version2
isExprAnAccessToSafeClientSideEncryptionVersionValue(versionExpr)
}
/**
* Holds if the expression `e` is an access to a safe version of the enum `ClientSideEncryptionVersion`
* or an equivalent numeric value
*/
predicate isExprAnAccessToSafeClientSideEncryptionVersionValue(Expr e) {
exists(EnumConstant ec |
ec.hasQualifiedName("Azure.Storage.ClientSideEncryptionVersion.V2_0") and
ec.getAnAccess() = e
)
or
e.getValue().toInt() >= 2
}
from Expr e, Class c, Assembly asm
where
asm = c.getLocation() and
(
exists(Expr e2 |
isCreatingAzureClientSideEncryptionObject(e, c, e2) and
not isObjectCreationSafe(c, e2, asm)
)
or
isCreatingOutdatedAzureClientSideEncryptionObject(e, c)
)
select e,
"Unsafe usage of v1 version of Azure Storage client-side encryption (CVE-2022-PENDING). See http://aka.ms/azstorageclientencryptionblog"