也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大
少走了弯路,也就错过了风景,无论如何,感谢经历
0x01 剪贴板敏感信息泄露
在 Android 中,由于 Android 操作系统的规范或 Android 操作系统提供的功能,应用程序实现难以保证安全。如果这些功能被恶意第三方滥用或被用户随意使用,就有导致信息泄露等安全问题的风险
复制和粘贴是用户经常随意使用的功能。例如,许多用户使用这些功能将邮件或网页中需要记住的奇怪信息或重要信息存储在记事本中,或者从存储密码以防忘记的记事本中复制或粘贴密码。这些操作看起来非常非常正常,但实际上可能存在用户处理信息被盗的潜在风险
此风险与 Android 系统中的复制和粘贴机制有关。用户或应用程序复制的信息会存储在名为剪贴板的缓冲区中。当用户或应用程序粘贴时,剪贴板中存储的信息将分发到其他应用程序。因此,此剪贴板功能存在导致信息泄露的风险。这是因为剪贴板实体在系统中仅有一个,任何应用程序都可以使用 ClipboardManager 随时获取剪贴板中存储的信息。这意味着用户复制/剪切的所有信息都有可能泄露给恶意应用程序
在文本框中经常会使用到复制粘贴的功能,这个时候数据是保存在剪切板中的。而剪切板是安卓系统提供的功能,所有的应用都可以访问,并且无需特殊权限申请。如果在剪切板中存储了敏感信息,就存在泄漏的风险。比如以下的应用通过监控剪切板内容,成功获取了身份证号码
在Android 4.0 中底层引入了TextLayoutCache,当每个测量过的文字都被添加到缓存中,下次需要相同的文字时,可以从缓存中获取,不用在测量。
打开预测文本的Android 设备会自动记录用户输入的记录缓存。Android 预测文本功能,将通过记住用户之前输入的单词作为未来输入建议的一部分,使键盘上的输入更容易,如下所示。但是,一旦单词已经写入,则禁用预测文本并在将来启用它。被记住的消息还在
如果您不使用Android键盘,则这些步骤可能会有所不同。不同手机版本开启预测文本的步骤也是不太相同的
演示如下:
代码如下:
package com.example.testpoc4;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取控件id
Button button = findViewById(R.id.button);
// 监听点击事件
button.setOnClickListener(new View.OnClickListener() {
@Override// 获取剪贴板内容并在打印出来
public void onClick(View v) {
ClipboardManager cm = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData data = cm.getPrimaryClip();
ClipData.Item item = data.getItemAt(0);
String content = item.getText().toString();
Toast.makeText(MainActivity.this,content,Toast.LENGTH_SHORT).show();
}
});
}
}
缓解措施
可以采用以下方法来禁用剪切板相关功能:
- 通过禁用长按视图也可禁止复制/剪切,可在 xml 布局文件中指定禁用长按视图在 EditText 中加入属性 android:longClickable=“false”
如果视图在应用程序中显示敏感信息,并且允许在视图(例如 EditText)中复制/剪切信息,则信息可能通过剪贴板泄露。因此,必须在显示敏感信息的视图中禁用复制/剪切
- 重写 EditText 的回调方法,从 EditText 字符串选择的菜单中删除复制/剪切项目(从字符串选择菜单中删除 android.R.id.copy和android.R.id.cut)
通过 TextView.setCustomSelectionActionMODECallback() 方法,可以自定义选择字符串时的菜单。通过使用此功能,如果在选择字符串时可以从菜单中删除复制/剪切项目,用户将无法再复制/剪切字符串。
0x02 检查键盘缓存是否存在敏感信息泄露
当用户在输入信息时,一般情况下软件默认会自动保存数据,这个特性功能对于消息传递类的应用程序非常有用。但是,当用户选择此类应用程序的输入框来输入信息时,键盘缓存就可能暴露敏感信息给攻击者收集用户个人信息的提供了途径
大部分中文应用弹出的默认键盘是简体中文输入法键盘,在输入用户名和密码的时候,如果使用简体中文输入法键盘,输入英文字符和数字字符的用户名和密码时,会自动启动系统输入法自动更正提示,然后用户的输入记录会被缓存下来
系统键盘缓存最方便拿到的就是利用系统输入法自动更正的字符串输入记录。 缓存文件的地址应该是下面的这个路径:
导出该缓存文件,查看内容,一切输入记录都是明文存储的。因为系统不会把所有的用户输入记录都当作密码等敏感信息来处理。 一般情况下,一个常规用户高频率出现的字符串就是用户名和密码
所以,一般银行客户端app输入密码时都不使用系统键盘,而使用自己定制的键盘,主要原因如下:
- 避免第三方读取系统键盘缓存
- 防止屏幕录制 (自己定制的键盘按键不加按下效果)
在一个activity的布局定义中,可以定义有XML属性的TextViews。如果XML属性android:inputType
给了值textNoSuggestions
,可以将文本框的输入类型设置为android:inputType="textNoSuggestions"
此时就不会再显示键盘缓存建议。用户就必须手工输入内容,不会再自动有缓存信息,下面一个是有源码的情况下的静态查看方式和没有源码的情况下的查看是否禁用键盘缓存
<EditText
android:id="@+id/passwordText"
android:inputType="textNoSuggestions" />
无源码的情况下,反编译APK并查看\res\layout 路径下的xml文件是否有配置android:inputType="textNoSuggestions"
然后打开APP运行,输入相关之前输入过的内容,看看是否会自动提示补齐输入的信息
注:并不是说文本框不设置android:inputType="textNoSuggestions"
就是有问题的,而是该文本框是否在使用过程中有输入敏感信息。如果有,则就有可能被攻击者窃取这些敏感信息,所以该EditText就需要配置android:inputType="textNoSuggestions"
- 缓解措施
在文本框输入的内容,有时候会被输入法缓存,以提升用户体验。但是在涉及到敏感信息输入框的时候,就可能会造成信息泄漏。可以指定 android:inputType 为 textNoSuggestions 来缓解该风险,如下:
注:上述涉及到的风险点通常需要根据应用的类型进行判断,例如如银行类 APP可能需要规避本文中的风险,而工具类 APP 则无需考虑大部分本文的风险点
0x03 UI界面敏感数据泄露
大多数APK应用程序会建议用户输入一些敏感数据,比如在注册新账号或付款时输入的敏感信息以明文显示数据,没有用*
(型号)或圆点代替输入的来屏蔽敏感数据,则可能导致敏感数据泄露
如何检测此类敏感信息泄露?只需要我们在检查设备上所有显示此类信息或将其作为输入的 UI 组件,并搜索敏感信息的任何痕迹并根据自身经验来来评估确认是否需要将其屏蔽或完全删除
3.1 静态分析
- 文本字段
反编译APK并查看AndroidManifest.xml,检查文件中 EditText 的定义是否有以下属性(因为配置该设置,文本框中的文字将显示点(而不是输入字符)将显示在文本字段,防止应用程序泄漏密码或 PIN (例如锁住手机时,要求输入密码)到用户界面):
android:inputType="textPassword"
- 程序通知
UI界面这里的程序通知导致的敏感信息泄露【静态分析】,跟第三方导致的敏感数据静态分析操作差不多,自行翻看对应的内容查看
3.2 动态分析
动态运行APK应用程序并识别显示此类信息或将其作为输入的组件,来判断APK应用程序是否向UI界面泄露敏感信息
- 文本字段
如果用户输入的信息被屏蔽,例如:用星号或圆点代替输入的信息,则APK应用程序不会将数据泄漏到用户界面
- 程序通知
UI界面这里的程序通知导致的敏感信息泄露【动态分析】,跟第三方导致的敏感数据静态分析操作差不多,自行翻看对应的内容查看
0x04 自动截屏泄露敏感信息
Android 系统厂商或制造商,在设计系统时为了考虑用户体验性,通常会在应用程序启动和退出时为设备用户提供美观的体验考虑,此特性就使用了屏幕截图保存功能,以便在应用程序当前状态是在后台的使用。可能使用该功能会存在安全风险,比如用户在显示敏感信息时故意对应用程序进行截屏,如果敏感信息没有做星号/圆点处理,那么就存在被其它恶意APK应用程序持续捕获屏幕截屏内容的导致敏感信息泄露,需要注意屏幕截图是存储在本地的,就有可能存在被窃取的可可能性
正题开始之前,我们先说一下就算我们在 EditText 标签中指定android:inputType
为 textPassword
,来让密码进行掩码显示并不能抵御截屏获取敏感信息。在 Android 5.0之前,要实现截屏需要有 root 权限,但Android 5.0 之后,Google 开放了录屏 API,无需 root 权限就能够截屏了。比如说以下图片中依然可以看到输入的密码明文,只是输入后变成了掩码,但只要能录屏,一样存在风险,如下图:
可以在承载的 Activity 中,加入以下代码来防止截屏获取敏感信息,如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE);
setContentView(R.layout.activity_sp);
etUsername = findViewById(R.id.et_sp_username);
etPassword = findViewById(R.id.et_sp_password);
}
为了验证效果,我们做以下实验来验证:
- 在以下界面(未做防护),执行命令
adb shell screencap -p /sdcard/1.png
进行截屏。
adb shell screencap -p /sdcard/1.png
- 在以下界面(做了防护),执行命令
adb shell screencap -p /sdcard/2.png
进行截屏
adb shell screencap -p /sdcard/2.png
看一下截图文件,发现 1.png 大小正常而 2.png 大小为 0 字节,说明成功阻止了屏幕截图的攻击,如下图:
4.1 静态分析
在APK应用程序进入后台时Android设备会自动截取当前活动的屏幕截图(这一点大家经常使用手机的人,应该都晓得),当我们再次返回APK应用程序前台时,为了好看,会在一个轮播图中显示出来,此设计特性就存在可能泄露没有做过处理的文本框导致的敏感信息泄露
检查是否可以使用应用切换器暴露敏感信息,只需查看有么有设置FLAG_SECURE选项,如果未配置该选项,则该APK应用程序容易被恶意APK应用程序持续屏幕捕获,如下代码示例:
Java 中的示例:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE);
setContentView(R.layout.activity_main);
Kotlin 中的示例:
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE)
setContentView(R.layout.activity_main)
4.2 动态分析
打开应用程序进入到后台导航切换栏,可以切换到任何含有敏感信息的屏幕,查看快照。如果FLAG_SECURE设置了,则快照为空;如果未设置标志将显示活动信息。如下(点击按钮,切换到后台界面,只要查看是否出现快照能显示截图的内容):
解决方案:
- 在支持基于文件的加密 (FBE)的设备上,快照存储在
/data/system_ce/<USER_ID>/<IMAGE_FOLDER_NAME>
文件夹中。<IMAGE_FOLDER_NAME>
取决于供应商,但最常见的名称是snapshots和recent_images。如果设备不支持 FBE,/data/system/<IMAGE_FOLDER_NAME>
则使用该文件夹。需要注意访问这些文件夹和快照需要root权限哦
上面有些内容细节,可以前往:[车联网安全自学篇] 三十七. Android安全之数据存储与数据安全「详解」
参考链接:
https://android-developers.googleblog.com/2017/09/keystore-key-attestation.html
https://github.com/OWASP/owasp-mstg/blob/master/Document/0x05d-Testing-Data-Storage.md
https://mp.weixin.qq.com/s/j5BIcOAeXyNG8MsAHIsKzw
https://wizardforcel.gitbooks.io/android-app-sec-guidebook/content/4.10.html
https://github.com/JinxKing/android_app_security_checklist
你以为你有很多路可以选择,其实你只有一条路可以走