Skip to content

Commit e6145f0

Browse files
authored
Merge pull request #6966 from atorralba/atorralba/android-explicit-intent-sanitizer
Android: Add ExplicitIntentSanitizer and allowIntentExtrasImplicitRead
2 parents ab4780c + 6f7d0b6 commit e6145f0

File tree

3 files changed

+57
-35
lines changed

3 files changed

+57
-35
lines changed

java/ql/lib/semmle/code/java/frameworks/android/Intent.qll

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,61 @@ class IntentGetParcelableExtraMethod extends Method {
7777
}
7878
}
7979

80+
/** The class `android.os.BaseBundle`, or a class that extends it. */
81+
class AndroidBundle extends Class {
82+
AndroidBundle() { this.getASupertype*().hasQualifiedName("android.os", "BaseBundle") }
83+
}
84+
85+
/** An `Intent` that explicitly sets a destination component. */
86+
class ExplicitIntent extends Expr {
87+
ExplicitIntent() {
88+
exists(MethodAccess ma, Method m |
89+
ma.getMethod() = m and
90+
m.getDeclaringType() instanceof TypeIntent and
91+
m.hasName(["setPackage", "setClass", "setClassName", "setComponent"]) and
92+
ma.getQualifier() = this
93+
)
94+
or
95+
exists(ConstructorCall cc, Argument classArg |
96+
cc.getConstructedType() instanceof TypeIntent and
97+
cc.getAnArgument() = classArg and
98+
classArg.getType() instanceof TypeClass and
99+
not exists(NullLiteral nullLiteral | DataFlow::localExprFlow(nullLiteral, classArg)) and
100+
cc = this
101+
)
102+
}
103+
}
104+
105+
/**
106+
* A sanitizer for explicit intents.
107+
*
108+
* Use this when you want to work only with implicit intents
109+
* in a `DataFlow` or `TaintTracking` configuration.
110+
*/
111+
class ExplicitIntentSanitizer extends DataFlow::Node {
112+
ExplicitIntentSanitizer() {
113+
exists(ExplicitIntent explIntent | DataFlow::localExprFlow(explIntent, this.asExpr()))
114+
}
115+
}
116+
117+
private class BundleExtrasSyntheticField extends SyntheticField {
118+
BundleExtrasSyntheticField() { this = "android.content.Intent.extras" }
119+
120+
override RefType getType() { result instanceof AndroidBundle }
121+
}
122+
123+
/**
124+
* Holds if extras may be implicitly read from the Intent `node`.
125+
*/
126+
predicate allowIntentExtrasImplicitRead(DataFlow::Node node, DataFlow::Content c) {
127+
node.getType() instanceof TypeIntent and
128+
(
129+
c instanceof DataFlow::MapValueContent
130+
or
131+
c.(DataFlow::SyntheticFieldContent).getType() instanceof AndroidBundle
132+
)
133+
}
134+
80135
private class IntentBundleFlowSteps extends SummaryModelCsv {
81136
override predicate row(string row) {
82137
row =

java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -121,31 +121,6 @@ private predicate isStartActivityOrServiceSink(DataFlow::Node arg) {
121121
)
122122
}
123123

124-
private predicate isCleanIntent(Expr intent) {
125-
intent.getType() instanceof TypeIntent and
126-
(
127-
exists(MethodAccess setRecieverMa |
128-
setRecieverMa.getQualifier() = intent and
129-
setRecieverMa.getMethod().hasName(["setPackage", "setClass", "setClassName", "setComponent"])
130-
)
131-
or
132-
// Handle the cases where the PackageContext and Class are set at construction time
133-
// Intent(Context packageContext, Class<?> cls)
134-
// Intent(String action, Uri uri, Context packageContext, Class<?> cls)
135-
exists(ConstructorCall cc | cc = intent |
136-
cc.getConstructedType() instanceof TypeIntent and
137-
cc.getNumArgument() > 1 and
138-
(
139-
cc.getArgument(0).getType() instanceof TypeContext and
140-
not maybeNullArg(cc.getArgument(1))
141-
or
142-
cc.getArgument(2).getType() instanceof TypeContext and
143-
not maybeNullArg(cc.getArgument(3))
144-
)
145-
)
146-
)
147-
}
148-
149124
/**
150125
* Taint configuration tracking flow from variables containing sensitive information to broadcast Intents.
151126
*/
@@ -165,11 +140,7 @@ class SensitiveCommunicationConfig extends TaintTracking::Configuration {
165140
/**
166141
* Holds if broadcast doesn't specify receiving package name of the 3rd party app
167142
*/
168-
override predicate isSanitizer(DataFlow::Node node) {
169-
exists(DataFlow::Node intent | isCleanIntent(intent.asExpr()) |
170-
DataFlow::localFlow(intent, node)
171-
)
172-
}
143+
override predicate isSanitizer(DataFlow::Node node) { node instanceof ExplicitIntentSanitizer }
173144

174145
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
175146
super.allowImplicitRead(node, c)

java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,7 @@ class GetContentIntentConfig extends TaintTracking2::Configuration {
4848
// Allow the wrapped intent created by Intent.getChooser to be consumed
4949
// by at the sink:
5050
isSink(node) and
51-
(
52-
content.(DataFlow::SyntheticFieldContent).getField() = "android.content.Intent.extras"
53-
or
54-
content instanceof DataFlow::MapValueContent
55-
)
51+
allowIntentExtrasImplicitRead(node, content)
5652
}
5753
}
5854

0 commit comments

Comments
 (0)