13
13
14
14
import cpp
15
15
import semmle.code.cpp.security.SensitiveExprs
16
- import semmle.code.cpp.security.TaintTracking
17
- import TaintedWithPath
18
-
19
- class UserInputIsSensitiveExpr extends SecurityOptions {
20
- override predicate isUserInput ( Expr expr , string cause ) {
21
- expr instanceof SensitiveExpr and cause = "sensitive information"
22
- }
23
- }
16
+ import semmle.code.cpp.dataflow.TaintTracking
17
+ import DataFlow:: PathGraph
24
18
25
19
class SqliteFunctionCall extends FunctionCall {
26
20
SqliteFunctionCall ( ) { this .getTarget ( ) .getName ( ) .matches ( "sqlite%" ) }
@@ -34,25 +28,51 @@ predicate sqlite_encryption_used() {
34
28
any ( FunctionCall fc ) .getTarget ( ) .getName ( ) .matches ( "sqlite%\\_key\\_%" )
35
29
}
36
30
37
- class Configuration extends TaintTrackingConfiguration {
38
- override predicate isSource ( Expr source ) {
39
- super .isSource ( source ) and source instanceof SensitiveExpr
31
+ /**
32
+ * Gets a field of the class `c`, or of another class contained in `c`.
33
+ */
34
+ Field getRecField ( Class c ) {
35
+ result = c .getAField ( ) or
36
+ result = getRecField ( c .getAField ( ) .getUnspecifiedType ( ) .stripType ( ) )
37
+ }
38
+
39
+ /**
40
+ * A taint flow configuration for flow from a sensitive expression to a `SqliteFunctionCall` sink.
41
+ */
42
+ class FromSensitiveConfiguration extends TaintTracking:: Configuration {
43
+ FromSensitiveConfiguration ( ) { this = "FromSensitiveConfiguration" }
44
+
45
+ override predicate isSource ( DataFlow:: Node source ) { source .asExpr ( ) instanceof SensitiveExpr }
46
+
47
+ override predicate isSink ( DataFlow:: Node sink ) {
48
+ any ( SqliteFunctionCall c ) .getASource ( ) = sink .asExpr ( ) and
49
+ not sqlite_encryption_used ( )
50
+ }
51
+
52
+ override predicate isSanitizer ( DataFlow:: Node node ) {
53
+ node .asExpr ( ) .getUnspecifiedType ( ) instanceof IntegralType
40
54
}
41
55
42
- override predicate isSink ( Element taintedArg ) {
43
- exists ( SqliteFunctionCall sqliteCall |
44
- taintedArg = sqliteCall .getASource ( ) and
45
- not sqlite_encryption_used ( )
56
+ override predicate allowImplicitRead ( DataFlow:: Node node , DataFlow:: ContentSet content ) {
57
+ // flow out from fields at the sink (only).
58
+ this .isSink ( node ) and
59
+ // constrain `content` to a field inside the node.
60
+ exists ( Class c |
61
+ node .asExpr ( ) .getUnspecifiedType ( ) .stripType ( ) = c and
62
+ content .( DataFlow:: FieldContent ) .getField ( ) = getRecField ( c )
46
63
)
64
+ or
65
+ // any default implicit reads
66
+ super .allowImplicitRead ( node , content )
47
67
}
48
68
}
49
69
50
70
from
51
- SensitiveExpr taintSource , Expr taintedArg , SqliteFunctionCall sqliteCall , PathNode sourceNode ,
52
- PathNode sinkNode
71
+ FromSensitiveConfiguration config , SensitiveExpr sensitive , DataFlow :: PathNode source ,
72
+ DataFlow :: PathNode sink , SqliteFunctionCall sqliteCall
53
73
where
54
- taintedWithPath ( taintSource , taintedArg , sourceNode , sinkNode ) and
55
- taintedArg = sqliteCall . getASource ( )
56
- select sqliteCall , sourceNode , sinkNode ,
57
- "This SQLite call may store $@ in a non-encrypted SQLite database" , taintSource ,
58
- "sensitive information"
74
+ config . hasFlowPath ( source , sink ) and
75
+ source . getNode ( ) . asExpr ( ) = sensitive and
76
+ sqliteCall . getASource ( ) = sink . getNode ( ) . asExpr ( )
77
+ select sqliteCall , source , sink , "This SQLite call may store $@ in a non-encrypted SQLite database" ,
78
+ sensitive , "sensitive information"
0 commit comments