# Exploiting Insecure Data Storage In Mobile

> 识别并利用 Android 和 iOS 移动应用程序中的本地数据不安全存储漏洞，包括未加密数据库、全局可读文件、不安全的 SharedPreferences、明文凭据存储以及 Keychain/Keystore 使用不当。适用于针对 OWASP M9（不安全数据存储）开展移动渗透测试，或评估 MASVS-STORAGE 合规性。适用于移动数据存储安全、本地存储利用、SharedPreferences 分析或移动数据泄露评估等请求场景。

- Skill: `killvxk/exploiting-insecure-data-storage-in-mobile` (Agent Skill, multi-file: 8 files)
- Install (CLI): `npx skillmds@latest add killvxk/exploiting-insecure-data-storage-in-mobile`
- Raw SKILL.md: https://api.skillmd.com/api/skills/killvxk/exploiting-insecure-data-storage-in-mobile/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- License: Apache-2.0
- Author: killvxk (https://skillmd.com/u/killvxk)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/killvxk/exploiting-insecure-data-storage-in-mobile

---

# 利用移动应用不安全数据存储

## 适用场景

使用此技能的场景：
- 评估移动应用是否在设备文件系统上安全存储敏感数据
- 测试通过 SharedPreferences、SQLite 数据库或 plist 文件导致的凭据泄露
- 评估 Keychain/Keystore 实现的访问控制属性是否正确
- 在移动渗透测试中执行静态数据安全评估

**不适用于**：未获授权情况下在生产用户设备上使用 —— 数据提取技术需要物理访问权限或 root/越狱权限。

## 前置条件

- 已 root 的 Android 设备或可访问 ADB 的模拟器
- 已越狱的 iOS 设备（可通过 SSH 访问）或经 Objection 注入的 IPA
- ADB（Android Debug Bridge）用于 Android 文件系统访问
- SQLite3 CLI 用于数据库检查
- Frida/Objection 用于运行时数据提取
- 目标应用已安装并已运行（已登录、数据已缓存）

## 工作流程

### 步骤 1：枚举应用数据存储位置

**Android 存储路径：**
```bash
# 内部存储（应用私有，需要 root）
/data/data/<package_name>/
├── shared_prefs/      # SharedPreferences XML 文件
├── databases/         # SQLite 数据库
├── files/             # 通用文件
├── cache/             # 缓存数据
├── lib/               # 本地库
└── app_webview/       # WebView 数据

# 外部存储（旧版 Android 上全局可读）
/sdcard/Android/data/<package_name>/

# 检查全局可读文件
adb shell run-as <package_name> ls -la /data/data/<package_name>/
```

**iOS 存储路径：**
```bash
# 应用沙盒（在已越狱设备上可通过 SSH 访问）
/var/mobile/Containers/Data/Application/<UUID>/
├── Documents/         # 用户数据，默认备份
├── Library/
│   ├── Preferences/   # NSUserDefaults plist 文件
│   ├── Caches/        # 缓存数据
│   └── Application Support/
└── tmp/               # 临时文件
```

### 步骤 2：提取并分析 SharedPreferences（Android）

```bash
# 拉取 SharedPreferences 文件
adb shell run-as <package_name> cat shared_prefs/*.xml

# 或在 root 设备上
adb pull /data/data/<package_name>/shared_prefs/ ./shared_prefs/

# 搜索敏感数据
grep -ri "password\|token\|secret\|key\|session\|auth\|cookie" shared_prefs/
```

常见不安全存储模式：
```xml
<!-- 明文凭据 -->
<string name="user_password">mysecretpass123</string>
<string name="auth_token">eyJhbGciOiJIUzI1NiIs...</string>
<string name="api_key">sk-live-abc123def456</string>

<!-- 敏感个人身份信息（PII） -->
<string name="user_ssn">123-45-6789</string>
<string name="credit_card">4111111111111111</string>
```

### 步骤 3：分析 SQLite 数据库

```bash
# 拉取数据库
adb pull /data/data/<package_name>/databases/ ./databases/

# 打开并检查
sqlite3 databases/app.db
.tables
.schema users
SELECT * FROM users;
SELECT * FROM sessions;
SELECT * FROM tokens;

# 在所有表中搜索敏感列
sqlite3 databases/app.db ".dump" | grep -i "password\|token\|secret\|credit"
```

检查未加密的 SQLCipher 数据库：
```bash
# 如果数据库无需密码即可打开，则未加密
sqlite3 databases/app.db "SELECT count(*) FROM sqlite_master;"
# 执行成功 = 未加密（漏洞）
```

### 步骤 4：检查 iOS Keychain 存储

```bash
# 使用 Objection
objection --gadget com.target.app explore
ios keychain dump

# 检查保护级别属性
# kSecAttrAccessibleWhenUnlocked —— 适用于大多数数据
# kSecAttrAccessibleAlways —— 存在漏洞：设备锁定时仍可访问
# kSecAttrAccessibleAfterFirstUnlock —— 适用于后台应用
```

### 步骤 5：评估外部存储和备份暴露

**Android：**
```bash
# 检查是否启用了备份
aapt dump badging target.apk | grep -i "allowBackup"
# android:allowBackup="true" = 漏洞

# 提取备份数据
adb backup -f backup.ab -apk <package_name>
java -jar abe.jar unpack backup.ab backup.tar
tar xvf backup.tar
# 检查提取数据中的敏感信息

# 检查外部存储
adb shell ls -la /sdcard/Android/data/<package_name>/
```

**iOS：**
```bash
# 检查备份排除设置
# Documents/ 中的文件默认备份
# 检查 NSURLIsExcludedFromBackupKey 属性
objection --gadget com.target.app explore
ios plist cat Info.plist
```

### 步骤 6：运行时内存分析

```bash
# 转储进程内存以查找敏感数据
objection --gadget com.target.app explore
memory search "password" --string
memory search "BEGIN RSA PRIVATE KEY" --string
memory dump all /tmp/memdump/

# Android：检查日志中的敏感数据
adb logcat -d | grep -i "password\|token\|key\|secret"
```

## 核心概念

| 术语 | 定义 |
|------|------|
| **SharedPreferences** | Android 基于 XML 格式的键值存储；常被误用于明文存储凭据 |
| **Keychain Services** | iOS 安全凭据存储，在现代设备上由 Secure Enclave 硬件支持 |
| **Android Keystore** | Android 上由硬件支持的密码密钥存储；密钥无法从设备中提取 |
| **SQLCipher** | SQLite 数据库的透明加密扩展；防止在没有密码的情况下提取数据 |
| **Data Protection API** | iOS 文件级加密，与设备密码绑定；通过保护级别属性控制 |

## 工具与系统

- **ADB（Android Debug Bridge）**：用于 Android 设备交互和文件系统访问的命令行工具
- **Objection**：基于 Frida 的运行时探索工具，用于 Keychain 转储和内存检查
- **SQLite3**：用于检查未加密 SQLite 数据库的命令行界面
- **Android Backup Extractor（ABE）**：用于解包 ADB 备份文件以检查存储数据的工具
- **iExplorer**：用于浏览 iOS 应用沙盒文件系统的 GUI 工具

## 常见陷阱

- **已加密但密钥在代码中**：部分应用对数据库加密，却将加密密钥存储在 SharedPreferences 中或硬编码在二进制文件里。检查加密措施的同时，务必检查密钥存储位置。
- **MODE_WORLD_READABLE 弃用**：该标志在 API 17 中已被弃用，但旧版应用可能仍在使用，使 SharedPreferences 可被其他应用读取。
- **iOS 备份范围**：默认情况下，Documents 目录中的所有文件都会包含在 iTunes/iCloud 备份中。验证敏感文件是否已设置备份排除属性。
- **剪贴板暴露**：复制到剪贴板的数据可被所有应用访问。检查应用是否将敏感数据（密码、令牌）复制到了剪贴板。

