Skip to content

Commit

Permalink
[MASWE-0004] Sensitive Data Not Excluded From Backup (OWASP#2866)
Browse files Browse the repository at this point in the history
* Add weakness page

* Update MASWE-0040.md with new links (OWASP#2867)

* [MASTG-TOOL-0108] Update Corellium tools page with benefits and limitations (OWASP#2834)

* Add Corellium tools page with benefits and limitations

* Apply suggestions from code review

Co-authored-by: Jeroen Beckers <[email protected]>

* fix md links

* update corellium content

* update tool id

---------

Co-authored-by: Jeroen Beckers <[email protected]>
Co-authored-by: Jeroen Beckers <[email protected]>

* [MASTG-TOOL-0109] Add Nope proxy (by @appknox) (OWASP#2868)

* added Nope-proxy tool

* fix spaces

* small fixes

* update tool ID

---------

Co-authored-by: Carlos Holguera <[email protected]>

* [MASTG-TOOL-0110] Add semgrep (OWASP#2871)

* add semgrep

* update references to @MASTG-TOOL-0110

* updated donators

* Typo fix (OWASP#2874)

Co-authored-by: Jeroen Beckers <[email protected]>

* Fixes OWASP#2824 (OWASP#2873)

Co-authored-by: Jeroen Beckers <[email protected]>

* Change news link (OWASP#2876)

Co-authored-by: Jeroen Beckers <[email protected]>

* Fix news not showing (OWASP#2877)

* Update MASWE-0100.md (OWASP#2878)

add refs

* Update talks.yaml (OWASP#2883)

* [MASWE-0009] Add Weak Cryptographic Key Generation (by appknox) (OWASP#2849)

* MASWE-0009

* fix spell

* fix markdown-lint

* updated weakness

* change test ID

* add semgrep as tool

* change demo IDs

* change demo id as duplicate

* Update weaknesses/MASVS-CRYPTO/MASWE-0009.md

* Apply suggestions from code review

* updated changes

* renamed TOOL-0105 -> TOOL-0109

* fix changes

* rm semgrep (will be added separately) and update refs to the tool

* update ios demo to use r2 and the MASTestApp for iOS

* update spell checker ignore words list

* rm ios folder

* add ios folder to correct name and demo based on r2

* update MASTG-TEST-0209 with libraries and references. Extended to consider also dynamic analysis.

* change to modes of introduction

* update DEMO-0011 to be about RSA key size

* Apply suggestions from code review

* add binary for demo 11

* update r2 script and output

* Update weaknesses/MASVS-CRYPTO/MASWE-0009.md

* Update tests-beta/ios/MASVS-CRYPTO/MASTG-TEST-0209.md

Co-authored-by: Carlos Holguera <[email protected]>

* Apply suggestions from code review

Co-authored-by: Carlos Holguera <[email protected]>

* Apply suggestions from code review

Co-authored-by: Sven <[email protected]>

* updated android demo

* changed semgrep rule to standard form

* Apply suggestions from code review

* remove extra line

* fix link

---------

Co-authored-by: Sven <[email protected]>
Co-authored-by: Carlos Holguera <[email protected]>

* fix rule filename (OWASP#2885)

* Update MASTG-DEMO-0012.md rule name (OWASP#2886)

* Fix title for MASTG-DEMO-0011.md (OWASP#2888)

* Update Sensitive Data Not Excluded From Backup

* Add a test and a demo for Android

* Add a test for iOS

* Add a demo for iOS

* Fix markdown files according to the linter

* Fix conflicts in IDs

* Apply suggestions from code review

Co-authored-by: Carlos Holguera <[email protected]>

* Update weaknesses/MASVS-STORAGE/MASWE-0004.md

* Apply suggestions from code review

Co-authored-by: Carlos Holguera <[email protected]>

* Update IDs and rephrase the evaluation sections

* Use r2 script for demo

* Fix the Observations section

* Apply suggestions from code review

* Add AndroidManifest.xml for MASTG-DEMO-0020

* rename demo folder

* Apply suggestions from code review

* Update MASWE-0004.md status to "new"

* Refactor Android backup instructions for MASTG-TEST-0216

* fix typo

---------

Co-authored-by: Carlos Holguera <[email protected]>
Co-authored-by: Jeroen Beckers <[email protected]>
Co-authored-by: Jeroen Beckers <[email protected]>
Co-authored-by: Prudhv! <[email protected]>
Co-authored-by: Sven <[email protected]>
Co-authored-by: Jeroen Beckers <[email protected]>
  • Loading branch information
7 people authored Oct 19, 2024
1 parent 67baf33 commit 4ffb7e2
Show file tree
Hide file tree
Showing 17 changed files with 358 additions and 7 deletions.
27 changes: 27 additions & 0 deletions demos/android/MASVS-STORAGE/MASTG-DEMO-0020/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,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>
43 changes: 43 additions & 0 deletions demos/android/MASVS-STORAGE/MASTG-DEMO-0020/MASTG-DEMO-0020.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
platform: android
title: Uses of AutoBackup backup_rules.xml to Exclude Data From Backups
id: MASTG-DEMO-0020
code: [kotlin]
test: MASTG-TEST-0216
---

### Sample

The following samples contain:

- the Kotlin code that creates two files inside [`filesDir`](https://developer.android.com/reference/android/content/Context#getFilesDir()).
- the AndroidManifest.xml with the `android:fullBackupContent` attribute (for Android 11 and lower).
- the `backup_rules.xml` file including a rule to exclude one of the files using an `<exclude>` element.

{{ MastgTest.kt # AndroidManifest.xml # backup_rules.xml }}

### Steps

1. Install the target app on your device.
2. Execute `run_before.sh` which runs @MASTG-TOOL-0004.
3. Open the app and exercise it to trigger file creations.
4. Execute `run_after.sh`.
5. Close the app once you finish testing.

{{ run.sh }}

### Observation

The output contains the list of all restored files which were written to the `./restored_files/` directory:

{{ output.txt }}

The app wrote two files: `backup_excluded_secret.txt` which is not restored because it is marked as `exclude` in the `backup_rules.xml` file, and `secret.txt`, which contains a password:

{{ restored_files/secret.txt }}

Note that `/data/user/0/org.owasp.mastestapp/files/` is equivalent to `/data/data/org.owasp.mastestapp/files/`.

### Evaluation

The test fails because `secret.txt` is restored from the backup and it contains sensitive data.
35 changes: 35 additions & 0 deletions demos/android/MASVS-STORAGE/MASTG-DEMO-0020/MastgTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,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 externalStorageDir = context.getExternalFilesDir(null)

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

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

return "SUCCESS!!\n\nFiles saved to $externalStorageDir"
}
}
4 changes: 4 additions & 0 deletions demos/android/MASVS-STORAGE/MASTG-DEMO-0020/backup_rules.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<exclude domain="file" path="backup_excluded_secret.txt" />
</full-backup-content>
2 changes: 2 additions & 0 deletions demos/android/MASVS-STORAGE/MASTG-DEMO-0020/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/data/user/0/org.owasp.mastestapp/files/profileInstalled
/data/user/0/org.owasp.mastestapp/files/secret.txt
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
secr3tPa$$W0rd
42 changes: 42 additions & 0 deletions demos/android/MASVS-STORAGE/MASTG-DEMO-0020/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/bash
# USAGE: ./run.sh <package name>
# EXAMPLE: ./run.sh org.owasp.mastestapp
# SUMMARY: List all files restored from a backup

# Script from https://developer.android.com/identity/data/testingbackup
# Initialize and create a backup
adb shell bmgr enable true
adb shell bmgr transport com.android.localtransport/.LocalTransport | grep -q "Selected transport" || (echo "Error: error selecting local transport"; exit 1)
adb shell settings put secure backup_local_transport_parameters 'is_encrypted=true'
adb shell bmgr backupnow "$1" | grep -F "Package $1 with result: Success" || (echo "Backup failed"; exit 1)

# Uninstall and reinstall the app to clear the data and trigger a restore
apk_path_list=$(adb shell pm path "$1")
OIFS=$IFS
IFS=$'\n'
apk_number=0
for apk_line in $apk_path_list
do
(( ++apk_number ))
apk_path=${apk_line:8:1000}
adb pull "$apk_path" "myapk${apk_number}.apk"
done
IFS=$OIFS
adb shell pm uninstall --user 0 "$1"
apks=$(seq -f 'myapk%.f.apk' 1 $apk_number)
adb install-multiple -t --user 0 $apks

# Clean up
adb shell bmgr transport com.google.android.gms/.backup.BackupTransportService
rm $apks

echo "Done"


# Demo script
# You might need to enable root for ADB first with `adb root`
adb shell "find /data/user/0/org.owasp.mastestapp/ -type f" > output.txt
mkdir -p restored_files
while read -r line; do
adb pull "$line" ./restored_files/
done < output.txt
32 changes: 32 additions & 0 deletions demos/ios/MASVS-STORAGE/MASTG-DEMO-0019/MASTG-DEMO-0019.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
platform: ios
title: Uses of isExcludedFromBackupKey to Exclude Data From Backups
code: [swift]
id: MASTG-DEMO-0019
test: MASTG-TEST-0215
---

### Sample

The code snippet below shows sample code that creates a file and marks it with `isExcludedFromBackupKey`.

{{ MastgTest.swift }}

### Steps

1. Unzip the app package and locate the main binary file (@MASTG-TECH-0058), which in this case is `./Payload/MASTestApp.app/MASTestApp`.
2. Run `run.sh`.

{{ run.sh }}

### Observation

The output reveals the use of `isExcludedFromBackupKey` in the app.

{{ output.txt }}

### Evaluation

The test fails because `secret.txt` might be restored from the backup and it contains sensitive data.

You can see the call to `isExcludedFromBackupKey` at `0x100004594` and the associated file, `secret.txt` at `0x10000443c`.
Binary file not shown.
27 changes: 27 additions & 0 deletions demos/ios/MASVS-STORAGE/MASTG-DEMO-0019/MastgTest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import SwiftUI

struct MastgTest {
static func mastgTest(completion: @escaping (String) -> Void) {
// Define the file name and create the file URL
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileName = "secret.txt"
var fileURL = documentsDirectory.appendingPathComponent(fileName)

// Create the file content
let fileContent = "MAS_API_KEY=8767086b9f6f976g-a8df76"

do {
try fileContent.write(to: fileURL, atomically: true, encoding: .utf8)

// Set the isExcludedFromBackup flag
var resourceValues = URLResourceValues()
resourceValues.isExcludedFromBackup = true

try fileURL.setResourceValues(resourceValues)

} catch {
completion("Error creating file: \(error)")
}
completion("File created and isExcludedFromBackup flag set to true")
}
}
20 changes: 20 additions & 0 deletions demos/ios/MASVS-STORAGE/MASTG-DEMO-0019/isExcludedFromBackup.r2
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
!printf "Uses of isExcludedFromBackup:\n"
afl~isExcludedFromBackup

!printf "\n"

!printf "xrefs to isExcludedFromBackup:\n"
axt @ 0x10000cc28

!printf "\n"
!printf "Use of isExcludedFromBackup:\n"

pd-- 5 @ 0x100004594

!printf "\n"
!print "Search for secret.txt"
/ secret.txt

!printf "\n"
!printf "Use of the string secret.txt:\n"
pd-- 5 @ 0x10000443c
31 changes: 31 additions & 0 deletions demos/ios/MASVS-STORAGE/MASTG-DEMO-0019/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Uses of isExcludedFromBackup:
0x10000cc28 1 12 sym.imp.Foundation.URLResourceValues.isExcludedFromBackup...Sgvs

xrefs to isExcludedFromBackup:
sym.MASTestApp.MastgTest.mastg.completion...FZ 0x100004594 [CALL:--x] bl sym.imp.Foundation.URLResourceValues.isExcludedFromBackup...Sgvs

Use of isExcludedFromBackup:
│ 0x100004580 080540f9 ldr x8, [x8, 8]
│ 0x100004584 00013fd6 blr x8
│ 0x100004588 e80314aa mov x8, x20
│ 0x10000458c a1210094 bl sym.imp.Foundation.URLResourceValues...VACycfC...ycfC
│ 0x100004590 20008052 mov w0, 1
│ 0x100004594 a5210094 bl sym Foundation.URLResourceValues.isExcludedFromBackup...Sgvs ; sym.imp.Foundation.URLResourceValues.isExcludedFromBackup...Sgvs
│ 0x100004598 a82300d1 sub x8, x29, 8
│ 0x10000459c 140150f8 ldur x20, [x8, -0x100]
│ 0x1000045a0 a82302d1 sub x8, x29, 0x88
│ 0x1000045a4 080150f8 ldur x8, [x8, -0x100]

0x10000dbe6 hit4_0 .lueFatal errorsecret.txt.

Use of the string secret.txt:
│ 0x100004428 e00314aa mov x0, x20
│ 0x10000442c 00013fd6 blr x8
│ 0x100004430 a08351f8 ldur x0, [x29, -0xe8] ; void *instance
│ 0x100004434 1b220094 bl sym.imp.objc_release ; void objc_release(void *instance)
│ 0x100004438 400000b0 adrp x0, sym.imp.swift_getObjCClassMetadata ; 0x10000d000
│ 0x10000443c 00982f91 add x0, x0, 0xbe6 ; 0x10000dbe6 ; "secret.txt"
│ 0x100004440 48018052 mov w8, 0xa
│ 0x100004444 e10308aa mov x1, x8
│ 0x100004448 28008052 mov w8, 1
│ 0x10000444c a91303d1 sub x9, x29, 0xc4
2 changes: 2 additions & 0 deletions demos/ios/MASVS-STORAGE/MASTG-DEMO-0019/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
r2 -q -i isExcludedFromBackup.r2 -A MASTestApp
39 changes: 39 additions & 0 deletions tests-beta/android/MASVS-STORAGE/MASTG-TEST-0216.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
platform: android
title: Sensitive Data Not Excluded From Backup
id: MASTG-TEST-0216
type: [dynamic, filesystem]
weakness: MASWE-0004
---

## Overview

This test verifies whether your app correctly instructs the system to exclude sensitive files from backups.

["Android Backups"](../../../0x05d-Testing-Data-Storage/#backups) can be implemented via [Auto Backup](https://developer.android.com/identity/data/autobackup) (Android 6.0 (API level 23) and higher) and [Key-value backup](https://developer.android.com/identity/data/keyvaluebackup) (Android 2.2 (API level 8) and higher). Auto Backup is the recommended approach by Android as it is enabled by default and requires no work to implement.

To exclude specific files when using Auto Backup, developers must explicitly define exclusion rules in the `exclude` tag in `backup_rules.xml` (for Android 11 or lower using `android:fullBackupContent`) or `data_extraction_rules.xml` (for Android 12 and higher using `android:dataExtractionRules`), depending on the target API. The `cloud-backup` and `device-transfer` parameters can be used to exclude files from cloud backups and device-to-device transfers, respectively. The key-value backup approach requires developers to set up a [`BackupAgent`](https://developer.android.com/identity/data/keyvaluebackup#BackupAgent) or [`BackupAgentHelper`](https://developer.android.com/identity/data/keyvaluebackup#BackupAgentHelper) and specify what data should be backed up.

Regardless of which approach the app used, Android provides a way to start the backup daemon to back up and restore app files. You can use this daemon for testing purposes and initiate the backup process and restore the app's data, allowing you to verify which files were restored from the backup.

## Steps

1. Start the device.
2. Install an app on your device.
3. Launch and use the app going through the various workflows while inputting sensitive data wherever you can.
4. Run the backup daemon.
5. Uninstall and reinstall the app but don't open it anymore.
6. Restore the data from the backup and get the list of restored files.

## Observation

The output should contain a list of files that are restored from the backup.

## Evaluation

The test fails if any of the files are considered sensitive.

For the sensitive files found, instruct the system to exclude them from the backup:

- If you are using Auto Backup, mark them with the `exclude` tag in `backup_rules.xml` (for Android 11 or lower using `android:fullBackupContent`) or `data_extraction_rules.xml` (for Android 12 and higher using `android:dataExtractionRules`), depending on the target API. Make sure to use both the `cloud-backup` and `device-transfer` parameters.
- If you are using the key-value approach, set up your [BackupAgent](https://developer.android.com/identity/data/keyvaluebackup#BackupAgent) accordingly.
31 changes: 31 additions & 0 deletions tests-beta/ios/MASVS-STORAGE/MASTG-TEST-0215.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
platform: ios
title: Sensitive Data Not Excluded From Backup
id: MASTG-TEST-0215
type: [static, filesystem]
weakness: MASWE-0004
---

## Overview

This test verifies whether your app correctly instructs the system to exclude sensitive files from backups.

Files in the `/tmp` and `/Library/Caches` subdirectories of the app container are excluded from iCloud Backups. For files and directories in any other locations within the app container, iOS provides the [`isExcludedFromBackup`](https://developer.apple.com/documentation/foundation/urlresourcevalues/1780002-isexcludedfrombackup) API to guide the system not to back up a given file or directory. However, this API [does not guarantee guarantee the actual exclusion](https://developer.apple.com/documentation/foundation/optimizing_your_app_s_data_for_icloud_backup/#3928527):

> "The `isExcludedFromBackup` resource value exists only to provide guidance to the system about which files and directories it can exclude; it's not a mechanism to guarantee those items never appear in a backup or on a restored device."
Therefore, the only way to properly protect your files from a backup is to encrypt them.

## Steps

1. Run a static analysis tool such as @MASTG-TOOL-0073 on the app binary, or use a dynamic analysis tool like @MASTG-TOOL-0039, and look for uses of `isExcludedFromBackup` API.

## Observation

The output should contain the disassembled code of the functions using `isExcludedFromBackup` and if possible the list of affected files.

## Evaluation

The test case fails if you can find the use of `isExcludedFromBackup` within the source code and if any of the affected files can be considered sensitive.

For the sensitive files found, and in addition to using `isExcludedFromBackup`, make sure to encrypt them, as `isExcludedFromBackup` does not guarantee the exclusion.
29 changes: 22 additions & 7 deletions weaknesses/MASVS-STORAGE/MASWE-0004.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,28 @@ mappings:
refs:
- https://developer.android.com/guide/topics/data/autobackup#include-exclude-android-11
- https://developer.android.com/guide/topics/data/autobackup#include-exclude-android-12
draft:
description: sensitive data can be excluded to prevent it from being backed up.
topics:
- '`android:fullBackupContent` (Android 11-) or `android:dataExtractionRules` (Android
12+)'
- iOS `isExcludedFromBackup` (iOS)
status: draft
status: new

---

## Overview

iOS and Android automatically back up app data to cloud services, and users can also create local backups on physical machines, or backups are automatically created during data transfers when switching between phones. When developers fail to properly configure how their app handles backups and neglect to exclude sensitive files, the backups may contain sensitive user and app data. Under certain conditions, the backups may not be adequately secured by the cloud provider, or a malicious actor could tamper with the backed up files, potentially altering the app's behavior or extracting confidential information.

## Impact

- **Modification of App's Behavior**: An attacker can tamper with data inside the backup, altering the app's logic. For example, they could modify a database that tracks the state of premium features and then restore the modified backup to the device. Another common scenario is backing up the device before redeeming a one-time coupon and restoring the backup afterward, which would allow the malicious actor to reuse the same coupon multiple times.
- **Loss of Confidentiality**: Sensitive data stored in backups (e.g., personal information, photos, documents or audio files) may be extracted by attackers, leading to privacy breaches.
- **Leakage of Authentication Material**: An attacker can extract passwords, cryptographic keys, and session tokens to facilitate additional attacks, such as identity theft, account takeover, or unauthorized access.

## Modes of Introduction

- **Automatic System Backups**: By default, iOS and Android back up app data to the cloud once the user consents during the initial setup.
- **Local Backups**: Users can back up their devices to local systems (e.g., laptops). If local backups are stored unencrypted or not securely handled, attackers could tamper with this data.
- **Device-To-Device Transfer**: Transferring data between devices (e.g., via iCloud or Google's device-to-device migration tools) enables an attacker to perform similar attacks.

## Mitigations

- Exclude sensitive files from backups using platform-specific attributes, such as `android:allowBackup` or `BackupAgent` with `excludeFromBackup` for Android. On iOS, API such as `NSURLIsExcludedFromBackupKey` [doesn't guarantee](https://developer.apple.com/documentation/foundation/optimizing_your_app_s_data_for_icloud_backup/#3928527) exclusion from the backup. Therefore, you should encrypt your data instead.
- Store sensitive data in locations excluded from backups by default, like the Keychain or `Library/Caches` on iOS.
- Encrypt sensitive data before storage to ensure confidentiality, even if it gets backed up.

0 comments on commit 4ffb7e2

Please sign in to comment.