什么是SafetyNet
Android Pay应用程序已于几天前发布。一些使用植根设备的人发现它拒绝工作。这是因为它使用了新的Google Play服务功能:SafetyNet证明。
SafetyNet证明是Google告知应用程序有关设备CTS兼容性状态的意见。CTS通常代表兼容性测试套件,它是设备在发布之前必须通过的一组测试,才能包含Google Play服务。这意味着SafetyNet上下文中的内容有所不同,例如“ 设备当前处于未篡改状态 ”。
篡改状态有多个定义,可以包括“被扎根”,“受到监视”或“被恶意软件感染”。
“兼容CTS” 并不意味着没有漏洞。作为SafetyNet服务的一部分,Google不会检查设备是否是最新的或容易受到公众利用。它会检查与预期的正常和安全状态相比是否已被篡改。
有人可以说这是应用程序开发人员想要的:设备的漏洞状态对最终用户有用,但对开发人员却无济于事。原因是不切实际的:如果某个应用程序拒绝在易受攻击的设备上运行,那么即使在最新的Android设备上,也几乎没有应用程序可以运行。SafetyNet旨在确保应用程序开发人员该设备“可以安全运行”,而不是确保最终用户该设备“安全”-不同的目标群体,不同的目标。
Google显然不想使用繁琐的术语,例如生根或篡改检测,因此它采用了中性的“兼容CTS”。
使用SafetyNet认证
SafetyNet认证是一项新功能,至少对于第三方应用程序开发人员而言。任何应用程序开发人员都可以在其应用程序中使用它。
该过程包括几个步骤:
SafetyNetApi.attest()
。这是由Google Play服务SDK提供的。该请求用于GoogleApiClient
访问Google服务器。JSON Web Signature (JWS)
格式-一种签名的JSON对象。响应包括各种签名和以下内容:"ctsProfileMatch": true|false
ctsProfileMatch
为真),则开发人员可以确定该设备没有被篡改(..与CTS兼容)。有趣的是,响应也可以在开发人员的服务器上进行验证。应用程序可以获取JWS证明响应并将其发送到通常连接的应用程序服务器。然后,该服务器可以直接要求Google验证JWS签名(或自己做),然后继续对服务器端的结果采取行动,例如拒绝对客户端的API访问。
这是一个好的设计:安全性决定发生在服务器上,而不是客户端上。即使客户端被操纵,服务器也将拒绝提供服务。据我所知,在AndroidPay中,几乎每个wallet&pay API都将证明结果用作参数。话虽如此,这并不意味着证明系统不能被欺骗-恶意环境可能将篡改的数据提供给收集器。而且,这并不意味着证明的结果总是新鲜的。。但是总比没有好。
开发人员可以在这里找到有关使用此功能的说明:https : //developer.android.com/training/safetynet/index.html
但是,这一切如何运作?
SafetyNet
是Google用来从10亿台启用Play的Android设备上收集与安全相关的信息的数据收集系统。
这个想法是,Google Play服务(设备上的封闭源程序包)会启动名为的始终运行的服务snet
。此服务经常从设备收集各种数据,然后将其发送回Google。
Google将此信息用于多种目的,例如生态系统分析和设备威胁分析。
事实证明,根据收集到的信息,Google可以确定设备是否受到多种方式的篡改。Google会维护此信息,并会随时知道特定设备是否处于可疑状态。
证明是如何将此信息公开给第三方开发人员。当应用程序执行证明请求时,Google会根据对先前从设备中收集的信息的分析,将包含其有关“ CTS兼容性”的决定的已签名响应发送回去。
收集到的数据的实际分析是在服务器端完成的,从而留出了更少的操作空间;再次做好安全设计。
当然,了解收集哪些数据可能意味着某人最终可以开发出一个不断提供snet
“非恶意”信息的挂钩系统。
但是,这并不简单:
snet
是非常灵活的,如下面所讨论。当第三方应用程序想要发出证明请求时,它将调用com.google.android.gms.safetynet.SafetyNetApi;->attest(mGoogleApiClient, nonce)
,该应用程序中包含的Play Services SDK的证明方法。该库与com.google.android.gms.safetynet.internal.ISafetyNetService
通过Binder在设备上运行的服务进行交易。
的SafetyNetService
是谷歌游戏服务之一。服务处理代码打包在Google认可的Android设备随附的Google Play服务软件包中,并通过Play商店进行更新。
但是,更深入地揭示一个非常有趣的技巧:
的实际实现snet
不在任何APK中。
SafetyNet服务与Google服务器联系,并下载包含代码的二进制程序包。验证软件包的完整性非常费力,例如使用硬编码的证书(固定)。该二进制程序包实质上是一个JAR文件,其中包含classes.dex
具有Java字节码的文件。Play Services将其缓存在dalvik-cache
(snet.dex
)中,并使用反射动态加载。
这对Google来说非常方便:即使不通过Google Play推送应用,也可以非常轻松地更新收集方法的实际实现。
这是该软件包的两个版本:https : //www.gstatic.com/android/snet/12042014-1626247.snet https://www.gstatic.com/android/snet/07172015-2097462.snet
这些文件不会以任何方式混淆(即使使用ProGuard也不会)-尽管使用了Google Play软件包。与Android安全团队的成员交谈之后,看来这是有意为之的:他们想要一个实现,而不是易于审查的实现。我的猜测是,他们希望确保人们知道自己没有收集与敏感/隐私相关的信息。混淆可能会引起怀疑。
从打包日期可以看出,该系统的某些部分根本不是新的-SafetyNet至少从2014年12月开始存在,但是在最新版本中已得到了很大增强。
该JAR文件包含com.google.android.snet.Snet
该类的实现。该enterSnet
方法是有趣的开始-这就是游戏服务调用通过反射。
Google会在更多情况下下载与安全相关的代码。例如,Android设备还下载了一个名为本机的共享库droidguard
并运行它,但让我们将其留给另一篇文章。
该系统非常模块化:snet
可以由Play Services使用配置文件来启动,该配置文件定义将使用哪些收集模块。默认情况下,并非所有功能都启用。
让我们更详细地了解这些模块的每个功能:
default_packages
这将为某些操作创建首选软件包的列表,并报告哪些软件包用于Web浏览和软件包安装。它专门检查首选的Web浏览器是否为 com.android.browser
或com.android.chrome
。 我可以假设这样做是为了检测用户授权使用非标准浏览器(可能是恶意软件)的情况-Google可以在其后端维护一个列表。
su_files
报告回来,如果这些文件/system/bin/su
或/system/xbin/su
存在。如果这样做,则表明存在篡改迹象。
我确实希望证明结果不仅仅基于此检查-尽管有证据表明它发挥了重要作用。在未感染的,仅已植根的设备上,将这些文件移动到其他位置似乎会产生积极的证明结果。通过“禁用SuperSU”之类的操作也可以达到相同的结果。也许Google格外谨慎。
settings
从android.provider.Settings$Secure
或android.provider.Settings$Global
取决于操作系统版本收集各种与安全性相关的字段。收集的设置包括的像变量的值adb_enabled
,install_non_market_apps
,isKeyguardSecure()
,getNotificationVisibility()
,lock_screen_lock_after_timeout
,lockscreen.password_type
,lock_pattern_autolock
。 显然,所有这些都表明该设备可能“令人感兴趣”。
locale
向后报告设备的当前语言环境配置。 我认为这样做是为了使他们可以根据地区风险对用户进行配置,并根据需要调整其阈值。
ssl_redirect
这是一个有趣的模块。它尝试确定设备是否正确遵循SSL重定向。它收集诸如活动连接的类型,使用中的DNS服务器以及可用连接之类的信息。
然后,它创建到以下主机的请求:http://accounts.google.com
,http://www.google.com
,http://pubads.g.doubleclick.net
-使用随机用户代理,甚至模仿一个iPhone,具有“后续重定向”禁用。所有这些主机都重定向到站点的HTTPS版本,并且模块从重定向响应中收集Location HTTP标头。然后,它将再次执行相同的请求,这次是在重定向之后。重定向之后,将报告最终端点主机的IP和主机名。第二个请求甚至是使用ApacheHTTPclient
类或HttpURLConnection
(!)随机完成的
有人要求提供有关该doubleclick.net
域的更多信息。这是一个用于向应用程序投放广告的域,该服务归Google所有。我只能假设这也是尝试检测是否安装了广告拦截器。
ssl_handshake
这个另一个非常有趣的模块。它试图确定是否可以通过多种方式来拦截通信,例如通过安装SSL-Kill-Switch应用程序。
该代码试图联系三台主机:accounts.google.com
,www.google.com
,pubads.g.doubleclick.net
对于每个主机,遵循以下算法,并捕获每个步骤的所有结果以及任何可能的错误。
TrustAllX509TrustManager
。TrustManager
都将不使用信任锚进行初始化,并且该checkServerTrusted()
方法将在检索到的证书链上执行。通常,这会引发异常,但是在大多数SSL Kill Switch实现中,它不会。该代码验证是否抛出异常(严格检查)DefaultHostnameVerifier
用于验证所述连接的主机名MD5withRSA
算法和公钥短于2048位。/system/etc/security/cacerts
)或是否已被用户添加(/data/misc/keychain/cacerts-added
)完成所有这些检查之后,所有有关连接是否成功,如果通过了链验证和信任检查都将收到的证书的信息将发送回Google。
mx_record
对于设备上设置的每个DNS服务器,将gmail.com
解析主机名并收集MX服务器以及完整的DNS响应。 我认为这是为了检测设备是否配置为使攻击者可以拦截电子邮件。
sslv3_fallback
使用通过和https://www.google.com
发起的SSL套接字进行连接。它收集套接字是否已连接以及主机名验证是否通过。如果没有通过连接,则使用而不是上面提到的现代TLS功能重试连接。该模块收集所有产生的工件和错误消息。 该模块显然旨在检测与网络相关的攻击,例如SSL降级。TLS
SNI extensions
SessionTicket
SSLv3
proxy
收集是否在设备上配置了代理,它们的IP地址是什么以及这些IP是否是设备的本地IP。 这会尝试确定设备上是否存在侦听流量的恶意软件(某些恶意软件-和广告拦截器-使用代理工作)或是否将通信发送到外部已知错误的位置。
selinux_status
收集设备上是否提供SELinux支持(如果/sys/fs/selinux/enforce
存在),以及是否处于强制模式(通过读取该文件的内容) 如果在较新的Android版本上SELinux处于非强制模式,则表明存在可疑现象正在进行。
sd_card_test
尝试了解SD卡是否已被篡改。这将gmsnet2.jpg
在SD卡上创建一个JPEG文件,并在其中填充一些硬编码的内容。然后,IT部门将分析文件的长度是否与硬编码值匹配,并逐字节验证写入的字节是否与发送的字节匹配。 我不确定我是否理解此检查的原因以及在与安全相关的条件下它将失败的原因。
google_page_info
尝试确定HTML代码的长度是否www.google.com
超过某个预先配置的阈值。 我假设这试图确定用户看到的页面上是否发生某种形式的javascript注入。
captive_portal_test
收集的IP地址clients3.google.com
。然后,它使用随机用户代理连接http://clients3.google.com/generate_204
并捕获响应的返回码和正文长度。 这将尝试确定设备是否使用重定向响应的强制门户。强制门户可以用作执行MitM攻击的方法。
logcat
运行logcat -d
命令并查找一组可配置的“有趣的字符串”。 Google可以将所有日志上传到他们的服务器并在其中进行搜索,但是我猜想它采取了这种方法,从而避免了意外泄露用户私人信息。默认情况下,“有趣的字符串”的集合为空,因此我无法确定它们在寻找什么。
event_log
与logcat检查类似,但用于EventLog
事件。跳过带有do-not-log-
标签前缀的事件。
apps
首先检查设备上是否存在Google帐户。然后,根据Google Play提供的配置开关,它可以收集和报告有关所有非系统应用程序或所有系统应用程序的信息。 默认情况下,此模块未启用。在应用程序测试期间,我们将此类行为标记为隐私问题。但是我想Google已经知道您已经安装了哪些应用程序,因为您最有可能使用Google Play进行了安装,因此泄漏可能不多。我可以理解,为什么Google会对查看设备上还安装了哪些其他应用感兴趣。
google_page
http://www.google.com
使用随机用户代理检索页面并存储收到的HTML代码。
suspicious_google_page
这与google_page
测试相同,但首先使用ssl_handshake
和ssl_redirect
测试的结果,以尝试确定的连接是否安全www.google.com
。如果不是,则不会保存任何结果。 这会将检索到的HTML代码发送回Google。我猜他们试图了解某些恶意软件是否在本地拦截流量并将内容注入HTML。
gmscore
收集有关com.google.android.gms
设备上的应用程序的信息。这是Google移动服务应用程序,也称为Play服务。收集的信息包括APK和包签名的完整路径。 Google在这里尝试查看是否有某种东西(例如恶意软件)试图静态篡改播放服务。
attest
进行证明请求并收集AttestationInfo
响应。 知道在计算较新的响应时要考虑多少过去的认证结果会很有趣。
device_admin_deactivator
检索设备的活动设备管理员(如果有)。将它们与名为的文件的内容进行检查device_admin_blacklist.txt
。它包含在下载的snet.jar
文件中,包含70多个条目,如下所示:
com.android.vendlng,66fd5cb0,f84d0d9f
org.helpzek.minecraft,1cf1e47b
google.android.xmppm,e39125e5,40c7d1e7
org.zl.zlorg,d2a16633,38d1153c
com.devguru.minecraft,9746f466
com.adobe.flplayer,1c0ec8e1,98837829,08dadccb,b094083a,81565420,76a05ce0,e5f7325e
com.android.pfx12,dc61b3d0
com.cryengine.gplay,61996cf8
com.wikihelp.minecraftwikiversion,2379f1d0
com.xsys.cfgs,749a7f99,3c0a9c89
com.cheatgroup.app,d2ef0ea4
这是一个HashMap,其中的键是程序包名称,值是完整路径名的sha256哈希的前缀。
如果在正确的APK路径上发现任何列入黑名单的应用是活跃的设备管理员,则将removeActiveAdmin()
其调用以删除该管理员,并使用停止该软件包forceStopPackage()
。收集设备管理软件包的应用程序信息。
显然,这超出了收集范围,实际上尝试使用黑名单方法保护设备免受危险应用的侵害。
system_partition_files
收集有关在下感兴趣的文件的可配置列表的各种信息/system
。信息包括所有许可权,文件名,symlink目标,selinux安全上下文,哈希等。当前感兴趣的文件列表似乎为空。有趣的是,该框架利用红色鲱鱼来使攻击者感到困惑:连同感兴趣的文件,可以以相同的方式访问可配置数量的随机文件。 好东西,红鲱鱼方法通常用于高级应用程序保护产品中。但是,默认情况下未启用此功能。
system_ca_cert_store
该模块包含证书的sha256哈希散列的可配置列表。此检查查看试图查找的内容(/system/etc/security/cacerts
或/system/etc/security/cacerts.bks
ICS之前的内容),如果找到,则将其返回,或者是完整证书,也可以是主题名称,发行者名称和签名信息(可再次配置)。 这试图通过查找列入黑名单的证书来了解流量是否被拦截。有一种恶意软件会将恶意证书丢弃在证书存储中,从而允许SSL流量在网络层被拦截。
setuid_files
如您所料,此检查将收集有关setuid
文件系统中存在的文件的信息。它采用libcore.io.StructStat
与libcore.io.OsConstants
,libcore.io.OS
,libcore.io.Libcore
和相关类检索信息。 setuid可执行文件的存在在较新的Android版本中是一个明显的危险信号。
####隐私问题一些人评论说,此博客文章中应单独解决隐私问题。这里有几点:
这就是说,我了解有些人会发现SafetyNet的侵入性-每个人对于构成私人/敏感信息的观点都不同。
还必须说,似乎没有退出系统。一旦第三方应用程序开始采用SafetyNet认证,那将产生有趣的含义。
原文地址: https://koz.io/inside-safetynet/