Refactor CWE-940/AndroidIntentRedirection

This commit is contained in:
Ed Minnix
2023-03-16 22:05:20 -04:00
parent 1e0c6811a4
commit d68bec98bc
3 changed files with 37 additions and 20 deletions

View File

@@ -8,9 +8,11 @@ import semmle.code.java.dataflow.TaintTracking3
import semmle.code.java.security.AndroidIntentRedirection import semmle.code.java.security.AndroidIntentRedirection
/** /**
* DEPRECATED: Use `IntentRedirectionFlow` instead.
*
* A taint tracking configuration for tainted Intents being used to start Android components. * A taint tracking configuration for tainted Intents being used to start Android components.
*/ */
class IntentRedirectionConfiguration extends TaintTracking::Configuration { deprecated class IntentRedirectionConfiguration extends TaintTracking::Configuration {
IntentRedirectionConfiguration() { this = "IntentRedirectionConfiguration" } IntentRedirectionConfiguration() { this = "IntentRedirectionConfiguration" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
@@ -26,31 +28,44 @@ class IntentRedirectionConfiguration extends TaintTracking::Configuration {
} }
} }
private module IntentRedirectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof IntentRedirectionSink }
predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof IntentRedirectionSanitizer }
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
any(IntentRedirectionAdditionalTaintStep c).step(node1, node2)
}
}
/** A taint tracking configuration for tainted Intents being used to start Android components. */
module IntentRedirectionFlow = TaintTracking::Make<IntentRedirectionConfig>;
/** /**
* A sanitizer for sinks that receive the original incoming Intent, * A sanitizer for sinks that receive the original incoming Intent,
* since its component cannot be arbitrarily set. * since its component cannot be arbitrarily set.
*/ */
private class OriginalIntentSanitizer extends IntentRedirectionSanitizer { private class OriginalIntentSanitizer extends IntentRedirectionSanitizer {
OriginalIntentSanitizer() { any(SameIntentBeingRelaunchedConfiguration c).hasFlowTo(this) } OriginalIntentSanitizer() { SameIntentBeingRelaunchedFlow::hasFlowTo(this) }
} }
/** /**
* Data flow configuration used to discard incoming Intents * Data flow configuration used to discard incoming Intents
* flowing directly to sinks that start Android components. * flowing directly to sinks that start Android components.
*/ */
private class SameIntentBeingRelaunchedConfiguration extends DataFlow2::Configuration { private module SameIntentBeingRelaunchedConfig implements DataFlow::ConfigSig {
SameIntentBeingRelaunchedConfiguration() { this = "SameIntentBeingRelaunchedConfiguration" } predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) { sink instanceof IntentRedirectionSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof IntentRedirectionSink } predicate isBarrier(DataFlow::Node barrier) {
override predicate isBarrier(DataFlow::Node barrier) {
// Don't discard the Intent if its original component is tainted // Don't discard the Intent if its original component is tainted
barrier instanceof IntentWithTaintedComponent barrier instanceof IntentWithTaintedComponent
} }
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
// Intents being built with the copy constructor from the original Intent are discarded too // Intents being built with the copy constructor from the original Intent are discarded too
exists(ClassInstanceExpr cie | exists(ClassInstanceExpr cie |
cie.getConstructedType() instanceof TypeIntent and cie.getConstructedType() instanceof TypeIntent and
@@ -61,12 +76,14 @@ private class SameIntentBeingRelaunchedConfiguration extends DataFlow2::Configur
} }
} }
private module SameIntentBeingRelaunchedFlow = DataFlow::Make<SameIntentBeingRelaunchedConfig>;
/** An `Intent` with a tainted component. */ /** An `Intent` with a tainted component. */
private class IntentWithTaintedComponent extends DataFlow::Node { private class IntentWithTaintedComponent extends DataFlow::Node {
IntentWithTaintedComponent() { IntentWithTaintedComponent() {
exists(IntentSetComponent setExpr, TaintedIntentComponentConf conf | exists(IntentSetComponent setExpr |
setExpr.getQualifier() = this.asExpr() and setExpr.getQualifier() = this.asExpr() and
conf.hasFlowTo(DataFlow::exprNode(setExpr.getSink())) TaintedIntentComponentFlow::hasFlowTo(DataFlow::exprNode(setExpr.getSink()))
) )
} }
} }
@@ -74,16 +91,16 @@ private class IntentWithTaintedComponent extends DataFlow::Node {
/** /**
* A taint tracking configuration for tainted data flowing to an `Intent`'s component. * A taint tracking configuration for tainted data flowing to an `Intent`'s component.
*/ */
private class TaintedIntentComponentConf extends TaintTracking3::Configuration { private module TaintedIntentComponentConfig implements DataFlow::ConfigSig {
TaintedIntentComponentConf() { this = "TaintedIntentComponentConf" } predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) {
override predicate isSink(DataFlow::Node sink) {
any(IntentSetComponent setComponent).getSink() = sink.asExpr() any(IntentSetComponent setComponent).getSink() = sink.asExpr()
} }
} }
private module TaintedIntentComponentFlow = TaintTracking::Make<TaintedIntentComponentConfig>;
/** A call to a method that changes the component of an `Intent`. */ /** A call to a method that changes the component of an `Intent`. */
private class IntentSetComponent extends MethodAccess { private class IntentSetComponent extends MethodAccess {
int sinkArg; int sinkArg;

View File

@@ -15,10 +15,10 @@
import java import java
import semmle.code.java.security.AndroidIntentRedirectionQuery import semmle.code.java.security.AndroidIntentRedirectionQuery
import DataFlow::PathGraph import IntentRedirectionFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, IntentRedirectionConfiguration conf from IntentRedirectionFlow::PathNode source, IntentRedirectionFlow::PathNode sink
where conf.hasFlowPath(source, sink) where IntentRedirectionFlow::hasFlowPath(source, sink)
select sink.getNode(), source, sink, select sink.getNode(), source, sink,
"Arbitrary Android activities or services can be started from a $@.", source.getNode(), "Arbitrary Android activities or services can be started from a $@.", source.getNode(),
"user-provided value" "user-provided value"

View File

@@ -9,7 +9,7 @@ class HasAndroidIntentRedirectionTest extends InlineExpectationsTest {
override predicate hasActualResult(Location location, string element, string tag, string value) { override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasAndroidIntentRedirection" and tag = "hasAndroidIntentRedirection" and
exists(DataFlow::Node sink, IntentRedirectionConfiguration conf | conf.hasFlowTo(sink) | exists(DataFlow::Node sink | IntentRedirectionFlow::hasFlowTo(sink) |
sink.getLocation() = location and sink.getLocation() = location and
element = sink.toString() and element = sink.toString() and
value = "" value = ""