安卓数据存储安全(1)

发布于 2023-01-03  85 次阅读


共享首选项Shared Preferences

在Android开发中,经常需要将少量简单类型数据保存在本地,如:用户设置。这些需要保存的数据可能一两个字符串,像这样的数据一般选择使用SharedPreferences来保存。

一般通过getSharedPreferences()进行信息获取,于此同时一起出现的还会有edit(),putstring()函数

而这种做法会将所有getSharedPreference的字符串都明文存储在安卓机子本身的/data/data/<packagename>/shared_prefs/key.xml文件中,并且所有用户可读

-rw-rw-r--

数据库

数据库SQLite

sqlite数据库通过openOrCreateDatabase 函数进行数据库操作,并且通过execSQL进行sql语句执行

Untitled

将使用提供的数据创建数据库文件并将其存储在文件中。/data/data/<package-name>/databases/privateNotSoSecure

openOrCreateDatabase 的第二个参数决定了sqlite存储的文件是否加密

firebase实时数据库

存储数据并将其与 NoSQL 云托管数据库同步。数据存储为 JSON,并实时同步到每个连接的客户端,即使应用程序脱机,数据也保持可用

可以通过进行以下网络调用来识别配置错误的 Firebase 实例:

https://_firebaseProjectName_.firebaseio.com/.json

或者使用firebase scanner

内部存储

当用户卸载应用时,这些文件也会被删除。并且内部存储由沙箱隔离

以下代码片段会将敏感数据持久存储到内部存储。

Untitled

openFileOutput函数会将文件保存到本地,而不是在容器内部,并且第二个参数可以设置文件的权限。同理也包括FileInputStream

openFileOutput()方法的第二参数用于指定操作模式,有四种模式,分别为: Context.MODE_PRIVATE    =  0

Context.MODE_APPEND    =  32768

Context.MODE_WORLD_READABLE =  1

Context.MODE_WORLD_WRITEABLE =  2

Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可以使用Context.MODE_APPEND

Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。

Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用来控制其他应用是否有权限读写该文件。

MODE_WORLD_READABLE:表示当前文件可以被其他应用读取;MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。

外部存储

存储到外部存储(包括SD)的文件是全局可读的,外部存储主要用于在应用程序之间或与PC共享文件。但是由于内存的不足,往往本应该使用内存的空间却使用了而外部存储

当用户卸载应用程序时,存储在应用程序文件夹 (data/data/) 之外的文件不会被删除

File file = new File (Environment.getExternalFilesDir(), "password.txt");
String password = "SecretPassword";
FileOutputStream fos;
    fos = new FileOutputStream(file);
    fos.write(password.getBytes());
    fos.close();

当一个程序的更新配置文件存放在外部存储时,恶意app可以通过修改外部存储的文件,导致其与原本配置不同而带有“恶意”,那么更新配置文件触发时,就会造成恶意

Man-in-the-Disk: A New Attack Surface for Android Apps - Check Point Software

日志

有两个基本类支持日志记录:log、logger

备份

adb backup

应用开发可以使用两个备份api:key/value backup和auto backup for apps,后者上传到google

测试敏感数据的本地存储(MSTG-STORAGE-1 和 MSTG-STORAGE-2)

静态分析

1. 检查读/写外部存储权限:

androidmanifest.xml uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE”或者是_EXTERNAL_STORAGE作为关键词

2.检查用于存储数据的关键字和 API 调用的源代码:

文件权限MODE_WORLD_WRITABLE会导致其他应用可以读取文件

  • 类和函数,例如:
    • 类(存储键值对)SharedPreferences
    • 类(使用内部或外部存储)FileOutPutStream
    • 功能(使用外部存储)getExternal*
    • 函数(返回用于写入的 SQLiteDatabase )getWritableDatabase
    • 函数(返回一个SQLite数据库进行读取)getReadableDatabase
    • 和函数(使用缓存文件)getCacheDirgetExternalCacheDirs

注意检查本地敏感信息的加密难度

在res/values/strings.xml中或者local.properties 或 gradle.properties

local.properties文件,该文件一般用来存放该Android工程私有的属性配置,比如Android的sdk路径等等。

动态分析

确定 SQLite 数据库是否包含敏感信息/data/data/<package-name>/databases,确定 SQLite 数据库是否已加密;

shared_prefs是否存在敏感信息

确定敏感存储的数据是否已通过 IPC 机制公开 (MSTG-STORAGE-6)

作为IPC机制,内容提供商可以允许应用的数据被其他程序所更改

静态分析

确定人AndroidManifest.xml中的provider标签中的tag android:exported 应该设置为false,以及android:permission的权限

通过工具drozer进行xml的渗透分析

测试敏感数据的备份 (MSTG-STORAGE-8)

文件中是否有以下标志:AndroidManifest.xml

android:allowBackup="true"

可以在代码中搜索是否实现了backupAgent、backupagenthelper

测试敏感数据的内存 (MSTG-STORAGE-10)

静态分析

分析源代码确定应用程序组件,因为直接通过内存转储是很难确定数据泄露的位置的,所以需要提前分析敏感文件的数据位于HTTP?、XML?中

EditText Editable Editable.Factory SpannableStringBuilder StringBuilder StringBuffer 这几个类都是可能存在内存中敏感数据的 ,以及一些第三方api是否存在明文的情况

动态分析

可以通过fridump转储后进行分析

也可以在运行时使用r2frida进行运行时检查内存,android studio内置的转储工具会自动生成,.hprof文件,然后通过MAT进行分析就好

SELECT * FROM java.lang.String

SELECT toString(object) FROM java.lang.String object

SELECT password FROM ".*" WHERE (null != password)


间桐桜のお菓子屋さん