【译】Inside SafetyNet - part 3

自从我上一篇关于Android的SafetyNet的博客文章以来,已经过去了8个月。在那篇文章中,我描述了该系统的2015年末版本(版本代码2495818)。如预期的那样,此后进行了几次更新。我认为我应该在本系列中再写一篇,可能是最后一篇。我将简要介绍该版本与上一版的区别10000700;这是倒数第二个版本。我看到的最新版本是10000801,但是功能上没有很多差异。

有关SafetyNet系统内部客户端检查及其用法的更完整概述,请通读我以前的文章。

SNET版本代码

我以为我只列出我在野外观察到的一些SNET版本;我敢肯定还有更多。

  • 1626247 (2014年12月)
  • 1839652 (2015年4月)
  • 2097462 (2015年7月)
  • 2296032 (2015年9月)
  • 2495818 (2015年12月)
  • 10000700 (2016年8月)
  • 10000801 (2016年9月)

设计变更

SafetyNet已Chimera作为炸药模块部分集成到系统中。Chimera是用于Google Play服务组件的一种软件包管理系统,可让Google灵活且独立地升级每个组件。由于Chimera管理着下载和配置过程的一部分,因此此更改使snet软件包更轻便,更灵活。Chimera还有一个不错的界面,可以通过进入Google设置并启用“调试项”来找到。您将看到一个名为“ Chimera Modules”的“ [internal]”菜单项。SafetyNet模块称为com.google.android.gms.flags当前版本1。您还将发现这DroidGuard是另一个炸药模块。

Chimera模块列表

basicIntegrity

 

 

Discovered new element "basicIntegrity: true/false" in Android's SafetyNet Attestation. Need to investigate what this indicates. #android

 
 
 
 

 

至少自去年7月以来,证明响应对象包含一个名为的新布尔标志basicIntegrity。此新字段尚未出现在Google的已发布文档中。我敢肯定会很快。

{
    "nonce": "R2Rra24fVm5xa2Mg",
    "timestampMs": 9860437986543,
    "apkPackageName": "com.package.name.of.requesting.app",
    "apkCertificateDigestSha256": ["base64 encoded, SHA-256 hash of the certificate used to sign requesting app"],
    "apkDigestSha256": "base64 encoded, SHA-256 hash of the app's APK",
    "ctsProfileMatch": true,
    "basicIntegrity": true,
}

但是这个领域是什么?以下是我的一些想法:

2016年9月,Google决定将更具侵略性的检查方式引入ctsProfileMatch,例如,采取已验证的启动状态。由于这些更改,未“植根”但只能使用其他引导程序的设备将ctsProfileMatch被设置为false

在这种情况下,basicIntegrity仍将保留true。似乎只有将su二进制文件放在预期的位置时,才将其设置为false 。basicIntegrity当前该字段的行为似乎ctsProfileMatch与最近更改之前的行为相同。可以将其视为维持先前ctsProfileMatch行为的一种方法,以便第三方应用程序可以选择他们希望基于其决策的检查级别。我还没有看到任何情况下basicIntegrity为真而ctsProfileMatch为假;如果您愿意,请在评论中让我知道。

我还在Google Play中更新了Cigital的SafetyNet Playground应用程序。现在,它检查并报告的值basicIntegrity。一探究竟!

SafetyNet游乐场

DroidGuard

可以肯定地说,DroidGuard在证明中的作用比我以前描述的要大。它是(并且一直以来都是)打包的本机库,旨在某种程度上承受逆向工程,这使得处理它更加有趣。关于此的另一篇博客文章可能会在将来出现。

安全浏览

SafetyNet-从第三方应用程序的角度看,最初只是关于证明和CTS兼容性。

现在,它提供了另一种形式:一种lookupUri()API,允许应用程序检查给定URI是否被Google的威胁情报系统分类为“潜在有害应用程序”。此处此处对此有更多详细信息。

我尚未在我的任何博客文章中描述安全浏览,将来可能会出现-就像Verify Apps&DroidGuard。

缩小

从版本开始,10000801SafetyNet正在使用ProGuard样式的缩小(有些人称其为混淆)。这是一个有趣的改变。最初,Google似乎是故意为了使透明度更加清晰而保留一些东西,但是这种情况似乎已经改变。

重要的是要注意,这种变化是在最近的设备完整性变化之后,SafetyNet与各种“旁路”之间的猫捉老鼠游戏同时发生的。我确信,像这样的 SafetyNet重新实施可能会影响此决定。

SafetyNet模块更改

在最新版本中添加了一些但重要的新模块,并对一些较旧的模块进行了重组。如上所述,SafetyNet是由Google在运行时或通过播放服务更新配置的;snet模块本身较少独立地更新。

以下是默认情况下当前启用的snet模块列表。请注意,与一年前相比,已经启用了一些额外的模块。但是,真正的区别当然不在这里。真正的区别在于每个模块的数据影响后端证明决策的方式。

空闲模式模块

空闲模式检查似乎每12小时运行一次。上次空闲模式扫描运行存储在Play Services应用私有文件内snet的共享首选项中。现在,默认情况下,以下模块始终在空闲模式下启用。

  • gmscore
  • system_partition_files
  • system_ca_cert_store
  • setuid_files
  • dalvik_cache_monitor
  • device_state
  • 地区
  • selinux_status
  • 日志猫
  • 事件记录日志

gmscorelocaleselinux_status现在模块已接通comared到去年同期水平。该gmscore模块com.google.android.gms通过PackageManager API 检索有关安装在设备上的软件包的信息,包括versionCode,哈希,签名等。该locale模块显然会检索当前语言环境,包括国家/地区代码。selinux_status稍后将描述这些模块。

普通模式模块

现在,默认情况下,以下模块始终在正常模式下启用。当第三方应用程序要求证明或每24小时最多进行一次认证时,普通模式“检查”似乎会运行。

  • default_packages
  • su_files
  • 设定
  • 地区
  • ssl_redirect
  • ssl_handshake
  • 代理
  • selinux_status
  • sd_card_test
  • google_page_info
  • captive_portal_test
  • 证明
  • gmscore
  • device_state
  • carrier_info
  • 日志猫
  • 事件记录日志

播放服务配置当前还启用了以下非默认模块:

  • mx_record
  • sslv3_fallback

与一年前相比,唯一的区别似乎是现在打开了以下两个模块:device_statecarrier_info。该device_state模块当然非常重要,并且与最近验证的启动块直接相关。下文将对其进行详细说明。

SU文件模块

自从首次发现以来,SU查找模块已进行了部分重新设计。它报告有关两套文件的信息:

  • Google明确要求的文件
  • 是二进制文件

第一类文件来自snet配置选项,它们作为Google Play服务的一部分与snet本身分开提供。目前,它仅包含一个文件:/proc/sunxi_debug/sunxi_debug。该文件是众所周知的内核后门,允许在某些设备上轻松进行root身份访问。

第二类已划分为新的生根文件查找器子模块。其工作原理如下:

  1. SNET组合了两种类型的目录的组合列表以进行搜索:

    • 有趣的目录:默认情况下,这些目录包括/system/bin/system/xbin和在中指定的所有目录PATH(如果存在这样的环境变量)。

    • systemless根目录:SNET尝试识别的目录可能是绑定挂载的通过解析/proc/self/mountinfo和如果找出/bin或者/xbin经由使用被安装/dev/block/loop。在本文中,我不会详细介绍无系统root的工作方式。

  2. SNET尝试查找su这些目录中是否存在二进制文件。如果是的话,它会收集有关它的信息,包括SHA256哈希,它是否是符号链接及其目标,所有权/权限/ selinux信息(lstat)等。现在它还会检查文件是否可执行-通过来完成java.libcore.io.Os.access(file, X_OK)

设置模块

该模块用于检索有关系统设置的各种信息,并作为“正常模式”检查的一部分运行。它已更改为还检索另外两个信息:

  • 存储加密状态

    如果SDK> = 11,则通过系统服务的getStorageEncryptionStatus()方法进行检索device_policy

  • 指纹状态

    如果SDK> = 23 ,则通过系统服务的isHardwareDetected()hasEnrolledFingerprints()方法检索此信息fingerprint。它可以返回以下值:

    • FINGERPRINT_ENROLLED = 1
    • FINGERPRINT_NOT_SUPPORTED = 0
    • FINGERPRINT_UNENROLLED = 2

设备状态模块

该模块用于收集以下数据:

  • 通过验证启动状态 ro.boot.verifiedbootstate
  • 验证模式通过 ro.boot.veritymode
  • 通过的安全补丁程序级别 ro.build.version.security_patch
  • 通过解锁支持 ro.oem_unlock_supported
  • 闪光锁的状态(oemLocked):通过 ro.boot.flash.locked

现在添加了以下内容:

  • 设备品牌通过 ro.product.brand
  • 设备型号通过 ro.product.model
  • 的内核版本 /proc/version
  • Google通过播放服务明确指定的系统属性列表。
    • 目前只是 ro.build.characteristics

在API> 23上,现在检索Flash锁定状态,PersistentDataBlockManager.getFlashLockState()这是该ro.boot.flash.locked属性的新包装API 。

可能的值为:

  • FLASH_LOCK_STATE_LOCKED = 1(0x1)
  • FLASH_LOCK_STATE_UNKNOWN = -1(0xffffffff)
  • FLASH_LOCK_STATE_UNLOCKED = 0(0x0)

某些人感到惊讶的是,今年9月,谷歌开始阻止那些没有根但已经解锁引导加载程序的设备。首先,解锁的引导加载程序会导致验证的引导失败-这就是触发snet的原因。客户端代码没有太大变化:SafetyNet一直在检索ro.boot.verifiedbootstate并且ro.boot.veritymode一直在收集指标,直到有人决定让这些指标影响ctsProfileMatch布尔标志(但不是basicIntegrity)。

dm-verity校正信息检查

对于空闲模式检查,现在传送回Google的设备状态还包括SDK> 23的dm-verity校正信息。您可能有些人可能知道Android N引入了带有错误校正功能的验证启动。这在这里这里这里都进行了描述。当然,前向纠错用于恢复文件系统损坏。一个有趣的安全“副作用”是“ curruption”的定义扩展到“ tampering”,因此此功能可以有效地修复根目录下的文件系统)

安全网搜索所有设备映射目录(例如/sys/block/dm-0/sys/block/dm-1)并寻找一个新的目录fec,这表明一个分区采用前向纠错。如果fec找到,则SNET检索分区名称(/sys/block/dm-X/dm/name)和fec记录文件(/sys/block/dm-X/fec/corrected)并将其发送回去,从而使Google能够跟踪该新功能的使用方式。

系统分区文件模块

在我以前的博文中,我简要介绍了该系统执行完整性度量,检索/system目录中的哈希树并将它们与其他信息一起报告给与SNET分开的系统完整性服务。

一年前,SIC服务器URL为空,但现在已填写。它是:https://sb-ssl.google.com/safebrowsing/clientreport/system-integrity 这似乎是安全浏览系统中未记录的部分。

SELinux检查模块

以前,此模块仅检索:

  • 是否支持selinux
  • 如果通过处于强制模式/sys/fs/selinux/enforce

现在,它还会检索:

  • 版本通过 /selinux_version
  • 策略文件的SHA256哈希(/sepolicy

SSL握手模块

如所讨论的,该模块试图找出如果通信可以以多种方式,如通过具有安装了SSL杀开关应用被截获。它基本上试图找到恶意的TrustManager。在最近的几个版本中,已对其进行了重大重构。

像以前一样,代码尝试与accounts.google.com和联系www.google.com。第三台主机正在play.google.com替换pubads.g.doubleclick.net

对于每个主机,模块都尝试进行SSL握手(sslContext.getSocketFactory().createSocket(hostname, 443)),现在尝试分别进行HTTPS连接(new URL("https", hostname, "").openConnection()),两者都使用自定义的全信任X509TrustManager建立安全连接并检索服务器的SSL证书。然后,该模块找到系统的第一个X509TrustManager(而不是像以前一样都使用它们)。

然后,它使用此TrustManager(通过checkServerTrusted()来验证服务器链。值得注意的是,现在,在API> = 21上,模块使用X509TrustManagerExtensions.checkServerTrusted()代替checkServerTrusted()来检索已验证的证书链。这是个好消息;坏事发生了当它们不同时,如CVE-2016-2402中所示。在自先前版本以来的更改中,即使在API <21上,也有代码重新创建验证证书链-很棒的东西。如前所述,该模块还检查证书是否有效因为它们是否已由用户添加;对于API> = 21而言,现在使用这些方法X509TrustManagerExtensions.isUserAddedCertificate()代替手动检查/data/misc/keychain/cacerts-added

SDCard分析器模块

现在,该模块检索它尝试存储在SD卡上的JPEG文件的最后修改时间。

运营商信息模块

SafetyNet中引入了一个新模块:“运营商信息”,它仅使用系统服务的getNetworkOperatorName()方法来检索当前运营商的名称phone

https://koz.io/inside-safetynet-3/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值