Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f55f27b

Browse files
committed
Expand handling of generic artifact sources
1 parent eb91ecf commit f55f27b

4 files changed

Lines changed: 147 additions & 36 deletions

File tree

java/ql/lib/experimental/Quantum/JCA.qll

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,16 +125,10 @@ module JCAModel {
125125
}
126126
}
127127

128-
class CipherUpdateCall extends MethodCall {
129-
CipherUpdateCall() { this.getMethod().hasQualifiedName("javax.crypto", "Cipher", "update") }
130-
131-
DataFlow::Node getInputData() { result.asExpr() = this.getArgument(0) }
132-
}
133-
134128
private newtype TCipherModeFlowState =
135129
TUninitializedCipherModeFlowState() or
136130
TInitializedCipherModeFlowState(CipherInitCall call) or
137-
TUsedCipherModeFlowState(CipherInitCall init, CipherUpdateCall update)
131+
TUsedCipherModeFlowState(CipherInitCall init)
138132

139133
abstract private class CipherModeFlowState extends TCipherModeFlowState {
140134
string toString() {

java/ql/lib/experimental/Quantum/Language.qll

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ private import java as Language
33
private import semmle.code.java.security.InsecureRandomnessQuery
44
private import semmle.code.java.security.RandomQuery
55
private import semmle.code.java.dataflow.DataFlow
6+
private import semmle.code.java.dataflow.FlowSources
67

78
private class UnknownLocation extends Language::Location {
89
UnknownLocation() { this.getFile().getAbsolutePath() = "" }
@@ -31,6 +32,25 @@ module CryptoInput implements InputSig<Language::Location> {
3132
*/
3233
module Crypto = CryptographyBase<Language::Location, CryptoInput>;
3334

35+
/**
36+
* Definitions of various generic data sources
37+
*/
38+
final class DefaultFlowSource = SourceNode;
39+
40+
final class DefaultRemoteFlowSource = RemoteFlowSource;
41+
42+
class GenericLocalDataSource extends Crypto::GenericRemoteDataSource {
43+
GenericLocalDataSource() {
44+
any(DefaultFlowSource src | not src instanceof DefaultRemoteFlowSource).asExpr() = this
45+
}
46+
47+
override DataFlow::Node asOutputData() { result.asExpr() = this }
48+
49+
override predicate flowsTo(Crypto::ArtifactLocatableElement other) {
50+
DataSourceToArtifactFlow::flow(this.asOutputData(), other.getInput())
51+
}
52+
}
53+
3454
/**
3555
* Random number generation, where each instance is modelled as the expression
3656
* tied to an output node (i.e., the result of the source of randomness)
@@ -70,5 +90,20 @@ module RNGToArtifactFlowConfig implements DataFlow::ConfigSig {
7090

7191
module RNGToArtifactFlow = DataFlow::Global<RNGToArtifactFlowConfig>;
7292

93+
/**
94+
* Generic data source to artifact flow configuration
95+
*/
96+
module DataSourceToArtifactFlowConfig implements DataFlow::ConfigSig {
97+
predicate isSource(DataFlow::Node source) {
98+
source = any(Crypto::GenericDataSourceInstance i).asOutputData()
99+
}
100+
101+
predicate isSink(DataFlow::Node sink) {
102+
sink = any(Crypto::ArtifactLocatableElement other).getInput()
103+
}
104+
}
105+
106+
module DataSourceToArtifactFlow = DataFlow::Global<DataSourceToArtifactFlowConfig>;
107+
73108
// Import library-specific modeling
74109
import JCA

java/ql/src/experimental/Quantum/TestCipher.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ where
1313
p = a.getPadding() and
1414
nonce = op.getNonce()
1515
select op, op.getCipherOperationMode(), a, a.getRawAlgorithmName(), m, m.getRawAlgorithmName(), p,
16-
p.getRawAlgorithmName(), nonce, nonce.getInputData()
16+
p.getRawAlgorithmName(), nonce

shared/cryptography/codeql/cryptography/Model.qll

Lines changed: 110 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,30 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
136136
abstract predicate flowsTo(ArtifactLocatableElement other);
137137
}
138138

139-
newtype TGenericDataSourceType =
140-
FilesystemDataSource() or
141-
ExternalLibraryDataSource() or
142-
MemoryAllocationDataSource() or
143-
ConstantDataSource()
139+
// TODO: WARNING:
140+
// If this overlaps with any other LocatableElement, there will be a cross-product
141+
// This is never to be used for unknowns
142+
abstract class GenericDataSourceInstance extends ArtifactLocatableElement {
143+
final override DataFlowNode getInput() { none() }
144+
145+
abstract string getLabel();
146+
}
147+
148+
abstract class GenericConstantOrAllocationSource extends GenericDataSourceInstance {
149+
final override string getLabel() { result = "ConstantData" } // TODO: toString of source?
150+
}
151+
152+
abstract class GenericExternalCallSource extends GenericDataSourceInstance {
153+
final override string getLabel() { result = "ExternalCall" } // TODO: call target name or toString of source?
154+
}
144155

145-
abstract class GenericDataSourceInstance extends ArtifactLocatableElement { }
156+
abstract class GenericRemoteDataSource extends GenericDataSourceInstance {
157+
final override string getLabel() { result = "RemoteData" } // TODO: toString of source?
158+
}
159+
160+
abstract class GenericLocalDataSource extends GenericDataSourceInstance {
161+
final override string getLabel() { result = "LocalData" } // TODO: toString of source?
162+
}
146163

147164
abstract class DigestArtifactInstance extends ArtifactLocatableElement { }
148165

@@ -224,7 +241,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
224241
* This predicate is overriden by derived classes to construct the graph of cryptographic operations.
225242
*/
226243
predicate properties(string key, string value, Location location) {
227-
key = "origin" and
244+
key = "Origin" and
228245
location = this.getOrigin(value).getLocation() and
229246
not location = this.getLocation()
230247
}
@@ -249,18 +266,65 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
249266
*/
250267
abstract ArtifactLocatableElement asArtifactLocatableElement();
251268

269+
/**
270+
* Gets the `Artifact` node that is the data source for this artifact.
271+
*/
252272
final Artifact getSourceArtifact() {
253-
not result = this and
254-
result.asArtifactLocatableElement().flowsTo(this.asArtifactLocatableElement())
273+
result.asArtifactLocatableElement() = this.getSourceArtifactElement()
274+
}
275+
276+
/**
277+
* Gets the `ArtifactLocatableElement` that is the data source for this artifact.
278+
*
279+
* This predicate is equivalent to `getSourceArtifact().asArtifactLocatableElement()`.
280+
*/
281+
final ArtifactLocatableElement getSourceArtifactElement() {
282+
not result = this.asArtifactLocatableElement() and
283+
result.flowsTo(this.asArtifactLocatableElement())
255284
}
256285

257286
override NodeBase getChild(string edgeName) {
258287
result = super.getChild(edgeName)
259288
or
260-
// [ONLY_KNOWN] - TODO: unknown case handled by reporting a generic source type or unknown as a property
261-
edgeName = "source" and
289+
// [ONLY_KNOWN] - TODO: known-unknown case handled by reporting a generic source type or unknown as a property
290+
edgeName = "Source" and
262291
result = this.getSourceArtifact()
263292
}
293+
294+
// TODO: document the below
295+
final private predicate src_generic_data_source_to_label_and_loc(string label, Location location) {
296+
exists(GenericDataSourceInstance instance |
297+
this.getSourceArtifactElement() = instance and
298+
instance.getLabel() = label and
299+
instance.getLocation() = location
300+
)
301+
}
302+
303+
final private predicate src_artifact_to_label_and_loc(string label, Location location) {
304+
exists(Artifact a |
305+
this.getSourceArtifact() = a and
306+
a.getInternalType() = label and
307+
a.getLocation() = location
308+
)
309+
}
310+
311+
final private predicate source_type_property(string key, string value, Location location) {
312+
key = "SourceType" and
313+
if this.src_artifact_to_label_and_loc(_, _)
314+
then this.src_artifact_to_label_and_loc(value, location)
315+
else
316+
if
317+
exists(this.asArtifactLocatableElement().getInput()) and
318+
not this.src_generic_data_source_to_label_and_loc(_, _)
319+
then value instanceof UnknownPropertyValue and location instanceof UnknownLocation
320+
else this.src_generic_data_source_to_label_and_loc(value, location)
321+
}
322+
323+
override predicate properties(string key, string value, Location location) {
324+
super.properties(key, value, location)
325+
or
326+
this.source_type_property(key, value, location)
327+
}
264328
}
265329

266330
/**
@@ -309,7 +373,25 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
309373
override NodeBase getChild(string edgeName) {
310374
result = super.getChild(edgeName)
311375
or
312-
edgeName = "uses" and
376+
/*
377+
* TODO: Consider a case with getProperty, where an unknown value is loaded from the filesystem,
378+
* but a default is specified as such:
379+
* String value = getProperty("property", "default_algorithm")
380+
* In this case, getAlgorithm *could* be resolved to default_algorithm, but in that case, the known
381+
* unknown case, i.e., what is loaded from `property`, would not be reported at all as a known unknown.
382+
*
383+
* Implementation brainstorming:
384+
* We have two cases, and we only considered one before: the case where we can't point to the known unknown.
385+
* The new case is pointing to a known unknown, e.g., "property" loaded via getProperty.
386+
* A potential solution is to create a known unknown node for each node type (particularly algorithms)
387+
* and model those elements in the database to associate with that known unknown type??
388+
*
389+
* - Idea: use the generic data source concept as the definition of potential known unknowns.
390+
* flow should be tracked from them to anything that could be a "sink" that specifies the relation.
391+
* in this case, the sink would be an instantiaition of an algorithm where the value is not resolvable.
392+
*/
393+
394+
edgeName = "Uses" and
313395
if exists(this.getAlgorithm()) then result = this.getAlgorithm() else result = this
314396
}
315397
}
@@ -336,10 +418,10 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
336418
super.properties(key, value, location)
337419
or
338420
// [ONLY_KNOWN]
339-
key = "name" and value = this.getAlgorithmName() and location = this.getLocation()
421+
key = "Name" and value = this.getAlgorithmName() and location = this.getLocation()
340422
or
341423
// [ONLY_KNOWN]
342-
key = "raw_name" and value = this.getRawAlgorithmName() and location = this.getLocation()
424+
key = "RawName" and value = this.getRawAlgorithmName() and location = this.getLocation()
343425
}
344426
}
345427

@@ -445,7 +527,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
445527
super.properties(key, value, location)
446528
or
447529
// [KNOWN_OR_UNKNOWN]
448-
key = "digest_size" and
530+
key = "DigestSize" and
449531
if exists(this.getDigestSize(location))
450532
then value = this.getDigestSize(location)
451533
else (
@@ -492,7 +574,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
492574
or
493575
(
494576
// [KNOWN_OR_UNKNOWN]
495-
edgeName = "uses" and
577+
edgeName = "Uses" and
496578
if exists(this.getHashAlgorithm()) then result = this.getHashAlgorithm() else result = this
497579
)
498580
}
@@ -526,7 +608,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
526608
or
527609
(
528610
// [KNOWN_OR_UNKNOWN]
529-
key = "iterations" and
611+
key = "Iterations" and
530612
if exists(this.getIterationCount(location))
531613
then value = this.getIterationCount(location)
532614
else (
@@ -536,7 +618,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
536618
or
537619
(
538620
// [KNOWN_OR_UNKNOWN]
539-
key = "key_len" and
621+
key = "KeyLength" and
540622
if exists(this.getKeyLength(location))
541623
then value = this.getKeyLength(location)
542624
else (
@@ -580,7 +662,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
580662
or
581663
(
582664
// [KNOWN_OR_UNKNOWN]
583-
key = "iterations" and
665+
key = "Iterations" and
584666
if exists(this.getIterationCount(location))
585667
then value = this.getIterationCount(location)
586668
else (
@@ -590,7 +672,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
590672
or
591673
(
592674
// [KNOWN_OR_UNKNOWN]
593-
key = "id_byte" and
675+
key = "IdByte" and
594676
if exists(this.getIDByte(location))
595677
then value = this.getIDByte(location)
596678
else (
@@ -661,7 +743,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
661743
or
662744
(
663745
// [KNOWN_OR_UNKNOWN]
664-
key = "key_len" and
746+
key = "KeyLength" and
665747
if exists(this.getDerivedKeyLength(location))
666748
then value = this.getDerivedKeyLength(location)
667749
else (
@@ -714,7 +796,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
714796
super.properties(key, value, location)
715797
or
716798
// [KNOWN_OR_UNKNOWN]
717-
key = "key_size" and
799+
key = "KeySize" and
718800
if exists(this.getKeySize(location))
719801
then value = this.getKeySize(location)
720802
else (
@@ -795,15 +877,15 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
795877
result = super.getChild(key)
796878
or
797879
// [KNOWN_OR_UNKNOWN]
798-
key = "nonce" and
880+
key = "Nonce" and
799881
if exists(this.getNonce()) then result = this.getNonce() else result = this
800882
}
801883

802884
override predicate properties(string key, string value, Location location) {
803885
super.properties(key, value, location)
804886
or
805887
// [ALWAYS_KNOWN] - Unknown is handled in getCipherOperationMode()
806-
key = "operation" and
888+
key = "Operation" and
807889
value = this.getCipherOperationMode().toString() and
808890
location = this.getLocation()
809891
}
@@ -1014,27 +1096,27 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
10141096
result = super.getChild(edgeName)
10151097
or
10161098
// [KNOWN_OR_UNKNOWN]
1017-
edgeName = "mode" and
1099+
edgeName = "Mode" and
10181100
if exists(this.getModeOfOperation())
10191101
then result = this.getModeOfOperation()
10201102
else result = this
10211103
or
10221104
// [KNOWN_OR_UNKNOWN]
1023-
edgeName = "padding" and
1105+
edgeName = "Padding" and
10241106
if exists(this.getPadding()) then result = this.getPadding() else result = this
10251107
}
10261108

10271109
override predicate properties(string key, string value, Location location) {
10281110
super.properties(key, value, location)
10291111
or
10301112
// [ALWAYS_KNOWN] - unknown case is handled in `getCipherStructureTypeString`
1031-
key = "structure" and
1113+
key = "Structure" and
10321114
getCipherStructureTypeString(this.getCipherStructure()) = value and
10331115
location instanceof UnknownLocation
10341116
or
10351117
(
10361118
// [KNOWN_OR_UNKNOWN]
1037-
key = "key_size" and
1119+
key = "KeySize" and
10381120
if exists(this.getKeySize(location))
10391121
then value = this.getKeySize(location)
10401122
else (

0 commit comments

Comments
 (0)