Skip to content

Commit 7834626

Browse files
committed
C++: Rewrite cpp/tainted-permissions-check to not use DefaultTaintTracking
1 parent 257fe1a commit 7834626

File tree

2 files changed

+68
-17
lines changed

2 files changed

+68
-17
lines changed

cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,83 @@
1212
* external/cwe/cwe-807
1313
*/
1414

15-
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
16-
import TaintedWithPath
15+
import cpp
16+
import semmle.code.cpp.security.Security
17+
import semmle.code.cpp.security.FlowSources
18+
import semmle.code.cpp.ir.dataflow.TaintTracking
19+
import semmle.code.cpp.ir.IR
20+
import Flow::PathGraph
21+
22+
Expr getExprWithoutNot(Expr expr) {
23+
result = expr and not expr instanceof NotExpr
24+
or
25+
result = getExprWithoutNot(expr.(NotExpr).getOperand()) and expr instanceof NotExpr
26+
}
1727

1828
predicate sensitiveCondition(Expr condition, Expr raise) {
1929
raisesPrivilege(raise) and
2030
exists(IfStmt ifstmt |
21-
ifstmt.getCondition() = condition and
31+
getExprWithoutNot(ifstmt.getCondition()) = condition and
2232
raise.getEnclosingStmt().getParentStmt*() = ifstmt
2333
)
2434
}
2535

26-
class Configuration extends TaintTrackingConfiguration {
27-
override predicate isSink(Element tainted) { sensitiveCondition(tainted, _) }
36+
private predicate constantInstruction(Instruction instr) {
37+
instr instanceof ConstantInstruction
38+
or
39+
instr instanceof StringConstantInstruction
40+
or
41+
constantInstruction(instr.(UnaryInstruction).getUnary())
42+
}
43+
44+
predicate isSource(FlowSource source, string sourceType) { sourceType = source.getSourceType() }
45+
46+
module Config implements DataFlow::ConfigSig {
47+
predicate isSource(DataFlow::Node node) { isSource(node, _) }
48+
49+
predicate isSink(DataFlow::Node node) {
50+
sensitiveCondition([node.asExpr(), node.asIndirectExpr()], _)
51+
}
52+
53+
predicate isBarrier(DataFlow::Node node) {
54+
// Block flow into binary instructions if both operands are non-constant
55+
exists(BinaryInstruction iTo |
56+
iTo = node.asInstruction() and
57+
not constantInstruction(iTo.getLeft()) and
58+
not constantInstruction(iTo.getRight()) and
59+
// propagate taint from either the pointer or the offset, regardless of constant-ness
60+
not iTo instanceof PointerArithmeticInstruction
61+
)
62+
or
63+
// Block flow through calls to pure functions if two or more operands are non-constant
64+
exists(Instruction iFrom1, Instruction iFrom2, CallInstruction iTo |
65+
iTo = node.asInstruction() and
66+
isPureFunction(iTo.getStaticCallTarget().getName()) and
67+
iFrom1 = iTo.getAnArgument() and
68+
iFrom2 = iTo.getAnArgument() and
69+
not constantInstruction(iFrom1) and
70+
not constantInstruction(iFrom2) and
71+
iFrom1 != iFrom2
72+
)
73+
}
2874
}
2975

76+
module Flow = TaintTracking::Global<Config>;
77+
3078
/*
3179
* Produce an alert if there is an 'if' statement whose condition `condition`
3280
* is influenced by tainted data `source`, and the body contains
3381
* `raise` which escalates privilege.
3482
*/
3583

36-
from Expr source, Expr condition, Expr raise, PathNode sourceNode, PathNode sinkNode
84+
from
85+
Expr raise, string sourceType, DataFlow::Node source, DataFlow::Node sink,
86+
Flow::PathNode sourceNode, Flow::PathNode sinkNode
3787
where
38-
taintedWithPath(source, condition, sourceNode, sinkNode) and
39-
sensitiveCondition(condition, raise)
40-
select condition, sourceNode, sinkNode, "Reliance on untrusted input $@ to raise privilege at $@.",
41-
source, source.toString(), raise, raise.toString()
88+
source = sourceNode.getNode() and
89+
sink = sinkNode.getNode() and
90+
isSource(source, sourceType) and
91+
sensitiveCondition([sink.asExpr(), sink.asIndirectExpr()], raise) and
92+
Flow::flowPath(sourceNode, sinkNode)
93+
select sink, sourceNode, sinkNode, "Reliance on $@ to raise privilege at $@.", source, sourceType,
94+
raise, raise.toString()
Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
edges
2-
| test.cpp:20:29:20:34 | call to getenv | test.cpp:24:10:24:35 | ! ... |
3-
| test.cpp:20:29:20:34 | call to getenv | test.cpp:24:11:24:16 | call to strcmp |
4-
| test.cpp:20:29:20:47 | call to getenv | test.cpp:24:10:24:35 | ! ... |
52
| test.cpp:20:29:20:47 | call to getenv | test.cpp:24:11:24:16 | call to strcmp |
6-
subpaths
3+
| test.cpp:20:29:20:47 | call to getenv indirection | test.cpp:24:11:24:16 | call to strcmp |
74
nodes
8-
| test.cpp:20:29:20:34 | call to getenv | semmle.label | call to getenv |
95
| test.cpp:20:29:20:47 | call to getenv | semmle.label | call to getenv |
10-
| test.cpp:24:10:24:35 | ! ... | semmle.label | ! ... |
6+
| test.cpp:20:29:20:47 | call to getenv indirection | semmle.label | call to getenv indirection |
117
| test.cpp:24:11:24:16 | call to strcmp | semmle.label | call to strcmp |
8+
subpaths
129
#select
13-
| test.cpp:24:10:24:35 | ! ... | test.cpp:20:29:20:34 | call to getenv | test.cpp:24:10:24:35 | ! ... | Reliance on untrusted input $@ to raise privilege at $@. | test.cpp:20:29:20:34 | call to getenv | call to getenv | test.cpp:25:9:25:27 | ... = ... | ... = ... |
10+
| test.cpp:24:11:24:16 | call to strcmp | test.cpp:20:29:20:47 | call to getenv | test.cpp:24:11:24:16 | call to strcmp | Reliance on $@ to raise privilege at $@. | test.cpp:20:29:20:47 | call to getenv | an environment variable | test.cpp:25:9:25:27 | ... = ... | ... = ... |
11+
| test.cpp:24:11:24:16 | call to strcmp | test.cpp:20:29:20:47 | call to getenv indirection | test.cpp:24:11:24:16 | call to strcmp | Reliance on $@ to raise privilege at $@. | test.cpp:20:29:20:47 | call to getenv indirection | an environment variable | test.cpp:25:9:25:27 | ... = ... | ... = ... |

0 commit comments

Comments
 (0)