Skip to content

Commit dd23d48

Browse files
authored
Merge pull request #9939 from jcogs33/android-debug-query-inline-tests
Java: query to detect android:debuggable attribute enabled
2 parents 4901deb + 07e141c commit dd23d48

15 files changed

+247
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: feature
3+
---
4+
* Added a new predicate, `isInBuildDirectory`, in the `AndroidManifestXmlFile` class. This predicate detects if the manifest file is located in a build directory.
5+
* Added a new predicate, `isDebuggable`, in the `AndroidApplicationXmlElement` class. This predicate detects if the application element has its `android:debuggable` attribute enabled.

java/ql/lib/semmle/code/xml/AndroidManifest.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ class AndroidManifestXmlFile extends XMLFile {
1818
* Gets the top-level `<manifest>` element in this Android manifest file.
1919
*/
2020
AndroidManifestXmlElement getManifestElement() { result = this.getAChild() }
21+
22+
/**
23+
* Holds if this Android manifest file is located in a build directory.
24+
*/
25+
predicate isInBuildDirectory() { this.getFile().getRelativePath().matches("%build%") }
2126
}
2227

2328
/**
@@ -51,6 +56,17 @@ class AndroidApplicationXmlElement extends XMLElement {
5156
* Gets a component child element of this `<application>` element.
5257
*/
5358
AndroidComponentXmlElement getAComponentElement() { result = this.getAChild() }
59+
60+
/**
61+
* Holds if this application element has the attribute `android:debuggable` set to `true`.
62+
*/
63+
predicate isDebuggable() {
64+
exists(AndroidXmlAttribute attr |
65+
this.getAnAttribute() = attr and
66+
attr.getName() = "debuggable" and
67+
attr.getValue() = "true"
68+
)
69+
}
5470
}
5571

5672
/**
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
6+
<overview>
7+
<p>The Android manifest file defines configuration settings for Android applications.
8+
In this file, the <code>android:debuggable</code> attribute of the <code>application</code> element can be used to
9+
define whether or not the application can be debugged. When set to <code>true</code>, this attribute will allow the
10+
application to be debugged even when running on a device in user mode.</p>
11+
12+
<p>When a debugger is enabled, it could allow for entry points in the application or reveal sensitive information.
13+
As a result, <code>android:debuggable</code> should only be enabled during development and should be disabled in
14+
production builds.</p>
15+
16+
</overview>
17+
<recommendation>
18+
19+
<p>In Android applications, either set the <code>android:debuggable</code> attribute to <code>false</code>,
20+
or do not include it in the manifest. The default value, when not included, is <code>false</code>.</p>
21+
22+
</recommendation>
23+
<example>
24+
25+
<p>In the example below, the <code>android:debuggable</code> attribute is set to <code>true</code>.</p>
26+
27+
<sample src="DebuggableTrue.xml" />
28+
29+
<p>The corrected version sets the <code>android:debuggable</code> attribute to <code>false</code>.</p>
30+
31+
<sample src="DebuggableFalse.xml" />
32+
33+
</example>
34+
<references>
35+
36+
<li>
37+
Android Developers:
38+
<a href="https://developer.android.com/guide/topics/manifest/manifest-intro">App Manifest Overview</a>.
39+
</li>
40+
<li>
41+
Android Developers:
42+
<a href="https://developer.android.com/guide/topics/manifest/application-element#debug">The android:debuggable attribute</a>.
43+
</li>
44+
<li>
45+
Android Developers:
46+
<a href="https://developer.android.com/studio/debug#enable-debug">Enable debugging</a>.
47+
</li>
48+
49+
</references>
50+
</qhelp>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* @name Android debuggable attribute enabled
3+
* @description An enabled debugger can allow for entry points in the application or reveal sensitive information.
4+
* @kind problem
5+
* @problem.severity warning
6+
* @security-severity 7.2
7+
* @id java/android/debuggable-attribute-enabled
8+
* @tags security
9+
* external/cwe/cwe-489
10+
* @precision very-high
11+
*/
12+
13+
import java
14+
import semmle.code.xml.AndroidManifest
15+
16+
from AndroidApplicationXmlElement androidAppElem
17+
where
18+
androidAppElem.isDebuggable() and
19+
not androidAppElem.getFile().(AndroidManifestXmlFile).isInBuildDirectory()
20+
select androidAppElem.getAttribute("debuggable"), "The 'android:debuggable' attribute is enabled."
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<manifest ... >
2+
<!-- GOOD: 'android:debuggable' set to 'false' -->
3+
<application
4+
android:debuggable="false">
5+
<activity ... >
6+
</activity>
7+
</application>
8+
</manifest>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<manifest ... >
2+
<!-- BAD: 'android:debuggable' set to 'true' -->
3+
<application
4+
android:debuggable="true">
5+
<activity ... >
6+
</activity>
7+
</application>
8+
</manifest>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: newQuery
3+
---
4+
* Added a new query, `java/android/debuggable-attribute-enabled`, to detect if the `android:debuggable` attribute is enabled in the Android manifest.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
4+
package="com.example.happybirthday">
5+
6+
<!-- $ hasDebuggableAttributeEnabled --> <application
7+
android:debuggable="true"
8+
android:allowBackup="true"
9+
android:dataExtractionRules="@xml/data_extraction_rules"
10+
android:fullBackupContent="@xml/backup_rules"
11+
android:icon="@mipmap/ic_launcher"
12+
android:label="@string/app_name"
13+
android:roundIcon="@mipmap/ic_launcher_round"
14+
android:supportsRtl="true"
15+
android:theme="@style/Theme.HappyBirthday"
16+
tools:targetApi="31">
17+
<activity
18+
android:name=".MainActivity"
19+
android:exported="true">
20+
<intent-filter>
21+
<action android:name="android.intent.action.MAIN" />
22+
23+
<category android:name="android.intent.category.LAUNCHER" />
24+
</intent-filter>
25+
</activity>
26+
</application>
27+
28+
</manifest>

java/ql/test/query-tests/security/CWE-489/DebuggableAttributeEnabledTest.expected

Whitespace-only changes.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import java
2+
import semmle.code.xml.AndroidManifest
3+
import TestUtilities.InlineExpectationsTest
4+
5+
class DebuggableAttributeEnabledTest extends InlineExpectationsTest {
6+
DebuggableAttributeEnabledTest() { this = "DebuggableAttributeEnabledTest" }
7+
8+
override string getARelevantTag() { result = "hasDebuggableAttributeEnabled" }
9+
10+
override predicate hasActualResult(Location location, string element, string tag, string value) {
11+
tag = "hasDebuggableAttributeEnabled" and
12+
exists(AndroidApplicationXmlElement androidAppElem |
13+
androidAppElem.isDebuggable() and
14+
not androidAppElem.getFile().(AndroidManifestXmlFile).isInBuildDirectory()
15+
|
16+
androidAppElem.getAttribute("debuggable").getLocation() = location and
17+
element = androidAppElem.getAttribute("debuggable").toString() and
18+
value = ""
19+
)
20+
}
21+
}

0 commit comments

Comments
 (0)