Skip to content

Commit 8208f92

Browse files
MathiasVPgeoffw0
authored andcommitted
An alternative design for 'cpp/cleartext-transmission'.
1 parent 041c2c7 commit 8208f92

File tree

1 file changed

+61
-56
lines changed

1 file changed

+61
-56
lines changed

cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql

Lines changed: 61 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -33,31 +33,71 @@ class SensitiveNode extends DataFlow::Node {
3333
}
3434
}
3535

36-
/**
37-
* A function call that sends or receives data over a network.
38-
*
39-
* note: functions such as `write` may be writing to a network source or a file. We could attempt to determine which, and sort results into `cpp/cleartext-transmission` and perhaps `cpp/cleartext-storage-file`. In practice it usually isn't very important which query reports a result as long as its reported exactly once. See `checkSocket` to narrow this down somewhat.
40-
*/
41-
abstract class NetworkSendRecv extends FunctionCall {
36+
abstract class SendRecv extends Function {
4237
/**
4338
* Gets the expression for the socket or similar object used for sending or
44-
* receiving data (if any).
39+
* receiving data through the function call `call` (if any).
4540
*/
46-
abstract Expr getSocketExpr();
41+
abstract Expr getSocketExpr(Call call);
4742

4843
/**
4944
* Gets the expression for the buffer to be sent from / received into.
5045
*/
51-
abstract Expr getDataExpr();
46+
abstract Expr getDataExpr(Call call);
47+
}
5248

53-
/**
54-
* Holds if the socket used by this call could be a true network socket (or
55-
* if no socket is specified). A constant value is likely to indicate standard
56-
* input, standard output or a similar non-network socket.
57-
*/
58-
predicate checkSocket() {
49+
class Send extends SendRecv instanceof RemoteFlowSinkFunction {
50+
override Expr getSocketExpr(Call call) {
51+
call.getTarget() = this and
52+
exists(FunctionInput input, int arg |
53+
super.hasSocketInput(input) and
54+
input.isParameter(arg) and
55+
result = call.getArgument(arg)
56+
)
57+
}
58+
59+
override Expr getDataExpr(Call call) {
60+
call.getTarget() = this and
61+
exists(FunctionInput input, int arg |
62+
super.hasRemoteFlowSink(input, _) and
63+
input.isParameterDeref(arg) and
64+
result = call.getArgument(arg)
65+
)
66+
}
67+
}
68+
69+
class Recv extends SendRecv instanceof RemoteFlowSourceFunction {
70+
override Expr getSocketExpr(Call call) {
71+
call.getTarget() = this and
72+
exists(FunctionInput input, int arg |
73+
super.hasSocketInput(input) and
74+
input.isParameter(arg) and
75+
result = call.getArgument(arg)
76+
)
77+
}
78+
79+
override Expr getDataExpr(Call call) {
80+
call.getTarget() = this and
81+
exists(FunctionOutput output, int arg |
82+
super.hasRemoteFlowSource(output, _) and
83+
output.isParameterDeref(arg) and
84+
result = call.getArgument(arg)
85+
)
86+
}
87+
}
88+
89+
/**
90+
* A function call that sends or receives data over a network.
91+
*
92+
* note: functions such as `write` may be writing to a network source or a file. We could attempt to determine which, and sort results into `cpp/cleartext-transmission` and perhaps `cpp/cleartext-storage-file`. In practice it usually isn't very important which query reports a result as long as its reported exactly once. See `checkSocket` to narrow this down somewhat.
93+
*/
94+
abstract class NetworkSendRecv extends FunctionCall {
95+
SendRecv target;
96+
97+
NetworkSendRecv() {
98+
this.getTarget() = target and
5999
not exists(GVN g |
60-
g = globalValueNumber(getSocketExpr()) and
100+
g = globalValueNumber(target.getSocketExpr(this)) and
61101
(
62102
// literal constant
63103
globalValueNumber(any(Literal l)) = g
@@ -70,56 +110,22 @@ abstract class NetworkSendRecv extends FunctionCall {
70110
)
71111
)
72112
}
113+
114+
final Expr getDataExpr() { result = target.getDataExpr(this) }
73115
}
74116

75117
/**
76118
* A function call that sends data over a network.
77119
*/
78120
class NetworkSend extends NetworkSendRecv {
79-
RemoteFlowSinkFunction target;
80-
81-
NetworkSend() { target = this.getTarget() }
82-
83-
override Expr getSocketExpr() {
84-
exists(FunctionInput input, int arg |
85-
target.hasSocketInput(input) and
86-
input.isParameter(arg) and
87-
result = this.getArgument(arg)
88-
)
89-
}
90-
91-
override Expr getDataExpr() {
92-
exists(FunctionInput input, int arg |
93-
target.hasRemoteFlowSink(input, _) and
94-
input.isParameterDeref(arg) and
95-
result = this.getArgument(arg)
96-
)
97-
}
121+
override Send target;
98122
}
99123

100124
/**
101125
* A function call that receives data over a network.
102126
*/
103127
class NetworkRecv extends NetworkSendRecv {
104-
RemoteFlowSourceFunction target;
105-
106-
NetworkRecv() { target = this.getTarget() }
107-
108-
override Expr getSocketExpr() {
109-
exists(FunctionInput input, int arg |
110-
target.hasSocketInput(input) and
111-
input.isParameter(arg) and
112-
result = this.getArgument(arg)
113-
)
114-
}
115-
116-
override Expr getDataExpr() {
117-
exists(FunctionOutput output, int arg |
118-
target.hasRemoteFlowSource(output, _) and
119-
output.isParameterDeref(arg) and
120-
result = this.getArgument(arg)
121-
)
122-
}
128+
override Recv target;
123129
}
124130

125131
/**
@@ -147,7 +153,7 @@ class FromSensitiveConfiguration extends TaintTracking::Configuration {
147153
override predicate isSource(DataFlow::Node source) { source instanceof SensitiveNode }
148154

149155
override predicate isSink(DataFlow::Node sink) {
150-
sink.asExpr() = any(NetworkSendRecv nsr | nsr.checkSocket()).getDataExpr()
156+
sink.asExpr() = any(NetworkSendRecv nsr).getDataExpr()
151157
or
152158
sink.asExpr() instanceof Encrypted
153159
}
@@ -169,7 +175,6 @@ where
169175
// flow from sensitive -> network data
170176
config.hasFlowPath(source, sink) and
171177
sink.getNode().asExpr() = networkSendRecv.getDataExpr() and
172-
networkSendRecv.checkSocket() and
173178
// no flow from sensitive -> evidence of encryption
174179
not exists(DataFlow::Node encrypted |
175180
config.hasFlow(source.getNode(), encrypted) and

0 commit comments

Comments
 (0)