Skip to content
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

[MASWE-0004] Sensitive Data Not Excluded From Backup #2866

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b51b366
Add weakness page
serek8 Aug 6, 2024
51d783c
Update MASWE-0040.md with new links (#2867)
cpholguera Aug 8, 2024
4ed2882
[MASTG-TOOL-0108] Update Corellium tools page with benefits and limit…
cpholguera Aug 8, 2024
eb8ff39
[MASTG-TOOL-0109] Add Nope proxy (by @appknox) (#2868)
sk3l10x1ng Aug 8, 2024
aa8d3c2
[MASTG-TOOL-0110] Add semgrep (#2871)
cpholguera Aug 8, 2024
34fffb8
updated donators
sushi2k Aug 11, 2024
94d5eb0
Typo fix (#2874)
TheDauntless Aug 12, 2024
7f4ba70
Fixes #2824 (#2873)
TheDauntless Aug 12, 2024
75d4aca
Change news link (#2876)
TheDauntless Aug 12, 2024
2f58384
Fix news not showing (#2877)
cpholguera Aug 12, 2024
7561818
Update MASWE-0100.md (#2878)
cpholguera Aug 15, 2024
d8e2e3f
Update talks.yaml (#2883)
cpholguera Aug 22, 2024
b1dcc1a
[MASWE-0009] Add Weak Cryptographic Key Generation (by appknox) (#2849)
sk3l10x1ng Aug 25, 2024
384d866
fix rule filename (#2885)
cpholguera Aug 26, 2024
c7ab9f3
Update MASTG-DEMO-0012.md rule name (#2886)
cpholguera Aug 26, 2024
a5b6eb5
Fix title for MASTG-DEMO-0011.md (#2888)
cpholguera Aug 29, 2024
01ec6fc
Update Sensitive Data Not Excluded From Backup
serek8 Sep 3, 2024
444021a
Add a test and a demo for Android
serek8 Sep 3, 2024
d913187
Merge branch 'OWASP:master' into issue-2542
serek8 Sep 3, 2024
6c71761
Add a test for iOS
serek8 Sep 3, 2024
9d50d70
Add a demo for iOS
serek8 Sep 3, 2024
45c62bb
Fix markdown files according to the linter
serek8 Sep 3, 2024
64dea15
Fix conflicts in IDs
serek8 Sep 3, 2024
e21a5e6
Apply suggestions from code review
serek8 Sep 24, 2024
83149cd
Update weaknesses/MASVS-STORAGE/MASWE-0004.md
cpholguera Sep 28, 2024
401f5b8
Apply suggestions from code review
serek8 Oct 7, 2024
3918a26
Update IDs and rephrase the evaluation sections
serek8 Oct 7, 2024
9db4282
Use r2 script for demo
serek8 Oct 7, 2024
2643176
Fix the Observations section
serek8 Oct 7, 2024
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
45 changes: 45 additions & 0 deletions demos/android/MASVS-STORAGE/MASTG-DEMO-0014/MASTG-DEMO-0014.md
serek8 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
platform: android
title: Sensitive Data Not Excluded From Backup
id: MASTG-DEMO-0014
code: [kotlin]
test: MASTG-TEST-0211
---

### Sample

The snippet below shows sample code that creates two files inside [`filesDir`](https://developer.android.com/reference/android/content/Context#getFilesDir()). One of the files is also marked as `exclude` inside `backup_rules.xml`.

{{ MastgTest.kt }}

{{ backup_rules.xml }}
serek8 marked this conversation as resolved.
Show resolved Hide resolved

### Steps

1. Install an app on your device.
serek8 marked this conversation as resolved.
Show resolved Hide resolved
2. Execute `run_before.sh` which runs @MASTG-TOOL-0004.
3. Open an app and exercise it to trigger file creations.
serek8 marked this conversation as resolved.
Show resolved Hide resolved
4. Execute `run_after.sh`.
5. Close the app once you finish testing.

{{ run.sh }}

### Observation

There is a list of all restored files inside `output.txt`.
serek8 marked this conversation as resolved.
Show resolved Hide resolved

{{ output.txt }}

Their content is inside the `./restored_files/` directory and contains:

A password:

{{ restored_files/secret.txt }}

The file was created in `/data/user/0/org.owasp.mastestapp/files/` which is equivalent to `/data/data/org.owasp.mastestapp/files/`.

Note that the sample app wrote two files: `secret.txt` and `backup_excluded_secret.txt`. The latter is not restored because it is marked as `exclude` in the `backup_rules.xml` file.

### Evaluation

If you don't intend to restore this file, this test fails.
serek8 marked this conversation as resolved.
Show resolved Hide resolved
35 changes: 35 additions & 0 deletions demos/android/MASVS-STORAGE/MASTG-DEMO-0014/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-0014/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-0014/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-0014/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 restered 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
34 changes: 34 additions & 0 deletions demos/ios/MASVS-STORAGE/MASTG-DEMO-0013/MASTG-DEMO-0013.md
serek8 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
platform: ios
title: Sensitive Data Not Excluded From Backup
code: [swift]
id: MASTG-DEMO-0013
test: MASTG-TEST-0210
---

### 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 contains information that `isExcludedFromBackupKey` was used in the app.

{{ output.txt }}

### Evaluation

In the output we can see how the `kSecAttrKeySizeInBits` attribute is set to `1024` bits (0x400 in hexadecimal) using the `x8` register. This is later used to call `SecKeyCreateRandomKey`.

{{ evaluation.txt }}

serek8 marked this conversation as resolved.
Show resolved Hide resolved
iOS doesn't guarantee that any file marked with `isExcludedFromBackupKey` will be excluded from a backup. Encrypt this file if necessary.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Binary file not shown.
27 changes: 27 additions & 0 deletions demos/ios/MASVS-STORAGE/MASTG-DEMO-0013/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")
}
}
1 change: 1 addition & 0 deletions demos/ios/MASVS-STORAGE/MASTG-DEMO-0013/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This app seems to exclude files from a backup but the developer might not be aware that the system doesn't guarantee that this file will be excluded from a backup. Make sure to encrypt this file if you want to prevent restoring this data.
6 changes: 6 additions & 0 deletions demos/ios/MASVS-STORAGE/MASTG-DEMO-0013/run.sh
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grep could be good for a quick check but if we want to obtain all references in the actual code that can be challenging. I'd suggest to use r2. The run.sh would be:

r2 -q -i isExcludedFromBackup.r2 -A MASTestApp

And the isExcludedFromBackup.r2:

!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

The output would be:

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]

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash
if grep -qiE "isExcludedFromBackup|NSURLIsExcludedFromBackupKey" ./MASTestApp; then
echo "This app appears to exclude files from backups; however, the developer may not be aware that the system does not guarantee these files will be excluded. To ensure the protection of this data, make sure to encrypt the file if you want to prevent it from being restored." > output.txt
else
echo "This app doesn't seem to use 'ExcludedFromBackup' flag." > output.txt
fi
39 changes: 39 additions & 0 deletions tests-beta/android/MASVS-STORAGE/MASTG-TEST-0211.md
serek8 marked this conversation as resolved.
Show resolved Hide resolved
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-0211
type: [dynamic, filesystem]
weakness: MASWE-0004
---

## Overview

This test verifies whether your app correctly instructs the system to exclude sensitive files from backups. There are two distinct APIs for instructing the system to exclude files:

1. [Auto Backup](https://developer.android.com/identity/data/autobackup)
2. [Key-value backup](https://developer.android.com/identity/data/autobackup)
Regardless of which API you use, Android provides a way to start the backup daemon to back up and restore your app's files. You can use this daemon to initiate the backup process and restore the app's data, allowing you to verify which files have been restored from the backup.
serek8 marked this conversation as resolved.
Show resolved Hide resolved

## 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 the app and install it again. Don't open the app anymore.

6. Restore the data from the backup.

7. Verify that restored files don't contain sensitive data. Test both Private and Shared storage locations.
serek8 marked this conversation as resolved.
Show resolved Hide resolved

## Observation

After installing the app for the second time and restoring data from the backup, inspect the files inside the Private and Shared storages and note down files with sensitive content.
serek8 marked this conversation as resolved.
Show resolved Hide resolved

## Evaluation

Once you complete the list of restored files containing sensitive data, instruct the system to exclude them from the backup. If you use Auto Backup, mark them with `exclude` tag inside `backup_rules.xml` or `data_extraction_riles.xml` depending on your target API. Make sure you use fill out both `cloud-backup` and `device-transfer` parameters. If you use Key-value approach, set up your [BackupAgent](https://developer.android.com/identity/data/keyvaluebackup#BackupAgent) accordingly.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Evaluation must start with "The test case fails if"

See https://mas.owasp.org/MASTG/tests-beta/ios/MASVS-CRYPTO/MASTG-TEST-0211/#evaluation

This content can be potentially reused for the Overview. Can you use this to create a new test using semgrep?

23 changes: 23 additions & 0 deletions tests-beta/ios/MASVS-STORAGE/MASTG-TEST-0210.md
serek8 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
platform: ios
title: Sensitive Data Not Excluded From Backup
id: MASTG-TEST-0210
type: [static, filesystem]
weakness: MASWE-0004
---

## Overview

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. However, this API does not guarantee that a file will be excluded. You can read more about it in the [Apple Documentation](https://developer.apple.com/documentation/foundation/optimizing_your_app_s_data_for_icloud_backup/). Therefore, the only way to properly protect your files from a backup is to encrypt them.
serek8 marked this conversation as resolved.
Show resolved Hide resolved

## 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

Inspect all files that you marked with `isExcludedFromBackup`.

## Evaluation

Make sure to encrypt any files you want to protect from a backup, as `isExcludedFromBackup` does not guarantee that a file will be excluded.
25 changes: 25 additions & 0 deletions weaknesses/MASVS-STORAGE/MASWE-0004.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,28 @@

---

## 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. This 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, 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.

Check failure on line 46 in weaknesses/MASVS-STORAGE/MASWE-0004.md

View workflow job for this annotation

GitHub Actions / markdown-lint-check

Trailing spaces

weaknesses/MASVS-STORAGE/MASWE-0004.md:46:415 MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1] https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md009.md
serek8 marked this conversation as resolved.
Show resolved Hide resolved
- 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.
Loading