Android传感器安全分析 | xxxAndroid传感器安全分析 – xxx
菜单

Android传感器安全分析

九月 29, 2023 - 安全维基
Android传感器安全分析
传感器介绍

现代智能手机中内置的传感器种类丰富,包括运动传感器、重力感应器、光传感器、距离传感器、陀螺仪、气压计等。这些传感器不仅可以帮助手机感知使用者的位置和动作,还能根据这些信息做进一步的处理操作,提升用户的体验。


以运动传感器为例,它可以检测用户的运动状态,如静止、运动中(步行、跑步、骑车等)以及运动方向。这样的功能可以让用户通过手机更方便地记录自己的运动数据,也可以在游戏中用来实现更加真实和精细的运动跟踪。再比如重力感应器,它可以感知设备的倾斜角度,从而让游戏、音乐播放器等应用进行相应的操作。光传感器可以感知环境的光线强度,从而让设备自动调节屏幕亮度。距离传感器可以感知使用者接近设备,例如手机放在包里或口袋里时,距离传感器会检测到,从而自动关闭屏幕,节省电量。陀螺仪可以检测设备的运动方向和速度,从而让游戏、导航等应用进行相应的操作。


传感器不仅可以让手机更加智能,还能让使用者的生活更加方便。例如用户可以通过手机感知周围环境的变化,比如温度和湿度,来调整自己的生活习惯。同时,这些传感器也为开发者提供了更多的可能性,让他们能够开发出更加智能和实用的应用。



1.1 Android传感器类型

硬件传感器

基于硬件的传感器是内置在手机或智能设备中的物理组件。这类传感器通过直接测量特定的环境属性(如加速度、地磁场强度或角度变化)来采集数据。


软件传感器

基于软件的传感器不是物理设备,它们只是模仿基于硬件的传感器。基于软件的传感器从一个或多个基于硬件的传感器获取数据,有时被称为虚拟传感器或合成传感器。比如线性加速度传感器和重力传感器有些就是基于软件实现的。


通常不同类型传感器型号的数据最高与最低采样率均有所不同。这里简单介绍下传感器采样率的含义,传感器数据采样率是表示每秒钟采集多少个样本点(或数据点),用sample/s或样本点数/秒表示,如采样(频)率为1000Hz,则表示每秒钟采集1000个样本点。Android系统也提供了采样率控制接口供上层APP使用。


Android手机常见内置传感器类型如下表所示。


传感器

类型

说明

用途

加速度传感器

硬件

测量在三个物理轴向(x、y 和 z)上施加在设备上的加速力(包括重力),以m/s2为单位

动态检测(摇晃、倾斜等)。

环境温度传感器

硬件

以摄氏度 (°C) 为单位测量环境室温。

监测气温。

重力传感器

软件或硬件

测量在所有三个物理轴向(x、y、z)上施加在设备上的重力,单位为  m/s2

动态检测(摇晃、倾斜等)。

陀螺仪传感器

硬件

测量设备在三个物理轴向(x、y 和 z)上的旋转速率,以 rad/s 为单位。

旋转检测(旋转、转动等)。

亮度传感器

硬件

测量环境光级(照度),以 lx 为单位。

控制屏幕亮度。

线性加速度传感器

软件或硬件

测量在所有三个物理轴向(x、y 和 z)上施加在设备上的加速力(不包括重力),以  m/s2为单位。

监测单个轴向上的加速度。

磁场传感器

硬件

测量所有三个物理轴向(x、y、z)上的环境地磁场,以  μT 为单位。

创建罗盘。

方向传感器

软件

测量设备围绕所有三个物理轴(x、y、z)旋转的度数。从 API 级别 3 开始,您可以结合使用重力传感器、地磁场传感器和 getRotationMatrix() 方法来获取设备的倾角矩阵和旋转矩阵。

确定设备方位。

气压传感器

硬件

测量环境气压,以 hPa 或 mbar 为单位。

监测气压变化。

距离传感器

硬件

测量物体相对于设备显示屏幕的距离,以 cm 为单位。该传感器通常用于确定手机是否被举到人的耳边。

通话过程中手机的距离。

湿度传感器

硬件

测量环境的相对湿度,以百分比 (%) 表示。

监测露点、绝对湿度和相对湿度。

旋转向量传感器

软件或硬件

通过提供设备旋转矢量的三个元素来检测设备的屏幕方向。

动态检测和旋转检测。


表1  Android手机常见传感器



1.2 Android传感器架构及使用介绍

Android传感器框架大致如下图所示,对于上层APP通过调用SensorManager便可轻松注册其想要访问和管理各种传感器类型数据。并且除了部分如计步器、心率等特殊传感器需要APP单独申请相应权限,对于其他传感器APP通常均是无需申请任何权限即可访问。


Android传感器安全分析

图1 Android传感器架构图


以三方应用注册访问加速度传感器数据为例,主要操作步骤如下所示。

1.获取SensorManager对象;
2.通过SensorManager获取加速度传感器Sensor对象;
3.创建并注册自定义的传感器事件监听器SensorEventListener;可以使用此接口创建两种回调方法,以在传感器值或精确度发生变化时接收相应传感器事件;

4.在合适位置进行注销监听器的调用。


Android传感器安全分析

图2 APP获取传感器数据示例代码



1.3 Android传感器权限介绍

目前Android系统对APP采集传感器数据的权限限制并不多,这里主要介绍以下几种常见传感器权限:


android.permission.ACTIVITY_RECOGNITION

从Android 10 ( 应用目标SDK版本为29或更高版本)开始,应用如需访问计步类型运动传感器,系统要求APP应用必须申请ACTIVITY_RECOGNITION权限,该权限级别为dangerous,因此应用申请该权限时需用户参与授权确认。使用低目标SDK版本(<29)的APP仍可以无需申请该权限直接采集计步传感器数据。


android.permission.BODY_SENSORS

该权限为身体传感器访问权限,如心率传感器、血氧传感器等类型。应用如需访问此类传感器,需要额外申请该权限,该权限级别为dangerous,因此应用申请该权限时需用户参与授权确认。目前手机内置此类身体传感器相对较少,但Android智能手表、移动医疗设备等内置相对较多。


android.permission.HIGH_SAMPLING_RATE_SENSORS

从Android12开始,系统默认将高版本APP(应用目标SDK版本大于31)获取加速传感器等运动传感器的采样率限制在200Hz以下,如果应用需要以更高的速率收集传感器数据,应用必须声明HIGH_SAMPLING_RATE_SENSORS权限,该权限为normal权限,用户无需参与确认。使用低目标SDK版本(<31)的App仍可以无需申请该权限并可以用最高速率采集如加速度等类型传感器数据。


Android传感器安全分析
Android 传感器相关漏洞分析

Android手机传感器由于其普遍性、丰富的类型、三方应用易访问性以及部分传感器涉及用户隐私数据特点,一直是安全研究者和恶意应用的重点关注对象。接下来我们将分别对Android传感器几种典型历史漏洞类型展开分析,包括常见的内存型漏洞、逻辑型漏洞以及当前研究热点侧信道攻击。



2.1 内存型漏洞

CVE-2021-0318是一个典型的内存释放后再使用(UAF)的内存型漏洞,它的漏洞位于SensorService系统服务的传感器事件连接类实现代码中。具体代码位于frameworks/native/services/sensorservice/SensorEventConnection.cpp文件中。


SensorEventConnection提供了一种传感器的数据传输通道,通常Client(APP)需要开始访问监听某一个Sensor传感器时,一个对应的SensorEventConnection在SensorService将会被创建,SensorService服务端在接收到Sensor数据后,通过写入到SensorEventConnection最终将数据传递给相应Client端。


每当Client调用系统服务接口SensorService::createSensorEventConnection()时,一个全新的SensorEventConnection实例将被成功创建,后续其成员变量mEventCache指针将在堆上分配固定大小内存空间,用于缓存后续部分传感器事件类型数据。


Android传感器安全分析

图3 SensorService::createSensorEventConnection()函数


Android传感器安全分析

图4 mEventCache初始化代码片段


然而当Client一旦主动调用SensorEventConnection::destroy()函数后,SensorEventConnection将进行部分资源的销毁工作,mEventCache指向的内存空间也将被主动delete释放掉。具体代码如下图所示。


Android传感器安全分析

图5 SensorEventConnection::destroy()函数


由于SensorEventConnection对象本身暂时仍未被全局释放,Client若再次调用SensorEventConnection::enableDisable()函数时,最终可能再次触发如下函数调用链:

SensorEventConnection::enableDisable()–>

SensorService::enable()–>

SensorEventConnection::sendEvents()–>

SensorEventConnection::appendEventsToCacheLocked()


Android传感器安全分析

图6 SensorEventConnection::enableDisable()函数


我们可以看到SensorEventConnection::appendEventsToCacheLocked()函数内部会再次对已释放的mEventCache指针所指向的内存空间进行读写操作,导致将出现堆内存释放后使用(Use-after-free)漏洞,该内存破坏性漏洞存在可能后续被恶意利用进行提权操作的风险。


Android传感器安全分析

图7 SensorEventConnection::appendEventsToCacheLocked()函数



2.2 逻辑型漏洞

接下来将介绍的CVE-2023-21034是一个典型由于代码设计实现存在缺陷从而导致权限检测被绕过的逻辑漏洞。利用该漏洞可以让目标SDK版本应用在部分场景下绕过ACTIVITY_RECOGNITION 或HIGH_SAMPLING_RATE_SENSORS系统权限的限制。


该漏洞问题代码位于Android传感器系统服务frameworks/native/services/sensorservice/SensorService.cpp文件当中。该系统服务代码里提供了两个函数来对APP应用传感器相关权限进行检测,一个是isRateCappedBasedOnPermission()函数,该函数负责检测APP是否有权限获取传感器的最高采样率(即HIGH_SAMPLING_RATE_SENSORS权限),函数代码如下图所示。


Android传感器安全分析

图8 isRateCappedBasedOnPermission()函数


另外一个是canAccessSensor()函数,该函数主要负责检测APP是否有访问计步器等类型传感器数据的权限(即ACTIVITY_RECOGNITION 权限),具体实代码如下图所示。


Android传感器安全分析
图9 canAccessSensor()函数


这两个权限检测函数有一个共同的特征就是首先通过getTargetSDKVersion()函数查询APP的目标SDK版本号,为了兼容性考虑,系统将首先判断应用目标SDK版本是否低于特定版本,是则不做相应的权限检测。如果应用目标SDK版本号高于特定版本则需要进行应用权限检测,因此应用则需要申请相应权限。接下来我们继续分析getTargetSDKVersion()函数,其代码实现如下图所示。


Android传感器安全分析
图10 getTargetSDKVersion()函数


通过代码可以看到getTargetSDKVersion()函数功能是负责通过包名查询其对应的SDK版本号,该函数内部声明使用到一个名为sPackageTargetVersion的容器变量,该变量类型为std::map,它主要用于缓存包名与目标SDK版本的映射关系,为了提升查询APP目标SDK版本的效率,函数会优先查询该缓存表内是否存在应用包名与对应的版本号,有则直接返回结果,没有则需通过PackageManager系统服务接口getTargetSDKVersionForPackage()进行实际查询操作,查询结果又会将同步更新到sPackageTargetVersion缓存表中,方便下次快速查询应用目标版本号,从而减少对PackageManager系统服务getTargetSDKVersionForPackage接口的重复调用频次。


Android传感器安全分析
图11 sPackageTargetVersion全局变量


然而由于该系统服务对于sPackageTargetVersion缓存表内部数据更新机制存在一定缺陷,在SensorService服务内部对缓存表只存在新增跟查询操作且不存在任何删除或更新老化操作(除非用户主动重启手机),导致如以下一些场景下会出现权限绕过风险:


1.     用户手机中APP目标SDK版本最开始是低于29,访问计步传感器无需申请权限。若APP正常升级后其目标版本高于29,但是由于APP升级前有执行过传感器访问操作,导致sPackageTargetVersion缓存表里可能仍然缓存的是老版本的目标SDK版本值,因此升级后的APP可以直接绕过系统针对高版本应用(>29)的ACTIVITY_RECOGNITION权限限制。


2.     用户手机中APP目标SDK版本最开始低于31,并执行了访问加速度传感器访问操作,后续即使该APP被用户正常删除后,使用高版本SDK的恶意应用若伪造相同包名去访问加速度传感器,也可以绕过isRateCappedBasedOnPermission()函数中系统对高版本应用(>31)的HIGH_SAMPLING_RATE_SENSORS权限检测。



2.3 测信道攻击

与常规攻击方法不同,侧信道攻击的关注点不再是系统的直观行为,而是由系统行为引起的诸如执行时间、功率损耗、无线电信号等间接表现的变化,从而通过统计方法推测出系统的原始行为。加上侧信道类攻击的隐蔽性以及不易防范等特性,近年来针对终端各类侧信道攻击研究也一直是安全学术界的研究热点。基于运感器的侧信道攻击同样易于实现,并且隐蔽性极强,与通话、 GPS 等模块不同,当前智能手机大都没有对运动传感器赋予高等级安全的权限,所以APP访问大部分运动传感器时用户均是无明显感知的。因此针对利用手机传感器通过侧信道方式窃取用户隐私数据的研究也是频频出现在四大安全顶会论文中。


我们这里将简要介绍一篇针对传感器侧信道攻击研究论文,它来自与浙江大学安全研究团队发表在NDSS 2020安全顶会上的研究成果。论文全名为《Learning-based Practical Smartphone Eavesdropping with Built-in Accelerometer》,其主要的研究内容为如何利用加速度传感器进行语音窃听。


论文中指出当手机播放声音时,扬声器产生的震动会通过主板传递至加速传感器,进而影响该传感器所采集的运动信号。由于加速传感器本身就是一种测量手机自身加速度的传感器,其对震动信号的捕捉能力极为优秀,因此能够较好的保留声音信号中的语义信息。具体的攻击场景如下图所示。


Android传感器安全分析
图12 数据收集场景


在手机上模拟恶意APP应用采集到大量扬声器工作时加速度传感器数据,研究团队基于深度学习算法实现了针对手机语音信号的关键字识别和语音重建攻击,证明了从加速传感器信号中识别并恢复出敏感语音信息的可行性。若读者想深入了解该攻击模型的实现细节以及实验结果可以下载查看其论文内容,本文就不再赘述。


Android传感器安全分析
图13 数据分析还原声音信号


论文中也指出当前这种攻击对加速度传感器支持的最高采样率有一定要求,通常采样率越高才能更好的恢复人声。比如传感器若以200Hz以下的频率工作时,目前其能完整恢复的语音信号将限制在100Hz以下,而人类语音的信息主要存在于85Hz以上的频段,因此传感器能采集到的语音信息也相对较少。


为了应对这类攻击降低用户隐私泄露的潜在风险,Google在Android12开始系统将APP访问运动传感器的采样率默认限制为200Hz以下,来减少此类传感器可能采集到的语音信号。如果某些特殊的应用程序需要以更高的采样率获取传感数据,则需额外申请HIGH_SAMPLING_RATE_SENSORS权限,该权限级别为normal,用户无需参与确认。虽然这种防御策略在一定程度提升了利用难度,但是并没有彻底解决运动传感器带来的隐私威胁。


Android传感器安全分析
总结

本文对常见Android传感器类型、使用方法、相关权限进行了简要介绍并分析了几种典型的传感器安全漏洞。目前,我们也看到Google持续加强Android传感器安全方面的各类措施,以确保用户的隐私安全。然而随着手机各类传感器芯片快速发展与部分传感器数据性质以及其易访问的特性,注定它将继续是安全研究人员以及恶意攻击者的一个热点研究目标。我们也将继续对Android传感器安全攻防领域展开持续深入的研究。

Android传感器安全分析
参考资料

1、https://developer.android.com/guide/topics/sensors

2、《Android更新公告 – 2021 年 01 月》:

https://source.android.com/docs/security/bulletin/2021-01-01

3、《Pixel 更新公告 – 2023 年 3 月》:

https://source.android.com/docs/security/bulletin/pixel/2023-03-01

4、《Learning-based Practical Smartphone Eavesdropping with Built-in Accelerometer》

https://www.ndss-symposium.org/ndss-paper/learning-based-practical-smartphone-eavesdropping-with-built-in-accelerometer/



➤ 往期推荐

· 安全开发·数智未来 | OPPO安珀实验室,助力第七届安全开发者峰会(2023 SDC)

· 手把手系列之——搭建TA-to-TA通信

· 保护函数返回的利器——Linux Shadow Call Stack

· Parcelable和Bundle的爱恨情仇(一)——读写不匹配

· AOSP ServiceFuzzer框架分析



Notice: Undefined variable: canUpdate in /var/www/html/wordpress/wp-content/plugins/wp-autopost-pro/wp-autopost-function.php on line 51