Skip to content

Commit 057bb14

Browse files
committed
C++: Add ExternalAPI library files (for AST and IR).
1 parent a94826d commit 057bb14

File tree

6 files changed

+221
-0
lines changed

6 files changed

+221
-0
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Definitions for reasoning about untrusted data used in APIs defined outside the
3+
* database.
4+
*/
5+
6+
private import cpp
7+
private import semmle.code.cpp.models.interfaces.DataFlow
8+
private import semmle.code.cpp.models.interfaces.Taint
9+
import implementation.ExternalAPIsSpecific
10+
11+
/** A node representing untrusted data being passed to an external API. */
12+
class UntrustedExternalAPIDataNode extends ExternalAPIDataNode {
13+
UntrustedExternalAPIDataNode() { any(UntrustedDataToExternalAPIConfig c).hasFlow(_, this) }
14+
15+
/** Gets a source of untrusted data which is passed to this external API data node. */
16+
DataFlow::Node getAnUntrustedSource() {
17+
any(UntrustedDataToExternalAPIConfig c).hasFlow(result, this)
18+
}
19+
}
20+
21+
private newtype TExternalAPI =
22+
TExternalAPIParameter(Function f, int index) {
23+
exists(UntrustedExternalAPIDataNode n |
24+
f = n.getExternalFunction() and
25+
index = n.getIndex()
26+
)
27+
}
28+
29+
/** An external API which is used with untrusted data. */
30+
class ExternalAPIUsedWithUntrustedData extends TExternalAPI {
31+
/** Gets a possibly untrusted use of this external API. */
32+
UntrustedExternalAPIDataNode getUntrustedDataNode() {
33+
this = TExternalAPIParameter(result.getExternalFunction(), result.getIndex())
34+
}
35+
36+
/** Gets the number of untrusted sources used with this external API. */
37+
int getNumberOfUntrustedSources() {
38+
result = count(getUntrustedDataNode().getAnUntrustedSource())
39+
}
40+
41+
/** Gets a textual representation of this element. */
42+
string toString() {
43+
exists(Function f, int index, string indexString |
44+
if index = -1 then indexString = "qualifier" else indexString = "param " + index
45+
|
46+
this = TExternalAPIParameter(f, index) and
47+
result = f.toString() + " [" + indexString + "]"
48+
)
49+
}
50+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import semmle.code.cpp.dataflow.TaintTracking
2+
import semmle.code.cpp.models.interfaces.FlowSource
3+
import semmle.code.cpp.models.interfaces.DataFlow
4+
import SafeExternalAPIFunction
5+
6+
/** A node representing untrusted data being passed to an external API. */
7+
class ExternalAPIDataNode extends DataFlow::Node {
8+
Call call;
9+
int i;
10+
11+
ExternalAPIDataNode() {
12+
// Argument to call to a function
13+
(
14+
this.asExpr() = call.getArgument(i)
15+
or
16+
i = -1 and this.asExpr() = call.getQualifier()
17+
) and
18+
exists(Function f |
19+
f = call.getTarget() and
20+
// Defined outside the source archive
21+
not f.hasDefinition() and
22+
// Not already modeled as a dataflow or taint step
23+
not f instanceof DataFlowFunction and
24+
not f instanceof TaintFunction and
25+
// Not a call to a known safe external API
26+
not f instanceof SafeExternalAPIFunction
27+
)
28+
}
29+
30+
/** Gets the called API `Function`. */
31+
Function getExternalFunction() { result = call.getTarget() }
32+
33+
/** Gets the index which is passed untrusted data (where -1 indicates the qualifier). */
34+
int getIndex() { result = i }
35+
36+
/** Gets the description of the function being called. */
37+
string getFunctionDescription() { result = getExternalFunction().toString() }
38+
}
39+
40+
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalAPIDataNode`s. */
41+
class UntrustedDataToExternalAPIConfig extends TaintTracking::Configuration {
42+
UntrustedDataToExternalAPIConfig() { this = "UntrustedDataToExternalAPIConfig" }
43+
44+
override predicate isSource(DataFlow::Node source) {
45+
exists(RemoteFlowFunction remoteFlow |
46+
remoteFlow = source.asExpr().(Call).getTarget() and
47+
remoteFlow.hasRemoteFlowSource(_, _)
48+
)
49+
}
50+
51+
override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalAPIDataNode }
52+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
private import cpp
2+
3+
/**
4+
* A `Function` that is considered a "safe" external API from a security perspective.
5+
*/
6+
abstract class SafeExternalAPIFunction extends Function { }
7+
8+
/** The default set of "safe" external APIs. */
9+
private class DefaultSafeExternalAPIFunction extends SafeExternalAPIFunction {
10+
DefaultSafeExternalAPIFunction() { this.hasGlobalName(["strcmp", "strlen", "memcmp"]) }
11+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Definitions for reasoning about untrusted data used in APIs defined outside the
3+
* database.
4+
*/
5+
6+
private import cpp
7+
private import semmle.code.cpp.models.interfaces.DataFlow
8+
private import semmle.code.cpp.models.interfaces.Taint
9+
import implementation.ExternalAPIsSpecific
10+
11+
/** A node representing untrusted data being passed to an external API. */
12+
class UntrustedExternalAPIDataNode extends ExternalAPIDataNode {
13+
UntrustedExternalAPIDataNode() { any(UntrustedDataToExternalAPIConfig c).hasFlow(_, this) }
14+
15+
/** Gets a source of untrusted data which is passed to this external API data node. */
16+
DataFlow::Node getAnUntrustedSource() {
17+
any(UntrustedDataToExternalAPIConfig c).hasFlow(result, this)
18+
}
19+
}
20+
21+
private newtype TExternalAPI =
22+
TExternalAPIParameter(Function f, int index) {
23+
exists(UntrustedExternalAPIDataNode n |
24+
f = n.getExternalFunction() and
25+
index = n.getIndex()
26+
)
27+
}
28+
29+
/** An external API which is used with untrusted data. */
30+
class ExternalAPIUsedWithUntrustedData extends TExternalAPI {
31+
/** Gets a possibly untrusted use of this external API. */
32+
UntrustedExternalAPIDataNode getUntrustedDataNode() {
33+
this = TExternalAPIParameter(result.getExternalFunction(), result.getIndex())
34+
}
35+
36+
/** Gets the number of untrusted sources used with this external API. */
37+
int getNumberOfUntrustedSources() {
38+
result = count(getUntrustedDataNode().getAnUntrustedSource())
39+
}
40+
41+
/** Gets a textual representation of this element. */
42+
string toString() {
43+
exists(Function f, int index, string indexString |
44+
if index = -1 then indexString = "qualifier" else indexString = "param " + index
45+
|
46+
this = TExternalAPIParameter(f, index) and
47+
result = f.toString() + " [" + indexString + "]"
48+
)
49+
}
50+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import semmle.code.cpp.ir.dataflow.TaintTracking
2+
private import semmle.code.cpp.security.FlowSources
3+
private import semmle.code.cpp.models.interfaces.DataFlow
4+
import SafeExternalAPIFunction
5+
6+
/** A node representing untrusted data being passed to an external API. */
7+
class ExternalAPIDataNode extends DataFlow::Node {
8+
Call call;
9+
int i;
10+
11+
ExternalAPIDataNode() {
12+
// Argument to call to a function
13+
(
14+
this.asExpr() = call.getArgument(i)
15+
or
16+
i = -1 and this.asExpr() = call.getQualifier()
17+
) and
18+
exists(Function f |
19+
f = call.getTarget() and
20+
// Defined outside the source archive
21+
not f.hasDefinition() and
22+
// Not already modeled as a dataflow or taint step
23+
not f instanceof DataFlowFunction and
24+
not f instanceof TaintFunction and
25+
// Not a call to a known safe external API
26+
not f instanceof SafeExternalAPIFunction
27+
)
28+
}
29+
30+
/** Gets the called API `Function`. */
31+
Function getExternalFunction() { result = call.getTarget() }
32+
33+
/** Gets the index which is passed untrusted data (where -1 indicates the qualifier). */
34+
int getIndex() { result = i }
35+
36+
/** Gets the description of the function being called. */
37+
string getFunctionDescription() { result = getExternalFunction().toString() }
38+
}
39+
40+
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalAPIDataNode`s. */
41+
class UntrustedDataToExternalAPIConfig extends TaintTracking::Configuration {
42+
UntrustedDataToExternalAPIConfig() { this = "UntrustedDataToExternalAPIConfigIR" }
43+
44+
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
45+
46+
override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalAPIDataNode }
47+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
private import cpp
2+
3+
/**
4+
* A `Function` that is considered a "safe" external API from a security perspective.
5+
*/
6+
abstract class SafeExternalAPIFunction extends Function { }
7+
8+
/** The default set of "safe" external APIs. */
9+
private class DefaultSafeExternalAPIFunction extends SafeExternalAPIFunction {
10+
DefaultSafeExternalAPIFunction() { this.hasGlobalName(["strcmp", "strlen", "memcmp"]) }
11+
}

0 commit comments

Comments
 (0)