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

Skip to content

Commit 7ad781e

Browse files
committed
C++: Repair the 'cpp/cleartext-transmission' query in preparation for IR-based use-use dataflow.
1 parent d62ae96 commit 7ad781e

3 files changed

Lines changed: 292 additions & 428 deletions

File tree

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

Lines changed: 87 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import cpp
1616
import semmle.code.cpp.security.SensitiveExprs
1717
import semmle.code.cpp.security.PrivateData
1818
import semmle.code.cpp.dataflow.TaintTracking
19+
import semmle.code.cpp.dataflow.TaintTracking2
20+
import semmle.code.cpp.dataflow.TaintTracking3
1921
import semmle.code.cpp.models.interfaces.FlowSource
2022
import semmle.code.cpp.commons.File
2123
import DataFlow::PathGraph
@@ -34,21 +36,6 @@ class SourceFunction extends Function {
3436
}
3537
}
3638

37-
/**
38-
* A DataFlow node corresponding to a variable or function call that
39-
* might contain or return a password or other sensitive information.
40-
*/
41-
class SourceNode extends DataFlow::Node {
42-
SourceNode() {
43-
this.asExpr() = any(SourceVariable sv).getInitializer().getExpr() or
44-
this.asExpr().(VariableAccess).getTarget() = any(SourceVariable sv).(GlobalOrNamespaceVariable) or
45-
this.asExpr().(VariableAccess).getTarget() = any(SourceVariable v | v instanceof Field) or
46-
this.asUninitialized() instanceof SourceVariable or
47-
this.asParameter() instanceof SourceVariable or
48-
this.asExpr().(FunctionCall).getTarget() instanceof SourceFunction
49-
}
50-
}
51-
5239
/**
5340
* A function that sends or receives data over a network.
5441
*/
@@ -216,43 +203,109 @@ class Encrypted extends Expr {
216203
}
217204
}
218205

206+
/**
207+
* Holds if `sink` is a node that represents data transmitted through a network
208+
* operation `nsr`.
209+
*/
210+
predicate isSinkSendRecv(DataFlow::Node sink, NetworkSendRecv nsr) {
211+
sink.asConvertedExpr() = nsr.getDataExpr().getFullyConverted()
212+
}
213+
214+
/**
215+
* Holds if `sink` is a node that is encrypted by `enc`.
216+
*/
217+
predicate isSinkEncrypt(DataFlow::Node sink, Encrypted enc) {
218+
sink.asConvertedExpr() = enc.getFullyConverted()
219+
}
220+
221+
/**
222+
* Holds if `source` represents a use of a sensitive variable, or data returned by a
223+
* function returning sensitive data.
224+
*/
225+
predicate isSourceImpl(DataFlow::Node source) {
226+
exists(Expr e |
227+
e = source.asIndirectConvertedExpr() and
228+
e.getUnconverted().(VariableAccess).getTarget() instanceof SourceVariable and
229+
not e.hasConversion()
230+
)
231+
or
232+
source.asExpr().(FunctionCall).getTarget() instanceof SourceFunction
233+
}
234+
219235
/**
220236
* A taint flow configuration for flow from a sensitive expression to a network
221-
* operation or encryption operation.
237+
* operation.
222238
*/
223239
class FromSensitiveConfiguration extends TaintTracking::Configuration {
224240
FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" }
225241

226-
override predicate isSource(DataFlow::Node source) { source instanceof SourceNode }
242+
override predicate isSource(DataFlow::Node source) { isSourceImpl(source) }
227243

228-
override predicate isSink(DataFlow::Node sink) {
229-
sink.asExpr() = any(NetworkSendRecv nsr).getDataExpr()
230-
or
231-
sink.asExpr() instanceof Encrypted
244+
override predicate isSink(DataFlow::Node sink) { isSinkSendRecv(sink, _) }
245+
246+
override predicate isSanitizer(DataFlow::Node node) {
247+
node.asExpr().getUnspecifiedType() instanceof IntegralType
232248
}
233249

234-
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
235-
// flow through encryption functions to the return value (in case we can reach other sinks)
236-
node2.asExpr().(Encrypted).(FunctionCall).getAnArgument() = node1.asExpr()
250+
override predicate isSanitizerIn(DataFlow::Node node) {
251+
// As any use of a sensitive variable is a potential source, we need to block flow into
252+
// sources to not get path duplication.
253+
this.isSource(node)
254+
}
255+
}
256+
257+
/**
258+
* A taint flow configuration for flow from a sensitive expression to an encryption operation.
259+
*/
260+
class ToEncryptionConfiguration extends TaintTracking2::Configuration {
261+
ToEncryptionConfiguration() { this = "ToEncryptionConfiguration" }
262+
263+
override predicate isSource(DataFlow::Node source) {
264+
any(FromSensitiveConfiguration config).hasFlow(source, _) and
265+
isSourceImpl(source)
266+
}
267+
268+
override predicate isSink(DataFlow::Node sink) { isSinkEncrypt(sink, _) }
269+
270+
override predicate isSanitizer(DataFlow::Node node) {
271+
node.asExpr().getUnspecifiedType() instanceof IntegralType
272+
}
273+
274+
override predicate isSanitizerIn(DataFlow::Node node) {
275+
// As any use of a sensitive variable is a potential source, we need to block flow into
276+
// sources to not get path duplication.
277+
this.isSource(node)
278+
}
279+
}
280+
281+
/**
282+
* A taint flow configuration for flow from an encryption operation to a network operation.
283+
*/
284+
class FromEncryptionConfiguration extends TaintTracking3::Configuration {
285+
FromEncryptionConfiguration() { this = "FromEncryptionConfiguration" }
286+
287+
override predicate isSource(DataFlow::Node source) {
288+
isSinkEncrypt(source, _) or
289+
isSinkEncrypt(_, source.asDefiningArgument())
290+
}
291+
292+
override predicate isSink(DataFlow::Node sink) {
293+
any(FromSensitiveConfiguration config).hasFlowTo(sink)
237294
}
238295

239296
override predicate isSanitizer(DataFlow::Node node) {
240297
node.asExpr().getUnspecifiedType() instanceof IntegralType
241298
}
242299
}
243300

244-
from
245-
FromSensitiveConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink,
246-
NetworkSendRecv networkSendRecv, string msg
301+
from DataFlow::PathNode source, DataFlow::PathNode sink, NetworkSendRecv networkSendRecv, string msg
247302
where
248303
// flow from sensitive -> network data
249-
config.hasFlowPath(source, sink) and
250-
sink.getNode().asExpr() = networkSendRecv.getDataExpr() and
304+
any(FromSensitiveConfiguration config).hasFlowPath(source, sink) and
305+
isSinkSendRecv(sink.getNode(), networkSendRecv) and
251306
// no flow from sensitive -> evidence of encryption
252-
not exists(DataFlow::Node encrypted |
253-
config.hasFlow(source.getNode(), encrypted) and
254-
encrypted.asExpr() instanceof Encrypted
255-
) and
307+
not any(ToEncryptionConfiguration config).hasFlow(source.getNode(), _) and
308+
not any(FromEncryptionConfiguration config).hasFlowTo(sink.getNode()) and
256309
// construct result
257310
if networkSendRecv instanceof NetworkSend
258311
then
@@ -263,4 +316,4 @@ where
263316
msg =
264317
"This operation receives into '" + sink.toString() +
265318
"', which may put unencrypted sensitive data into $@."
266-
select networkSendRecv, source, sink, msg, source, source.getNode().toString()
319+
select networkSendRecv, source, sink, msg, source.getNode(), source.getNode().toString()

0 commit comments

Comments
 (0)