@@ -16,6 +16,8 @@ import cpp
1616import semmle.code.cpp.security.SensitiveExprs
1717import semmle.code.cpp.security.PrivateData
1818import semmle.code.cpp.dataflow.TaintTracking
19+ import semmle.code.cpp.dataflow.TaintTracking2
20+ import semmle.code.cpp.dataflow.TaintTracking3
1921import semmle.code.cpp.models.interfaces.FlowSource
2022import semmle.code.cpp.commons.File
2123import 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 */
223239class 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
247302where
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