-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Java: Add query for Improper Verification of Intent by Broadcast Receiver (CWE-925) #8669
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
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
1959f49
Add Improper Intent Verification query
joefarebrother 87f26bf
Fix typos
joefarebrother 4aed1a1
Add test cases; fix handling of recievers declared through xml
joefarebrother 8e2e8cc
Add qhelp
joefarebrother 2fc142f
Add security severity
joefarebrother d88d216
Add change note
joefarebrother 9d048e7
Apply suggestions from code review - fix typos/style, make things pri…
joefarebrother 320c671
Adress reveiw comments - make use of existing ql libraries
joefarebrother c71586e
Remove checks for dynamically registered recievers
joefarebrother a6736a9
Apply doc review suggestions -
joefarebrother f46dd8c
Fix misspellings
joefarebrother File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
79 changes: 79 additions & 0 deletions
79
java/ql/lib/semmle/code/java/security/ImproperIntentVerificationQuery.qll
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/** Definitions for the improper intent verification query. */ | ||
|
||
import java | ||
import semmle.code.java.dataflow.DataFlow | ||
import semmle.code.xml.AndroidManifest | ||
import semmle.code.java.frameworks.android.Intent | ||
|
||
/** An `onReceive` method of a `BroadcastReceiver` */ | ||
private class OnReceiveMethod extends Method { | ||
OnReceiveMethod() { this.getASourceOverriddenMethod*() instanceof AndroidReceiveIntentMethod } | ||
|
||
/** Gets the parameter of this method that holds the received `Intent`. */ | ||
Parameter getIntentParameter() { result = this.getParameter(1) } | ||
} | ||
|
||
/** A configuration to detect whether the `action` of an `Intent` is checked. */ | ||
private class VerifiedIntentConfig extends DataFlow::Configuration { | ||
VerifiedIntentConfig() { this = "VerifiedIntentConfig" } | ||
|
||
override predicate isSource(DataFlow::Node src) { | ||
src.asParameter() = any(OnReceiveMethod orm).getIntentParameter() | ||
} | ||
|
||
override predicate isSink(DataFlow::Node sink) { | ||
exists(MethodAccess ma | | ||
ma.getMethod().hasQualifiedName("android.content", "Intent", "getAction") and | ||
sink.asExpr() = ma.getQualifier() | ||
) | ||
} | ||
} | ||
|
||
/** An `onReceive` method that doesn't verify the action of the intent it receives. */ | ||
private class UnverifiedOnReceiveMethod extends OnReceiveMethod { | ||
UnverifiedOnReceiveMethod() { | ||
not any(VerifiedIntentConfig c).hasFlow(DataFlow::parameterNode(this.getIntentParameter()), _) | ||
} | ||
} | ||
|
||
/** Gets the name of an intent action that can only be sent by the system. */ | ||
string getASystemActionName() { | ||
result = | ||
[ | ||
"AIRPLANE_MODE", "AIRPLANE_MODE_CHANGED", "APPLICATION_LOCALE_CHANGED", | ||
"APPLICATION_RESTRICTIONS_CHANGED", "BATTERY_CHANGED", "BATTERY_LOW", "BATTERY_OKAY", | ||
"BOOT_COMPLETED", "CONFIGURATION_CHANGED", "DEVICE_STORAGE_LOW", "DEVICE_STORAGE_OK", | ||
"DREAMING_STARTED", "DREAMING_STOPPED", "EXTERNAL_APPLICATIONS_AVAILABLE", | ||
"EXTERNAL_APPLICATIONS_UNAVAILABLE", "LOCALE_CHANGED", "LOCKED_BOOT_COMPLETED", | ||
"MY_PACKAGE_REPLACED", "MY_PACKAGE_SUSPENDED", "MY_PACKAGE_UNSUSPENDED", "NEW_OUTGOING_CALL", | ||
"PACKAGES_SUSPENDED", "PACKAGES_UNSUSPENDED", "PACKAGE_ADDED", "PACKAGE_CHANGED", | ||
"PACKAGE_DATA_CLEARED", "PACKAGE_FIRST_LAUNCH", "PACKAGE_FULLY_REMOVED", "PACKAGE_INSTALL", | ||
"PACKAGE_NEEDS_VERIFICATION", "PACKAGE_REMOVED", "PACKAGE_REPLACED", "PACKAGE_RESTARTED", | ||
"PACKAGE_VERIFIED", "POWER_CONNECTED", "POWER_DISCONNECTED", "REBOOT", "SCREEN_OFF", | ||
"SCREEN_ON", "SHUTDOWN", "TIMEZONE_CHANGED", "TIME_TICK", "UID_REMOVED", "USER_PRESENT" | ||
] | ||
} | ||
|
||
/** An expression or XML attribute that contains the name of a system intent action. */ | ||
class SystemActionName extends AndroidActionXmlElement { | ||
string name; | ||
|
||
SystemActionName() { | ||
name = getASystemActionName() and | ||
this.getActionName() = "android.intent.action." + name | ||
} | ||
|
||
/** Gets the name of the system intent that this expression or attribute represents. */ | ||
string getSystemActionName() { result = name } | ||
} | ||
|
||
/** Holds if the XML element `rec` declares a receiver `orm` to receive the system action named `sa` that doesn't verify intents it receives. */ | ||
predicate unverifiedSystemReceiver( | ||
AndroidReceiverXmlElement rec, UnverifiedOnReceiveMethod orm, SystemActionName sa | ||
) { | ||
exists(Class ormty | | ||
ormty = orm.getDeclaringType() and | ||
rec.getComponentName() = ["." + ormty.getName(), ormty.getQualifiedName()] and | ||
rec.getAnIntentFilterElement().getAnActionElement() = sa | ||
) | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="test"> | ||
<application> | ||
<receiver android:name=".BootReceiverXml"> | ||
<intent-filter> | ||
<action android:name="android.intent.action.BOOT_COMPLETED" /> | ||
</intent-filter> | ||
</receiver> | ||
</application> | ||
</manifest> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
public class ShutdownReceiver extends BroadcastReceiver { | ||
@Override | ||
public void onReceive(final Context context, final Intent intent) { | ||
mainActivity.saveLocalData(); | ||
mainActivity.stopActivity(); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
public class ShutdownReceiver extends BroadcastReceiver { | ||
@Override | ||
public void onReceive(final Context context, final Intent intent) { | ||
if (!intent.getAction().equals(Intent.ACTION_SHUTDOWN)) { | ||
return; | ||
} | ||
mainActivity.saveLocalData(); | ||
mainActivity.stopActivity(); | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
java/ql/src/Security/CWE/CWE-925/ImproperIntentVerification.qhelp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<!DOCTYPE qhelp PUBLIC | ||
"-//Semmle//qhelp//EN" | ||
"qhelp.dtd"> | ||
|
||
<qhelp> | ||
|
||
<overview> | ||
<p> | ||
When an Android application uses a <code>BroadcastReceiver</code> to receive intents, | ||
it is also able to receive explicit intents that are sent directly to it, regardless of its filter. | ||
|
||
Certain intent actions are only able to be sent by the operating system, not third-party applications. | ||
However, a <code>BroadcastReceiver</code> that is registered to receive system intents is still able to receive | ||
intents from a third-party application, so it should check that the intent received has the expected action. | ||
Otherwise, a third-party application could impersonate the system this way to cause unintended behavior, such as a denial of service. | ||
</p> | ||
</overview> | ||
|
||
<example> | ||
<p>In the following code, the <code>ShutdownReceiver</code> initiates a shutdown procedure upon receiving an intent, | ||
without checking that the received action is indeed <code>ACTION_SHUTDOWN</code>. This allows third-party applications to | ||
send explicit intents to this receiver to cause a denial of service.</p> | ||
joefarebrother marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<sample src="Bad.java" /> | ||
<sample src="AndroidManifest.xml" /> | ||
</example> | ||
|
||
<recommendation> | ||
<p> | ||
In the <code>onReceive</code> method of a <code>BroadcastReciever</code>, the action of the received Intent should be checked. The following code demonstrates this. | ||
</p> | ||
<sample src="Good.java" /> | ||
atorralba marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</recommendation> | ||
|
||
|
||
|
||
<references> | ||
|
||
atorralba marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</references> | ||
|
||
</qhelp> |
19 changes: 19 additions & 0 deletions
19
java/ql/src/Security/CWE/CWE-925/ImproperIntentVerification.ql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/** | ||
* @name Improper verification of intent by broadcast receiver | ||
* @description A broadcast receiver that does not verify intents it receives may be susceptible to unintended behavior by third party applications sending it explicit intents. | ||
* @kind problem | ||
* @problem.severity warning | ||
* @security-severity 8.2 | ||
* @precision high | ||
* @id java/improper-intent-verification | ||
* @tags security | ||
* external/cwe/cwe-925 | ||
*/ | ||
|
||
import java | ||
import semmle.code.java.security.ImproperIntentVerificationQuery | ||
|
||
from AndroidReceiverXmlElement reg, Method orm, SystemActionName sa | ||
where unverifiedSystemReceiver(reg, orm, sa) | ||
select orm, "This reciever doesn't verify intents it receives, and is registered $@ to receive $@.", | ||
reg, "here", sa, "the system action " + sa.getName() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
category: newQuery | ||
--- | ||
* A new query "Improper verification of intent by broadcast receiver" (`java/improper-intent-verification`) has been added. | ||
This query finds instances of Android `BroadcastReceiver`s that don't verify the action string of received intents when registered | ||
to receive system intents. |
9 changes: 9 additions & 0 deletions
9
java/ql/test/query-tests/security/CWE-925/AndroidManifest.xml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="test"> | ||
<application> | ||
<receiver android:name=".BootReceiverXml"> | ||
<intent-filter> | ||
<action android:name="android.intent.action.BOOT_COMPLETED" /> | ||
</intent-filter> | ||
</receiver> | ||
</application> | ||
</manifest> |
13 changes: 13 additions & 0 deletions
13
java/ql/test/query-tests/security/CWE-925/BootReceiverXml.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package test; | ||
import android.content.Intent; | ||
import android.content.Context; | ||
import android.content.BroadcastReceiver; | ||
|
||
class BootReceiverXml extends BroadcastReceiver { | ||
void doStuff(Intent intent) {} | ||
|
||
@Override | ||
public void onReceive(Context ctx, Intent intent) { // $hasResult | ||
doStuff(intent); | ||
} | ||
} |
Empty file.
18 changes: 18 additions & 0 deletions
18
java/ql/test/query-tests/security/CWE-925/ImproperIntentVerification.ql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import java | ||
import semmle.code.java.security.ImproperIntentVerificationQuery | ||
import TestUtilities.InlineExpectationsTest | ||
|
||
class HasFlowTest extends InlineExpectationsTest { | ||
HasFlowTest() { this = "HasFlowTest" } | ||
|
||
override string getARelevantTag() { result = "hasResult" } | ||
|
||
override predicate hasActualResult(Location location, string element, string tag, string value) { | ||
tag = "hasResult" and | ||
exists(Method orm | unverifiedSystemReceiver(_, orm, _) | | ||
orm.getLocation() = location and | ||
element = orm.toString() and | ||
value = "" | ||
) | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/google-android-9.0.0 |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
What does the
its
pronoun refer to here, the app or theBroadcastReceiver
(sorry, not a developer)?Uh oh!
There was an error while loading. Please reload this page.
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.
It refers to the BroadcastReceiver