上一篇
安卓安全的操作数据库
- 行业动态
- 2025-04-21
- 4
安卓数据库操作安全基础
安卓应用主要使用SQLite数据库存储数据,需注意以下安全风险:
- 明文存储风险:未加密的数据库文件可被root设备直接读取
- SQL注入破绽:动态拼接SQL语句可能导致反面代码执行
- 权限泄露风险:ContentProvider配置不当可能导致数据越权访问
- 备份破绽:未加密的数据库可能通过adb备份泄露
安全操作实践对照表
风险类型 | 不安全做法 | 安全做法 |
---|---|---|
SQL注入 | SQLiteDatabase.execSQL("SELECT FROM users WHERE name='"+inputName+"'") |
使用占位符和SQLiteStatement 参数绑定 |
数据加密 | 明文存储用户密码、token等敏感信息 | 使用AES加密敏感字段,密钥存储在Keystore |
权限控制 | 暴露ContentProvider且未设置权限 | 配置android:exported="false" ,使用自定义权限 |
文件存储 | 数据库文件存储在常规目录 | 使用getDatabasePath().getAbsolutePath() 获取路径,设置文件权限为600 |
关键防护措施
- 参数化查询:
// 不安全示例 String sql = "SELECT FROM users WHERE id=" + userId; Cursor cursor = db.rawQuery(sql, null);
// 安全示例
String sql = “SELECT FROM users WHERE id=?”;
Cursor cursor = db.rawQuery(sql, new String[]{String.valueOf(userId)});
2. 数据加密方案:
```java
// 使用SQLCipher加密数据库
NetSqlAdapter adapter = new NetSqlAdapter(context, "encrypted.db");
SQLiteDatabase db = adapter.openDatabase();
// 字段级加密示例(AES)
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] encrypted = cipher.doFinal(plaintext.getBytes());
- 权限最小化配置:
<provider android:name=".MyContentProvider" android:exported="false" android:permission="com.example.MY_READ_PERMISSION"/>
敏感数据保护清单
数据类型 | 保护措施 |
---|---|
用户密码 | 哈希存储(BCrypt/PBKDF2)+ 盐值 |
支付Token | AES-256加密存储,独立密钥管理 |
身份认证 | 结合设备指纹/生物识别特征 |
密钥存储 | 使用Android Keystore系统 |
常见破绽防御对照
- SQL注入防御:
- 禁用Dynamic SQL
- 使用ORM框架(如Room)的参数绑定功能
- 特殊字符转义处理
- 数据库文件防护:
- 启用SQLite数据库的WAL模式时限制文件权限
- 使用File-based encryption(FBE)特性
- 数据库文件存储路径随机化处理
相关问题与解答
Q1:如何检测应用是否存在SQL注入破绽?
A1:可通过以下方式检测:
- 使用Burp Suite拦截SQL查询,尝试注入
' OR 1=1 --
等payload - 审查所有数据库操作代码,查找字符串拼接场景
- 使用SQLMap等自动化工具扫描(需配置代理)
- 开启StrictMode检测未处理的异常查询
Q2:Android Keystore系统如何生成数据库加密密钥?
A2:实现步骤:
- 调用KeyGenParameterSpec.Builder设置密钥属性:
KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder("db_key", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build();
- 通过KeyGenerator创建密钥:
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); KeyGenerator generator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); generator.init(spec); SecretKey key = generator.generateKey();
- 使用生成的密钥进行数据库加密