Skip to content

Java: Improve Android app detection #16914

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 7 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions java/ql/lib/change-notes/2024-06-12-isandroid-deprecated.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: deprecated
---
* The predicate `isAndroid` from the module `semmle.code.java.security.AndroidCertificatePinningQuery` has been deprecated. Use `semmle.code.java.frameworks.android.Android::inAndroidApplication(File)` instead.
14 changes: 14 additions & 0 deletions java/ql/lib/semmle/code/java/frameworks/android/Android.qll
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@
import java
private import semmle.code.xml.AndroidManifest

/**
* Holds if in `file`'s directory or some parent directory there is an `AndroidManifestXmlFile`
* that defines at least one activity, service or contest provider, suggesting this file is
* part of an android application.
*/
predicate inAndroidApplication(File file) {
file.isSourceFile() and
exists(AndroidManifestXmlFile amxf, Folder amxfDir |
amxf.definesAndroidApplication() and amxfDir = amxf.getParentContainer()
|
file.getParentContainer+() = amxfDir
)
}

/**
* Gets a reflexive/transitive superType
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.frameworks.Networking
import semmle.code.java.security.Encryption
import semmle.code.java.security.HttpsUrls
private import semmle.code.java.frameworks.android.Android

/** An Android Network Security Configuration XML file. */
class AndroidNetworkSecurityConfigFile extends XmlFile {
Expand All @@ -19,8 +20,12 @@ class AndroidNetworkSecurityConfigFile extends XmlFile {
}
}

/** Holds if this database is of an Android application. */
predicate isAndroid() { exists(AndroidManifestXmlFile m) }
/**
* DEPRECATED. Use `semmle.code.java.frameworks.android.Android::inAndroidApplication` instead.
*
* Holds if this database contains an Android manifest file.
*/
deprecated predicate isAndroid() { exists(AndroidManifestXmlFile m) }

/** Holds if the given domain name is trusted by the Network Security Configuration XML file. */
private predicate trustedDomainViaXml(string domainName) {
Expand Down Expand Up @@ -122,7 +127,7 @@ private module UntrustedUrlFlow = TaintTracking::Global<UntrustedUrlConfig>;

/** Holds if `node` is a network communication call for which certificate pinning is not implemented. */
predicate missingPinning(MissingPinningSink node, string domain) {
isAndroid() and
inAndroidApplication(node.getLocation().getFile()) and
exists(DataFlow::Node src | UntrustedUrlFlow::flow(src, node) |
if trustedDomain(_) then domain = getDomain(src.asExpr()) else domain = ""
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,15 @@
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.security.CleartextStorageQuery
import semmle.code.xml.AndroidManifest
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.FlowSinks
private import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.frameworks.android.Android

private class AndroidFilesystemCleartextStorageSink extends CleartextStorageSink {
AndroidFilesystemCleartextStorageSink() {
filesystemInput(_, this.asExpr()) and
// Make sure we are in an Android application.
exists(AndroidManifestXmlFile manifest)
inAndroidApplication(this.getLocation().getFile())
}
}

Expand Down
15 changes: 15 additions & 0 deletions java/ql/lib/semmle/code/xml/AndroidManifest.qll
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@ class AndroidManifestXmlFile extends XmlFile {
* Holds if this Android manifest file is located in a build directory.
*/
predicate isInBuildDirectory() { this.getFile().getRelativePath().matches("%build%") }

/**
* Holds if this file defines at least one activity, service or contest provider,
* and so it corresponds to an android application rather than a library.
*/
predicate definesAndroidApplication() {
exists(AndroidComponentXmlElement acxe |
this.getManifestElement().getApplicationElement().getAComponentElement() = acxe and
(
acxe instanceof AndroidActivityXmlElement or
acxe instanceof AndroidServiceXmlElement or
acxe instanceof AndroidProviderXmlElement
)
)
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The heuristic to enable certain Android queries has been improved. Now it ignores Android Manifests which don't define an activity, content provider or service. We also only consider files which are under a folder containing such an Android Manifest for these queries. This should remove some false positive alerts.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
android:versionName="0.1" >

<application android:networkSecurityConfig="@xml/NetworkSecurityConfig">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
android:versionName="0.1" >

<application android:networkSecurityConfig="@xml/NetworkSecurityConfig">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
android:versionName="0.1" >

<application android:networkSecurityConfig="@xml/NetworkSecurityConfig">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
android:versionName="0.1" >

<application android:networkSecurityConfig="@xml/NetworkSecurityConfig">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
</manifest>
Loading