实现认证器应用时,遵循下列规则:
前提是,提供认证器的服务由账户管理器使用,并且不应该被其他应用访问。 因此,通过使其成为私有服务,它可以避免其他应用的访问。 此外,账户管理器以系统权限运行,所以即使是私有服务,账户管理器也可以访问。
用于添加新帐户并获取认证令牌的登录界面,应由认证应用实现。 自己的登录界面不应该在用户应用一端准备。 正如本文开头提到的,【账户管理器的优势在于,极其敏感的信息/密码不一定要由应用处理】,如果在用户应用一端准备登录界面,则密码由用户应用处理, 其设计越过了账户管理器的策略。
通过由身份验证器应用准备登录界面,操作登录界面的人仅限于设备用户。 这意味着,恶意应用无法通过尝试直接登录,或创建帐户来攻击帐户。
登录界面活动是由用户应用加载的系统。 为了即使在用户应用和身份验证器应用的签名密钥不同时,也能展示登录界面,登录界面活动应该实现为公共活动。 登录界面活动是公共活动,意味着有可能会被恶意应用启动。 永远不要相信任何输入数据。 因此,有必要采取“3.2 小心并安全处理输入数据”中提到的对策。
KEY_INTENT
,带有登录界面活动的指定类名称(必需)当认证器需要打开登录界面活动时,启动登录界面活动的意图,会在返回给账户管理器的 Bundle 中,由KEY_INTENT
提供。 所提供的意图应该是指定登录界面活动的类名的显式意图。 在使用隐示意图,它指定动作名称的情况下,有可能并不启动由认证器应用本身准备的登录界面活动,而是其他应用准备的活动。 当恶意应用准备了和常规一样的登录界面时,用户可能会在伪造的登录界面中输入密码。
访问在线服务的应用有时会遇到麻烦,例如无法成功访问在线服务。 访问失败的原因各不相同,如网络环境管理不善,通信协议实现失败,权限不足,认证错误等。一个常见的实现方式是,程序输出详细信息给日志,以便开发人员可以稍后分析问题的原因。
敏感信息(如密码或认证令牌)不应输出到日志中。 日志信息可以从其他应用读取,因此可能成为信息泄露的原因。 此外,如果帐户名称的泄漏可能导致损失,则不应将帐户名称输出到日志中。
两个认证信息,密码和认证令牌可以保存在一个账户中,来注册账户管理器。 这些信息将以明文形式(即不加密)存储在以下目录下的accounts.db
中。
/data/system/accounts.db
/data/system/0/accounts.db or /data/system/<UserId>/accounts.db
要阅读accounts.db
的内容,需要 root 权限或系统权限,并且无法从市场上的 Android 设备中读取它。 在 Android 操作系统中存在漏洞的情况下,攻击者可以获得 root 权限或系统权限,保存在accounts.db
中的认证信息将处在风险边缘。
本文中介绍的认证应用旨在将认证令牌保存在账户管理器中,而不保存用户密码。 在一定时间内连续访问在线服务时,通常认证令牌的有效期限会延长,因此在大多数情况下,不保存密码的设计就足够了。
通常,认证令牌的有效期限比密码短,并且它的特点是可以随时禁用。 如果认证令牌泄漏,则可以将其禁用,因此与密码相比,认证令牌比较安全。 在认证令牌被禁用的情况下,用户可以再次输入密码以获得新的认证令牌。
如果在密码泄漏时禁用密码,用户将无法再使用在线服务。 在这种情况下,它需要呼叫中心支持等,这将花费巨大的成本。 因此,最好从设计中避免在账户管理器中保存密码。 在不能避免保存密码的设计的情况下,应该采取高级别的逆向工程对策,如加密密码和混淆加密密钥。
密码或认证令牌就是所谓的认证信息,如果被第三方接管,第三方可以伪装成有效用户。 由于认证器使用在线服务来发送/接收这些类型的认证信息,因此应使用可靠的加密通信方法,如 HTTPS。
如果有多个认证器在设备中定义了相同的帐户类型,则先前安装的认证器将生效。 所以,安装自己的认证器之后,它不会被使用。
如果之前安装的认证器是恶意软件的伪装,则用户输入的帐户信息可能被恶意软件接管。 在执行帐户操作之前,用户应用应验证执行帐户操作的帐户类型,不管是否分配了常规认证器。
可以通过检查认证器的包的证书散列值,是否匹配预先确认的有效证书散列值,来验证分配给账户类型的认证器是否是正常的。 如果发现证书哈希值不匹配,则最好提示用户卸载程序包,它包含分配给该帐户类型的意外的认证验证器。