-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Java: Add query for exposure of sensitive information to android notifications #15281
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
143ce0b
3aa2714
cd19a91
f9bb004
a1a2acd
bafd65b
2ca164c
d806fca
1190352
69faafa
b23bbf9
0acb647
dedba1f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,48 @@ extensions: | |
- ["android.app", "FragmentTransaction", True, "replace", "(int,Class,Bundle,String)", "", "Argument[1]", "fragment-injection", "manual"] | ||
- ["android.app", "FragmentTransaction", True, "replace", "(int,Fragment)", "", "Argument[1]", "fragment-injection", "manual"] | ||
- ["android.app", "FragmentTransaction", True, "replace", "(int,Fragment,String)", "", "Argument[1]", "fragment-injection", "manual"] | ||
- ["android.app", "Notification$Action", True, "Action", "(int,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"] | ||
- ["android.app", "Notification$Action$Builder", True, "Builder", "(Icon,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"] | ||
- ["android.app", "Notification$Action$Builder", True, "Builder", "(int,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"] | ||
- ["android.app", "Notification$Action$Builder", True, "addExtras", "(Bundle)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$BigPictureStyle", True, "setBigContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$BigPictureStyle", True, "setContentDescription", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$BigPictureStyle", True, "setSummaryText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$BigTextStyle", True, "bigText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$BigTextStyle", True, "setBigContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$BigTextStyle", True, "setSummaryText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "addAction", "(int,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "addExtras", "(Bundle)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setCategory", "(String)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setChannelId", "(String)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setContent", "(RemoteViews)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setContentInfo", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setContentText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setCustomBigContentView", "(RemoteViews)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setCustomContentView", "(RemoteViews)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setCustomHeadsUpContentView", "(RemoteViews)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setExtras", "(Bundle)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setGroup", "(String)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setRemoteInputHistory", "(CharSequence[])", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setSettingsText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setSortKey", "(String)", "", "Argument[0]", "notification", "manual"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can the sort key be recovered from the notification? And even if so, this doesn't very likely to receive sensitive data, does it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It can with getSortKey. Though it does indeed seem unlikely to receive sensitive data. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, the model won't hurt, you never know what people can use as sort key 😄 |
||
- ["android.app", "Notification$Builder", True, "setSubText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setTicker", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$Builder", True, "setTicker", "(CharSequence,RemoteViews)", "", "Argument[0..1]", "notification", "manual"] | ||
- ["android.app", "Notification$CallStyle", True, "setVerificationText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$InboxStyle", True, "addLine", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$InboxStyle", True, "setBigContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$InboxStyle", True, "setSummaryText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$MediaStyle", True, "setRemotePlaybackInfo", "(CharSequence,int,PendingIntent)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$MessagingStyle", True, "MessagingStyle", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$MessagingStyle", True, "addMessage", "(CharSequence,long,CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$MessagingStyle", True, "addMessage", "(CharSequence,long,CharSequence)", "", "Argument[2]", "notification", "manual"] | ||
- ["android.app", "Notification$MessagingStyle", True, "addMessage", "(CharSequence,long,Person)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$MessagingStyle", True, "setConversationTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$MessagingStyle$Message", True, "Message", "(CharSequence,long,CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "Notification$MessagingStyle$Message", True, "Message", "(CharSequence,long,CharSequence)", "", "Argument[2]", "notification", "manual"] | ||
- ["android.app", "Notification$MessagingStyle$Message", True, "Message", "(CharSequence,long,Person)", "", "Argument[0]", "notification", "manual"] | ||
- ["android.app", "NotificationManager", True, "notify", "(String,int,Notification)", "", "Argument[2]", "pending-intents", "manual"] | ||
- ["android.app", "NotificationManager", True, "notify", "(int,Notification)", "", "Argument[1]", "pending-intents", "manual"] | ||
- ["android.app", "NotificationManager", True, "notifyAsPackage", "(String,String,int,Notification)", "", "Argument[3]", "pending-intents", "manual"] | ||
|
@@ -38,6 +80,7 @@ extensions: | |
- ["android.app", "PendingIntent", False, "send", "(Context,int,Intent,PendingIntent$OnFinished,Handler)", "", "Argument[2]", "pending-intents", "manual"] | ||
- ["android.app", "PendingIntent", False, "send", "(Context,int,Intent,PendingIntent$OnFinished,Handler,String)", "", "Argument[2]", "pending-intents", "manual"] | ||
- ["android.app", "PendingIntent", False, "send", "(Context,int,Intent,PendingIntent$OnFinished,Handler,String,Bundle)", "", "Argument[2]", "pending-intents", "manual"] | ||
|
||
- addsTo: | ||
pack: codeql/java-all | ||
extensible: summaryModel | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,8 +7,50 @@ extensions: | |
- ["androidx.core.app", "AlarmManagerCompat", True, "setAndAllowWhileIdle", "", "", "Argument[3]", "pending-intents", "manual"] | ||
- ["androidx.core.app", "AlarmManagerCompat", True, "setExact", "", "", "Argument[3]", "pending-intents", "manual"] | ||
- ["androidx.core.app", "AlarmManagerCompat", True, "setExactAndAllowWhileIdle", "", "", "Argument[3]", "pending-intents", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Action", True, "Action", "(int,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same questions/comments from above, since the APIs are nearly identical. |
||
- ["androidx.core.app", "NotificationCompat$Action$Builder", True, "Builder", "(IconCompat,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Action$Builder", True, "Builder", "(int,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Action$Builder", True, "addExtras", "(Bundle)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$BigPictureStyle", True, "setBigContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$BigPictureStyle", True, "setContentDescription", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$BigPictureStyle", True, "setSummaryText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$BigTextStyle", True, "bigText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$BigTextStyle", True, "setBigContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$BigTextStyle", True, "setSummaryText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "addAction", "(int,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "addExtras", "(Bundle)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setCategory", "(String)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setChannelId", "(String)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setContent", "(RemoteViews)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setContentInfo", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setContentText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setCustomBigContentView", "(RemoteViews)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setCustomContentView", "(RemoteViews)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setCustomHeadsUpContentView", "(RemoteViews)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setExtras", "(Bundle)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setGroup", "(String)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setRemoteInputHistory", "(CharSequence[])", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setSettingsText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setSortKey", "(String)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setSubText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setTicker", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$Builder", True, "setTicker", "(CharSequence,RemoteViews)", "", "Argument[0..1]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$CallStyle", True, "setVerificationText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$InboxStyle", True, "addLine", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$InboxStyle", True, "setBigContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$InboxStyle", True, "setSummaryText", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$MessagingStyle", True, "addMessage", "(CharSequence,long,CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$MessagingStyle", True, "addMessage", "(CharSequence,long,CharSequence)", "", "Argument[2]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$MessagingStyle", True, "addMessage", "(CharSequence,long,Person)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$MessagingStyle", True, "setConversationTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$MessagingStyle", True, "MessagingStyle", "(CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$MessagingStyle$Message", True, "Message", "(CharSequence,long,CharSequence)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$MessagingStyle$Message", True, "Message", "(CharSequence,long,CharSequence)", "", "Argument[2]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationCompat$MessagingStyle$Message", True, "Message", "(CharSequence,long,Person)", "", "Argument[0]", "notification", "manual"] | ||
- ["androidx.core.app", "NotificationManagerCompat", True, "notify", "(String,int,Notification)", "", "Argument[2]", "pending-intents", "manual"] | ||
- ["androidx.core.app", "NotificationManagerCompat", True, "notify", "(int,Notification)", "", "Argument[1]", "pending-intents", "manual"] | ||
|
||
- addsTo: | ||
pack: codeql/java-all | ||
extensible: summaryModel | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/** Definitions for Android Sensitive UI queries */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume you plan to add more configurations here and that's why this library file has a more general name. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed; #15396 uses the same file |
||
|
||
import java | ||
private import semmle.code.java.dataflow.ExternalFlow | ||
private import semmle.code.java.dataflow.TaintTracking | ||
private import semmle.code.java.security.SensitiveActions | ||
|
||
/** A configuration for tracking sensitive information to system notifications. */ | ||
private module NotificationTrackingConfig implements DataFlow::ConfigSig { | ||
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SensitiveExpr } | ||
|
||
predicate isSink(DataFlow::Node sink) { sinkNode(sink, "notification") } | ||
|
||
joefarebrother marked this conversation as resolved.
Show resolved
Hide resolved
|
||
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { | ||
isSink(node) and exists(c) | ||
} | ||
|
||
predicate isBarrierIn(DataFlow::Node node) { isSource(node) } | ||
} | ||
|
||
/** Taint tracking flow for sensitive data flowing to system notifications. */ | ||
module NotificationTracking = TaintTracking::Global<NotificationTrackingConfig>; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// BAD: `password` is exposed in a notification. | ||
void confirmPassword(String password) { | ||
NotificationManager manager = NotificationManager.from(this); | ||
manager.send( | ||
new Notification.Builder(this, CHANNEL_ID) | ||
.setContentText("Your password is: " + password) | ||
.build()); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<!DOCTYPE qhelp PUBLIC | ||
"-//Semmle//qhelp//EN" | ||
"qhelp.dtd"> | ||
<qhelp> | ||
<overview> | ||
<p> | ||
Sensitive information such as passwords or two-factor authentication (2FA) codes should not be exposed in a system notification. | ||
Notifications should not be considered secure, as other untrusted applications may be able to use a | ||
<code>NotificationListenerService</code> to read the contents of notifications. | ||
</p> | ||
</overview> | ||
|
||
<recommendation> | ||
<p> | ||
Do not expose sensitive data in notifications. | ||
</p> | ||
</recommendation> | ||
|
||
<example> | ||
<p> | ||
In the following sample, the <code>password</code> is sent as part of a notification. | ||
This can allow another application to read this password. | ||
</p> | ||
|
||
<sample src="AndroidSensitiveNotifications.java"/> | ||
</example> | ||
|
||
<references> | ||
<li> | ||
OWASP Mobile Application Security: <a href="https://mas.owasp.org/MASTG/Android/0x05d-Testing-Data-Storage/#app-notifications">Android Data Storage - Application Notifications</a> | ||
</li> | ||
</references> | ||
|
||
</qhelp> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/** | ||
* @name Exposure of sensitive information to notifications | ||
* @id java/android/sensitive-notification | ||
* @kind path-problem | ||
* @description Sensitive information exposed in a system notification can be read by an unauthorized application. | ||
* @problem.severity error | ||
* @precision medium | ||
* @security-severity 6.5 | ||
* @tags security | ||
* external/cwe/cwe-200 | ||
*/ | ||
|
||
import java | ||
import java | ||
import semmle.code.java.security.SensitiveUiQuery | ||
import NotificationTracking::PathGraph | ||
|
||
from NotificationTracking::PathNode source, NotificationTracking::PathNode sink | ||
where NotificationTracking::flowPath(source, sink) | ||
select sink, source, sink, "This $@ is exposed in a system notification.", source, | ||
"sensitive information" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
--- | ||
category: newQuery | ||
--- | ||
* Added a new query `java/android/sensitive-notification` to detect instances of sensitive data being exposed through Android notifications. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can a
RemoteViews
contain sensitive data?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think existing models could track it, but it seems like it would theoretically be able to.