当前位置: 首页 > 科技观察

逆向看证书覆盖安装漏洞

时间:2023-03-18 19:53:55 科技观察

前言首先了解一下证书覆盖安装漏洞。该漏洞是2020年谷歌官方公布的漏洞之一,编号为CVE-2020-0015。造成该漏洞的主要原因是由于本地安装的证书被覆盖导致的提权漏洞,本文将从逆向角度分析证书安装过程,分析漏洞发生的位置和原因形成。分析过程中,代码会进行截图,尽可能覆盖所有关键代码,防止本文读者在阅读过程中反编译查看代码。漏洞介绍证书覆盖安装漏洞主要体现在系统导入证书时,导入证书的功能由系统中的CertInstaller.apk完成。但是在使用中没有进行安全验证,导致导入证书的界面被覆盖。由于证书安装是由系统应用完成的,当安装界面被覆盖时,提权的目的就变了。根据官方说法,该漏洞存在于全系统版本,但官方只修复了Android-8.0、Android-8.1、Android-9、Android-10系统版本。通过以下代码分析该漏洞产生的原因。分析过程首先,我们通过ADB命令从手机中提取CertInstaller.apk文件到本地,CertInstaller.apk在系统中的/system/app/CertInstaller/目录下。得到APK文件后,我们使用jadx、jeb等工具对APK文件进行反编译。然后我们通过ADB命令将/system/app/CertInstaller/CertInstaller.apk复制到本地,使用jadx、jeb等反编译工具对apk进行反编译。首先我们来看一下反编译后的AndroidManifest.xml文件。从AndroidManifest.xml文件可以看出,主要入口在CertInstallerMain中,因为是一个activity,所以我们从onCreate函数开始分析:代码位置:com/android/certstaller/CertInstallerMain.java可以看到从上面的代码中,首先获取intent对象并判断其携带的数据,主要有三种情况:intent不携带任何数据,或者选择sdcard中的证书文件进行安装,即选择安装certificatefromthestoragedeviceinthesystemsettings,如下图:Intent携带证书内容,直接创建一个Intent并启动CertInstaller安装证书,例如:通过action列出已安装的证书来自以上三部分,无论是第一种情况还是第二种情况的分析,都可以到达证书安装的位置,那么我们主要分析第二种情况,创建一个启动CertInstaller的intentactivity,并以参数形式传递携带证书内容的Intent。继续往下看:代码位置:com/android/certinstaller/CertInstaller.java从代码可以看出,证书安装过程基本依赖于CredentialHelper类。首先,使用createCredentialHelper函数创建一个CredentialHelper实例。从上面的代码可以看出,在创建CredentialHelper实例的同时,也进行了证书解析操作。这里我们主要看parseCert(byte[]bytes)函数,其中会根据证书将证书缓存到mCaCerts或mUserCert列表中。然后继续分析CertInstaller的OnCreate函数,继续往下看验证当前环境,其中keyguardManager.createConfirmDeviceCredentialIntent(null,null);是检查是否设置信任凭证。然后它将调用extractPkcs12OrInstall函数。PKCS12文件一般都有密码保护,所以需要弹出密码输入框输入密码。当你平时抓包设置代理证书或安装CA证书时,你会去else。继续分析代码。这里可以看到InstallOthersAction中的run方法其实就是调用了CertInstaller.installOther函数;可以看到在安装证书之前做了一个校验,检查是否有CA证书,或者私有和用户证书,然后调用nameCredential()函数会调用showDialog()弹窗安装证书。这就是漏洞发生的地方。产生该漏洞的原因是系统的对话框弹窗在弹窗位置没有安全保护,所以对话框可以被劫持和覆盖,这也是造成该漏洞的主要原因。由于设备环境原因,该漏洞仅在低版本手机上进行测试,未在修复后的高版本手机上进行测试。我们看下面的代码:这里为了方便,直接创建了一个线程用于监听,也可以在服务中实现。为线程创建runnabl任务,确定当前运行的应用程序包名称。如果是com.android.certinstaller,启动一个伪装的activity界面覆盖。此活动界面设置为对话框显示。代码中getTopPackage()检测当前运行的是哪个应用,然后在线程中判断,如果是certInstaller应用的进程,则弹窗覆盖系统对话框,伪造证书安装界面,导致在本地提权。错误修复以下是谷歌的官方修复。从上图中我们可以看到在CertInstaller.java代码的onCreate方法中增加了一个系统属性“SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS”。添加该属性的目的是为了屏蔽其他应用的悬浮窗,避免系统界面上的恶意程序被覆盖。该漏洞风险目前仅在Android8-Android10系统正式修复。综上所述,该漏洞本质上是一个劫持漏洞,但又不同于常规的劫持。常规劫持针对的是非系统应用,而证书覆盖安装漏洞针对的是系统应用。在修复后的系统上,如果恶意程序伪装成系统应用程序,证书安装仍然可以被覆盖,漏洞依然存在。