Java: Promote android sensitive broadcast query#6599
Java: Promote android sensitive broadcast query#6599joefarebrother merged 31 commits intogithub:mainfrom
Conversation
javaGenerated file changes for java
- Android,``android.*``,18,34,70,,,3,67,,,
+ Android,``android.*``,18,136,70,,,3,67,,,
- Totals,,84,3495,398,13,6,6,107,33,1,66
+ Totals,,84,3597,398,13,6,6,107,33,1,66
- android.content,8,,4,,,,,,,,,,,,,8,,,,,,4,
+ android.content,8,,44,,,,,,,,,,,,,8,,,,,,4,40
+ android.os,,,62,,,,,,,,,,,,,,,,,,,,62 |
| "android.os;Bundle;true;putSizeF;;;Argument[0];MapKey of Argument[-1];value", | ||
| "android.os;Bundle;true;putSparseParcelableArray;;;Argument[1];MapValue of Argument[-1];value", | ||
| "android.os;Bundle;true;putStringArrayList;;;Argument[1];MapValue of Argument[-1];value", | ||
| "android.content;Intent;true;getExtras;();;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", |
There was a problem hiding this comment.
Missing fluent mutators: addCategory, addFlags.
atorralba
left a comment
There was a problem hiding this comment.
Added some inline comments. I still need to review the CSV models in detail.
java/ql/src/semmle/code/java/security/AndroidSensitiveBroadcastQuery.qll
Outdated
Show resolved
Hide resolved
java/ql/src/semmle/code/java/security/AndroidSensitiveBroadcastQuery.qll
Outdated
Show resolved
Hide resolved
@joefarebrother IMHO yes, it would make sense, because you can send implicit (and thus, interceptable) Intents with those methods, although the exploitation is a little harder because the user needs to select the malicious app in a dialog for the Intent to reach it. The query would need to identify implicit Intents (i.e. explicit component not set, just an action). I think some code from this PR could be reused for that. |
Do the existing sanitizers for |
Probably, now that you mention it. I was thinking that we could reuse some code since we're doing similar things, but the sanitizer approach is simpler. Adding the new sinks should be easier than I initially thought, then :) |
java/ql/src/semmle/code/java/security/AndroidSensitiveBroadcastQuery.qll
Outdated
Show resolved
Hide resolved
java/ql/test/query-tests/security/CWE-927/SensitiveBroadcast.ql
Outdated
Show resolved
Hide resolved
atorralba
left a comment
There was a problem hiding this comment.
Added some more comments regarding CSV models. This covers the Intent extras pretty nicely, and the rest of the Intent methods (like get/setPackage) are or can be handled in other PRs like #6397.
Also, this will need a doc review at some point.
4062949 to
cd7a8a7
Compare
javaGenerated file changes for java
- Android,``android.*``,18,34,70,,,3,67,,,
+ Android,``android.*``,18,148,70,,,3,67,,,
- Totals,,116,3554,402,13,6,10,107,33,1,66
+ Totals,,116,3668,402,13,6,10,107,33,1,66
- android.content,8,,4,,,,,,,,,,,,,8,,,,,,4,
+ android.content,8,,44,,,,,,,,,,,,,8,,,,,,4,40
+ android.os,,,74,,,,,,,,,,,,,,,,,,,2,72 |
|
@joefarebrother this has conflicts |
java/ql/src/semmle/code/java/security/AndroidSensitiveBroadcastQuery.qll
Show resolved
Hide resolved
| } | ||
| } | ||
|
|
||
| private predicate isNullArg(Expr ex) { |
There was a problem hiding this comment.
Bad name (this indicates may-be-null, not is-null).
Also simplify this and isEmptyArrayArg using DataFlow::localExprFlow
| } | ||
|
|
||
| /** | ||
| * Holds if a `sendBroadcast` call doesn't specify receiver permission. |
There was a problem hiding this comment.
| * Holds if a `sendBroadcast` call doesn't specify receiver permission. | |
| * Holds if a `sendBroadcast` call `sendBroadcastCall` doesn't specify receiver permission. |
| /** | ||
| * Holds if a `sendBroadcast` call doesn't specify receiver permission. | ||
| */ | ||
| private predicate isSensitiveBroadcastSink(DataFlow::Node sink) { |
There was a problem hiding this comment.
| private predicate isSensitiveBroadcastSink(DataFlow::Node sink) { | |
| private predicate isSensitiveBroadcastSink(DataFlow::Node sendBroadcastCall) { |
| override predicate isSanitizer(DataFlow::Node node) { | ||
| exists(MethodAccess setReceiverMa | | ||
| setReceiverMa.getMethod().hasName(["setPackage", "setClass", "setClassName", "setComponent"]) and | ||
| setReceiverMa.getQualifier().(VarAccess).getVariable().getAnAccess() = node.asExpr() |
There was a problem hiding this comment.
Use localFlow instead of specifically one layer of access? Or (check by experiment) this might work just sanitising the qualifier due to use-use dataflow allowing sanitisers like this to interrupt dataflow paths to subsequent uses
(For example, in l = in; l.append("a"); l.append("b"), in Java the dataflow edges go in -> l, defn of l -> use of l in l.append("a"), use of l in l.append("a") -> use of l in l.append("b"), rather than both uses flowing from the definition as you might suppose)
| "android.os;Bundle;true;putSizeF;;;Argument[0];MapKey of Argument[-1];value", | ||
| "android.os;Bundle;true;putSparseParcelableArray;;;Argument[1];MapValue of Argument[-1];value", | ||
| "android.os;Bundle;true;putStringArrayList;;;Argument[1];MapValue of Argument[-1];value", | ||
| "android.content;Intent;true;getExtras;();;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", |
|
The context and class of the Intent can also be determined at construction time so the sanitizer needs to account for that. Something like: // Handle the cases where the PackageContext and Class are set at construction time
// Intent(Context packageContext, Class<?> cls)
// Create an intent for a specific component.
// Intent(String action, Uri uri, Context packageContext, Class<?> cls)
exists(ConstructorCall cc |
cc.getConstructedType() instanceof TypeIntent and
cc.getNumArgument() > 1 and
(
cc.getArgument(0).getType() instanceof TypeContext and
not exists(Expr classArg |
classArg instanceof NullLiteral and DataFlow::localExprFlow(classArg, cc.getArgument(1))
)
or
cc.getArgument(2).getType() instanceof TypeContext and
not exists(Expr classArg |
classArg instanceof NullLiteral and DataFlow::localExprFlow(classArg, cc.getArgument(3))
)
) and
DataFlow::localExprFlow(cc, node.asExpr())
) |
|
There is also the case when the broadcast receiver is determined dynamically. An attacker can abuse the intent filter priority to make it the first available receiver. The current sanitizers would ignore this case as setClassName or setPackage are usually called. I don't have the skills to propose a query for this case though. Intent intent = new Intent("com.victim.ADD_CARD_ACTION");
intent.putExtra("credit_card_number", num.getText().toString());
intent.putExtra("holder_name", name.getText().toString());
//...
for(ResolveInfo info : getPackageManager().queryBroadcastReceivers(intent, 0)) {
intent.setClassName(info.activityInfo.packageName, info.activityInfo.name);
sendBroadcast(intent);
return;
} |
0511a17 to
e815405
Compare
|
Additional models have been split into #6739 |
javaGenerated file changes for java
- Android,``android.*``,18,94,70,,,3,67,,,
+ Android,``android.*``,18,208,70,,,3,67,,,
- Totals,,116,4169,402,13,6,10,107,33,1,66
+ Totals,,116,4283,402,13,6,10,107,33,1,66
- android.content,8,,4,,,,,,,,,,,,,8,,,,,,4,
+ android.content,8,,44,,,,,,,,,,,,,8,,,,,,4,40
+ android.os,,,74,,,,,,,,,,,,,,,,,,,2,72 |
e815405 to
b6c584c
Compare
|
|
atorralba
left a comment
There was a problem hiding this comment.
Some tests are failing, and I added a minor inline comment. Otherwise, LGTM.
| private import semmle.code.java.frameworks.apache.Collections | ||
| private import semmle.code.java.frameworks.apache.Lang | ||
| private import semmle.code.java.frameworks.Flexjson | ||
| private import semmle.code.java.frameworks.android.Intent |
There was a problem hiding this comment.
Duplicates import in line 81.
| private import semmle.code.java.frameworks.android.Intent |
Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
|
Hi everyone 👋🏻 - Docs First Responder here, thanks for the ping. |
hubwriter
left a comment
There was a problem hiding this comment.
LGTM. A couple of little editorial suggestions. 👍
| @@ -0,0 +1,21 @@ | |||
| /** | |||
| * @name Leaking sensitive information through an implicit Intent | |||
There was a problem hiding this comment.
For consistency, use lowercase for intent - as elsewhere:
| * @name Leaking sensitive information through an implicit Intent | |
| * @name Leaking sensitive information through an implicit intent |
There was a problem hiding this comment.
Isn't Intent the name of the class? I'm not sure this should be lower-cased.
There was a problem hiding this comment.
If so we should make it Intent throughout.
There was a problem hiding this comment.
Indeed, it's the name of a class (just like Activity or Service), so I would use uppercase everywhere. Since there's more Android work coming, maybe a dedicated PR standardizing capitalization for this kind of thing in all files is due.
There was a problem hiding this comment.
Let's fix the query name and change note of this query here in this PR instead of postponing these particular instances to a dedicated PR. Even if we need a general sweep to standardize, I don't think we should add to those needed changes.
Co-authored-by: hubwriter <hubwriter@github.com>
java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll
Outdated
Show resolved
Hide resolved
java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll
Show resolved
Hide resolved
|
I had set myself as a reviewer for this this morning and had actually started a review, but as this has been already reviewed by a Docs team member, I'll unassign myself 😄 |
atorralba
left a comment
There was a problem hiding this comment.
As suggested by @aschackmull and @hubwriter, let's capitalize the first letter in all occurrences of terms like Intent, Activity or Service.
java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll
Outdated
Show resolved
Hide resolved
java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
@atorralba - thanks for suggesting those changes.
LGTM 👍
Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
This PR promotes the query contributed by #4512 from experimental.
Changes:
SensitiveBroadcastQuery.qllIntentandBundlesendStickyBroadcastmethods as additional sinksConsiderations:
A similar vulnerability is in sending sensitive data via methods likestartActivityandstartService. Should sinks for those be part of this same query?Should the additional models be a separate PR?