Skip to content

MASTG-DEMO-0034: Backup and Restore App Data with semgrep

Content in BETA

This content is in beta and still under active development, so it is subject to change any time (e.g. structure, IDs, content, URLs, etc.).

Send Feedback

Download MASTG-DEMO-0034 APK Open MASTG-DEMO-0034 Folder Build MASTG-DEMO-0034 APK

Sample

This demo uses the sample from Data Exclusion using backup_rules.xml with Backup Manager.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package org.owasp.mastestapp

import android.content.Context
import android.util.Log
import java.io.File
import java.io.FileOutputStream
import java.io.IOException

class MastgTest (private val context: Context){

    fun mastgTest(): String {

        val internalStorageDir = context.filesDir

        val fileName = File(internalStorageDir, "secret.txt")
        val fileNameOfBackupExcludedFile = File(internalStorageDir, "backup_excluded_secret.txt")
        val fileContent = "secr3tPa\$\$W0rd\n"

        try {
            FileOutputStream(fileName).use { output ->
                output.write(fileContent.toByteArray())
                Log.d("WriteInternalStorage", "File written to internal storage successfully.")
            }
            FileOutputStream(fileNameOfBackupExcludedFile).use { output ->
                output.write(fileContent.toByteArray())
                Log.d("WriteInternalStorage", "File written to internal storage successfully.")
            }
        } catch (e: IOException) {
            Log.e("WriteInternalStorage", "Error writing file to internal storage", e)
            return "ERROR!!\n\nError writing file to internal storage"
        }

        return "SUCCESS!!\n\nFiles saved to $internalStorageDir"
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MASTestApp"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:theme="@style/Theme.MASTestApp">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
    <include domain="file" path="." requireFlags="clientSideEncryption" />
    <exclude domain="file" path="backup_excluded_secret.txt" />
</full-backup-content>

Steps

  1. Read the AndroidManifest.xml and backup_rules.xml files.
  2. Run the semgrep script.
1
NO_COLOR=true semgrep -c ../../../../rules/mastg-android-backup-manifest.yml ../MASTG-DEMO-0020/AndroidManifest.xml > output.txt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
rules:
  - id: mastg-android-backup-manifest-allow-backup
    severity: WARNING
    languages:
      - xml
    metadata:
      summary: This rule inspects the AndroidManifest.xml for allowBackup.
      references:
        - https://developer.android.com/guide/topics/data/autobackup
    message: "[MASVS-STORAGE-2] allowBackup detected as $ARG."
    patterns:
      - pattern: 'android:allowBackup="$ARG"'
  - id: mastg-android-backup-manifest-backup-rules
    severity: WARNING
    languages:
      - xml
    metadata:
      summary: This rule inspects the AndroidManifest.xml for backup rules.
      references:
        - https://developer.android.com/guide/topics/data/autobackup
    message: "[MASVS-STORAGE-2] Backup rules detected."
    pattern-either:
      - pattern: 'android:fullBackupContent="@xml/backup_rules"'
      - pattern: 'android:dataExtractionRules="@xml/data_extraction_rules"'

Observation

The output contains all backup-related attributes from the AndroidManifest.xml file.

output.txt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
┌─────────────────┐
 3 Code Findings 
└─────────────────┘

    ../MASTG-DEMO-0020/AndroidManifest.xml
    ❯❱ rules.mastg-android-backup-manifest-allow-backup
          [MASVS-STORAGE-2] allowBackup detected as true.

            6 android:allowBackup="true"

    ❯❱ rules.mastg-android-backup-manifest-backup-rules
          [MASVS-STORAGE-2] Backup rules detected.

            7 android:dataExtractionRules="@xml/data_extraction_rules"
            ⋮┆----------------------------------------
            8 android:fullBackupContent="@xml/backup_rules"

Evaluation

The test fails because the sensitive file secret.txt ends up in the backup. This is due to:

  • The android:allowBackup="true" attribute in the AndroidManifest.xml file.
  • The android:fullBackupContent="@xml/backup_rules" attribute is present in the AndroidManifest.xml file.
  • The backup_rules.xml file is present in the APK and does not exclude all sensitive files.
../MASTG-DEMO-0020/backup_rules.xml
1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
    <include domain="file" path="." requireFlags="clientSideEncryption" />
    <exclude domain="file" path="backup_excluded_secret.txt" />
</full-backup-content>

The backup includes all files in the app's data directory except for backup_excluded_secret.txt.