Skip to content

Commit 8ea6b6f

Browse files
committed
Python: Update py/azure-storage/unsafe-client-side-encryption-in-use to use datafow
1 parent 7a17cd2 commit 8ea6b6f

File tree

2 files changed

+59
-29
lines changed

2 files changed

+59
-29
lines changed
Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @name Unsafe usage of v1 version of Azure Storage client-side encryption.
33
* @description Using version v1 of Azure Storage client-side encryption is insecure, and may enable an attacker to decrypt encrypted data
4-
* @kind problem
4+
* @kind path-problem
55
* @tags security
66
* experimental
77
* cryptography
@@ -15,33 +15,44 @@ import python
1515
import semmle.python.dataflow.new.DataFlow
1616
import semmle.python.ApiGraphs
1717

18-
predicate isUnsafeClientSideAzureStorageEncryptionViaAttributes(Call call, AttrNode node) {
19-
exists(
20-
API::Node client, DataFlow::AttrWrite keyAttrWrite, DataFlow::MethodCallNode uploadBlobCall
21-
|
22-
call = uploadBlobCall.asExpr() and node = keyAttrWrite.asCfgNode()
23-
|
24-
client =
25-
API::moduleImport("azure")
26-
.getMember("storage")
27-
.getMember("blob")
28-
.getMember(["ContainerClient", "BlobClient", "BlobServiceClient"])
29-
.getAMember()
30-
.getReturn() and
31-
keyAttrWrite
32-
.accesses(client.getAValueReachableFromSource(),
33-
["key_encryption_key", "key_resolver_function"]) and
34-
uploadBlobCall.calls(client.getAValueReachableFromSource(), "upload_blob") and
35-
DataFlow::localFlow(keyAttrWrite.getObject(), uploadBlobCall.getObject()) and
36-
not exists(DataFlow::AttrWrite encryptionVersionWrite |
37-
encryptionVersionWrite.accesses(client.getAValueReachableFromSource(), "encryption_version") and
38-
encryptionVersionWrite.getValue().asExpr().(StrConst).getText() in ["'2.0'", "2.0"] and
39-
DataFlow::localFlow(keyAttrWrite.getObject(), encryptionVersionWrite.getObject()) and
40-
DataFlow::localFlow(encryptionVersionWrite.getObject(), uploadBlobCall.getObject())
18+
API::Node getClient() {
19+
result =
20+
API::moduleImport("azure")
21+
.getMember("storage")
22+
.getMember("blob")
23+
.getMember(["ContainerClient", "BlobClient", "BlobServiceClient"])
24+
.getAMember()
25+
.getReturn()
26+
}
27+
28+
module AzureBlobClientConfig implements DataFlow::ConfigSig {
29+
predicate isSource(DataFlow::Node node) {
30+
exists(DataFlow::AttrWrite attr |
31+
node = getClient().getAValueReachableFromSource() and
32+
attr.accesses(node, ["key_encryption_key", "key_resolver_function"])
33+
)
34+
}
35+
36+
predicate isBarrier(DataFlow::Node node) {
37+
exists(DataFlow::AttrWrite attr |
38+
node = getClient().getAValueReachableFromSource() and
39+
attr.accesses(node, "encryption_version") and
40+
attr.getValue().asExpr().(StrConst).getText() in ["'2.0'", "2.0"]
4141
)
42-
)
42+
}
43+
44+
predicate isSink(DataFlow::Node node) {
45+
exists(DataFlow::MethodCallNode call |
46+
call = getClient().getMember("upload_blob").getACall() and
47+
node = call.getObject()
48+
)
49+
}
4350
}
4451

45-
from Call call, ControlFlowNode node
46-
where isUnsafeClientSideAzureStorageEncryptionViaAttributes(call, node)
47-
select node, "Unsafe usage of v1 version of Azure Storage client-side encryption."
52+
module AzureBlobClient = DataFlow::Global<AzureBlobClientConfig>;
53+
54+
import AzureBlobClient::PathGraph
55+
56+
from AzureBlobClient::PathNode source, AzureBlobClient::PathNode sink
57+
where AzureBlobClient::flowPath(source, sink)
58+
select sink, source, sink, "Unsafe usage of v1 version of Azure Storage client-side encryption"
Original file line numberDiff line numberDiff line change
@@ -1 +1,20 @@
1-
| test.py:8:5:8:34 | ControlFlowNode for Attribute | Unsafe usage of v1 version of Azure Storage client-side encryption. |
1+
edges
2+
| test.py:8:5:8:15 | ControlFlowNode for blob_client | test.py:10:9:10:19 | ControlFlowNode for blob_client |
3+
| test.py:16:5:16:15 | ControlFlowNode for blob_client | test.py:22:9:22:19 | ControlFlowNode for blob_client |
4+
| test.py:38:5:38:15 | ControlFlowNode for blob_client | test.py:39:12:39:22 | ControlFlowNode for blob_client |
5+
| test.py:39:12:39:22 | ControlFlowNode for blob_client | test.py:43:10:43:33 | ControlFlowNode for get_unsafe_blob_client() |
6+
| test.py:43:10:43:33 | ControlFlowNode for get_unsafe_blob_client() | test.py:45:9:45:10 | ControlFlowNode for bc |
7+
nodes
8+
| test.py:8:5:8:15 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client |
9+
| test.py:10:9:10:19 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client |
10+
| test.py:16:5:16:15 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client |
11+
| test.py:22:9:22:19 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client |
12+
| test.py:38:5:38:15 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client |
13+
| test.py:39:12:39:22 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client |
14+
| test.py:43:10:43:33 | ControlFlowNode for get_unsafe_blob_client() | semmle.label | ControlFlowNode for get_unsafe_blob_client() |
15+
| test.py:45:9:45:10 | ControlFlowNode for bc | semmle.label | ControlFlowNode for bc |
16+
subpaths
17+
#select
18+
| test.py:10:9:10:19 | ControlFlowNode for blob_client | test.py:8:5:8:15 | ControlFlowNode for blob_client | test.py:10:9:10:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
19+
| test.py:22:9:22:19 | ControlFlowNode for blob_client | test.py:16:5:16:15 | ControlFlowNode for blob_client | test.py:22:9:22:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
20+
| test.py:45:9:45:10 | ControlFlowNode for bc | test.py:38:5:38:15 | ControlFlowNode for blob_client | test.py:45:9:45:10 | ControlFlowNode for bc | Unsafe usage of v1 version of Azure Storage client-side encryption |

0 commit comments

Comments
 (0)