Skip to content

Commit ff37b35

Browse files
authored
Merge pull request #9 from trailofbits/go-fix-dataflows-new
Go fix dataflows new
2 parents 23da6f6 + 37062f5 commit ff37b35

File tree

4 files changed

+42
-45
lines changed

4 files changed

+42
-45
lines changed

go/src/crypto/MsgNotHashedBeforeSigVerfication/MsgNotHashedBeforeSigVerfication.ql

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
*/
1212

1313
import go
14-
import DataFlow::PathGraph
15-
import semmle.go.dataflow.DataFlow2
1614

1715
/**
1816
* Function that performs signing or signature verification on a hash of a message
@@ -90,27 +88,25 @@ class HashFunction extends Function {
9088
}
9189
}
9290

93-
class LongestFlowConfig extends DataFlow2::Configuration {
94-
LongestFlowConfig() { this = "LongestFlowConfig" }
95-
override predicate isSource(DataFlow::Node source) { source = source }
96-
override predicate isSink(DataFlow::Node sink) { sink = sink }
91+
private module LongestFlowConfig implements DataFlow::ConfigSig {
92+
predicate isSource(DataFlow::Node source) { source = source }
93+
predicate isSink(DataFlow::Node sink) { sink = sink }
9794
}
95+
module LongestFlowFlow = DataFlow::Global<LongestFlowConfig>;
9896

9997
/**
10098
* Flows from anything to SignatureMsgTruncationFunction
10199
* that do not cross a hash function or slicing expression
102100
*/
103-
class AnythingToSignatureMsgTrunFuncFlow extends DataFlow::Configuration {
104-
AnythingToSignatureMsgTrunFuncFlow() { this = "AnythingToSignatureMsgTrunFuncFlow" }
105-
101+
module AnythingToSignatureMsgTrunFuncConfig implements DataFlow::ConfigSig {
106102
// anything that is not a function's argument
107103
// TODO: alternatively, set sources to be ExternalInputs
108-
override predicate isSource(DataFlow::Node source) {
109-
not this.isSink(source, _)
104+
predicate isSource(DataFlow::Node source) {
105+
not isSink(source)
110106
and not source.asInstruction() instanceof IR::ReadArgumentInstruction
111107
}
112108

113-
override predicate isSink(DataFlow::Node sink) {
109+
predicate isSink(DataFlow::Node sink) {
114110
exists(SignatureMsgTruncationFunction sigUseF, CallExpr sigUseCall, int position |
115111
sigUseCall.getTarget() = sigUseF
116112
and sigUseF.hashArgPosition(position)
@@ -122,7 +118,7 @@ class AnythingToSignatureMsgTrunFuncFlow extends DataFlow::Configuration {
122118
// * data goes through a hash function
123119
// * data is truncated with a hardcoded value
124120
// * TODO: data is of type Hash
125-
override predicate isBarrier(DataFlow::Node node) {
121+
predicate isBarrier(DataFlow::Node node) {
126122
// direct hash function call
127123
exists(HashFunction hf | hf.getACall().getResult(_) = node or hf.getACall().getArgument(_) = node)
128124
or
@@ -142,14 +138,17 @@ class AnythingToSignatureMsgTrunFuncFlow extends DataFlow::Configuration {
142138
node.asExpr().getType().getUnderlyingType().(ArrayType).getLength() <= 66
143139
}
144140
}
141+
module AnythingToSignatureMsgTrunFuncFlow = DataFlow::Global<AnythingToSignatureMsgTrunFuncConfig>;
142+
import AnythingToSignatureMsgTrunFuncFlow::PathGraph
145143

146-
from AnythingToSignatureMsgTrunFuncFlow config, DataFlow::PathNode source, DataFlow::PathNode sink
144+
from AnythingToSignatureMsgTrunFuncFlow::PathNode source, AnythingToSignatureMsgTrunFuncFlow::PathNode sink
147145
where
148-
config.hasFlowPath(source, sink)
146+
AnythingToSignatureMsgTrunFuncFlow::flowPath(source, sink)
149147

150148
// only the longest flow
151-
and not exists(LongestFlowConfig config2, DataFlow::Node source2 |
152-
config2.hasFlow(source2, source.getNode())
149+
// TODO: find only flows originating from user input
150+
and not exists(DataFlow::Node source2 |
151+
LongestFlowFlow::flow(source2, source.getNode())
153152
and source2 != source.getNode()
154153
)
155154

go/src/security/MissingMinVersionTLS/MissingMinVersionTLS.ql

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,11 @@ import go
1515
/**
1616
* Flow of a `tls.Config` to a write to the `MinVersion` field.
1717
*/
18-
class TlsVersionFlowConfig extends TaintTracking::Configuration {
19-
TlsVersionFlowConfig() { this = "TlsVersionFlowConfig" }
20-
18+
module TlsVersionConfig implements DataFlow::ConfigSig {
2119
/**
2220
* Holds if `source` is a TLS.Config instance.
2321
*/
24-
override predicate isSource(DataFlow::Node source) {
22+
predicate isSource(DataFlow::Node source) {
2523
exists(Variable v |
2624
configOrConfigPointer(v.getType()) and
2725
source.asExpr() = v.getAReference()
@@ -31,21 +29,21 @@ class TlsVersionFlowConfig extends TaintTracking::Configuration {
3129
/**
3230
* Holds if a write to `sink`.MinVersion exists.
3331
*/
34-
override predicate isSink(DataFlow::Node sink) {
32+
predicate isSink(DataFlow::Node sink) {
3533
exists(Write fieldWrite, Field fld |
3634
fld.hasQualifiedName( "crypto/tls", "Config", "MinVersion") and
3735
fieldWrite.writesField(sink, fld, _)
3836
)
3937
}
4038
}
39+
module TlsVersionFlow = TaintTracking::Global<TlsVersionConfig>;
40+
4141

4242
/**
4343
* Flow of a `tls.Config` with `MinVersion` to a variable.
4444
*/
45-
class TlsConfigCreation extends TaintTracking::Configuration {
46-
TlsConfigCreation() { this = "TlsConfigCreation" }
47-
48-
predicate isSecure(DataFlow::Node source) {
45+
module TlsConfigCreationConfig implements DataFlow::ConfigSig {
46+
additional predicate isSecure(DataFlow::Node source) {
4947
exists(StructLit lit, Field fld |
5048
lit.getType().hasQualifiedName("crypto/tls", "Config") and
5149
fld.hasQualifiedName("crypto/tls", "Config", "MinVersion") and
@@ -58,18 +56,19 @@ class TlsConfigCreation extends TaintTracking::Configuration {
5856
/**
5957
* Holds if `source` is a TLS.Config literal.
6058
*/
61-
override predicate isSource(DataFlow::Node source) {
59+
predicate isSource(DataFlow::Node source) {
6260
exists(StructLit lit, Field fld |
6361
lit.getType().hasQualifiedName("crypto/tls", "Config") and
6462
fld.hasQualifiedName("crypto/tls", "Config", "MinVersion") and
6563
source.asExpr() = lit
6664
)
65+
and not isSecure(source)
6766
}
6867

6968
/**
7069
* Holds if it is TLS.Config instance (a Variable).
7170
*/
72-
override predicate isSink(DataFlow::Node sink) {
71+
predicate isSink(DataFlow::Node sink) {
7372
exists(Variable v |
7473
sink.asExpr() = v.getAReference()
7574
)
@@ -78,10 +77,11 @@ class TlsConfigCreation extends TaintTracking::Configuration {
7877
/**
7978
* Holds if TLS.Config literal is saved in a structure's field
8079
*/
81-
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
80+
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
8281
exists(Write w | w.writesField(succ, _, pred))
8382
}
8483
}
84+
module TlsConfigCreationFlow = TaintTracking::Global<TlsConfigCreationConfig>;
8585

8686
/**
8787
* Holds if `t` is a TLS.Config type or a pointer to it (or ptr to ptr...) or a struct containing it.
@@ -104,14 +104,13 @@ predicate configOrConfigPointer(Type t) {
104104
}
105105

106106
// v - a variable holding any structure which is or contains the tls.Config
107-
from StructLit configStruct, Variable v, TlsConfigCreation cfg, DataFlow::Node source, DataFlow::Node sink
107+
from StructLit configStruct, Variable v, DataFlow::Node source, DataFlow::Node sink
108108
where
109109
// find tls.Config structures with MinVersion not set on the structure initialization
110110
(
111-
cfg.hasFlow(source, sink) and
111+
TlsConfigCreationFlow::flow(source, sink) and
112112
sink.asExpr() = v.getAReference() and
113-
source.asExpr() = configStruct and
114-
not cfg.isSecure(source)
113+
source.asExpr() = configStruct
115114
)
116115

117116
// exclude if tls.Config is used as TLSClientConfig, as default for clients is TLS 1.2
@@ -143,8 +142,8 @@ where
143142
and if configOrConfigPointer(v.getType()) then
144143
(
145144
// exclude if there is a later write to MinVersion
146-
not exists(TlsVersionFlowConfig cfg2, DataFlow::Node source2, DataFlow::Node sink2 |
147-
cfg2.hasFlow(source2, sink2) and
145+
not exists(DataFlow::Node source2, DataFlow::Node sink2 |
146+
TlsVersionFlow::flow(source2, sink2) and
148147
source2.asExpr() = v.getAReference()
149148
)
150149
) else

go/src/security/TrimMisuse/TrimMisuse.ql

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,23 @@
1111
*/
1212

1313
import go
14-
import DataFlow
14+
import DataFlow2
1515

1616
/*
1717
* Flows from a string to TrimFamilyCall cutSet argument
1818
*/
19-
class Trim2ndArg extends DataFlow::Configuration {
20-
Trim2ndArg() { this = "Trim2ndArg" }
21-
22-
override predicate isSource(DataFlow::Node source) {
19+
module Trim2ndArgConfig implements DataFlow::ConfigSig {
20+
predicate isSource(DataFlow::Node source) {
2321
source.asExpr() instanceof StringLit
2422
}
2523

26-
override predicate isSink(DataFlow::Node sink) {
24+
predicate isSink(DataFlow::Node sink) {
2725
exists(TrimFamilyCall trimCall |
2826
sink.asExpr() = trimCall.getCutSetArg()
2927
)
3028
}
3129
}
30+
module Trim2ndArgFlow = DataFlow::Global<Trim2ndArgConfig>;
3231

3332
/*
3433
* Calls to Trim methods that we are interested in
@@ -49,8 +48,8 @@ class TrimFamilyCall extends CallNode {
4948
from TrimFamilyCall trimCall, StringLit cutset
5049
where
5150
// get 2nd argument value, if possible
52-
exists(Trim2ndArg config, DataFlow::Node source, DataFlow::Node sink |
53-
config.hasFlow(source, sink)
51+
exists(DataFlow::Node source, DataFlow::Node sink |
52+
Trim2ndArgFlow::flow(source, sink)
5453
and source.asExpr() = cutset
5554
and sink.asExpr() = trimCall.getCutSetArg()
5655
)

go/test/query-tests/crypto/MsgNotHashedBeforeSigVerfication/MsgNotHashedBeforeSigVerfication.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
edges
2-
| MsgNotHashedBeforeSigVerfication.go:78:33:78:46 | "test message" | MsgNotHashedBeforeSigVerfication.go:78:26:78:47 | type conversion |
3-
| MsgNotHashedBeforeSigVerfication.go:86:31:86:44 | "test message" | MsgNotHashedBeforeSigVerfication.go:86:24:86:45 | type conversion |
2+
| MsgNotHashedBeforeSigVerfication.go:78:33:78:46 | "test message" | MsgNotHashedBeforeSigVerfication.go:78:26:78:47 | type conversion | provenance | |
3+
| MsgNotHashedBeforeSigVerfication.go:86:31:86:44 | "test message" | MsgNotHashedBeforeSigVerfication.go:86:24:86:45 | type conversion | provenance | |
44
nodes
55
| MsgNotHashedBeforeSigVerfication.go:78:26:78:47 | type conversion | semmle.label | type conversion |
66
| MsgNotHashedBeforeSigVerfication.go:78:33:78:46 | "test message" | semmle.label | "test message" |

0 commit comments

Comments
 (0)