Android 13/14 注入系统级自定义CA证书
前言:
关键字:ANDROID 13/14、CA证书、系统CA证书、自定义CA证书;
本博文并非原创,博文中的最重要的内容部分,来自于国外的一篇博文(后附),实际上博主也没这个能力,本博文仅仅是对原网络博文的内容,作了一点博主认为合适的优化。基于于CA证书注入安卓系统证书的方法,如果你希望直接查看原博文,可以直接跳转至本博文最下方的"参考资料"。
本博文中的CA注入的方法,理论上适用于Android 13/14,但由于测试条件限制,本博文中的CA注入测试,只在Android 13
的实机环境中验证过。
需要CA注入的使用环境,一般与逆向、爬虫等概念有关;其比较常用的方向是抓包,相应地一般会结合Charles、Fiddler、Wireshark等进行使用,为了便于显示本博文所说的内容,本博文以注入Charles的CA证书为示例进行说明。
当然,基于安卓系统的相关安全防护措施,在进行CA注入前,你还需要一系列的额外操作,比方说"具有安卓系统的ROOT权限",但这些内容的具体操作不会包含在本博文内,这可能需要你额外的去搜索一些其它的资料,本博文会在下面以较为详细的方式说明其相关的要求。
特别提示:如果你在实验过程中,直接复制本博客任意博文中的配置/代码,"空格"字符的前面将可能产生不可见的字符"M-BM-",从而造成文件不可用,这是字符编码的问题~若必需使用复制粘贴方式,请务必手动替换掉配置项中的所有空格!!!或尝试使用以下命令过滤掉所有"M-BM-"字符~
1 2 3 4 |
sed -i 's/\xc2\xa0/ /g' [文件名称] # LINUX下可使用以下命令查看不可见字符的情况 cat -A [文件名称] |
一、环境、要求与建议
在进行CA注入前,你所使用的的安卓系统应该满足以下要求;
1、你已经获取到安卓系统的ROOT权限
2、禁用了安卓系统的"AVB"验证
3、禁用了安卓系统的"dm-verity"验证
*、补充:要禁用"AVB"验证与"dm-verity"验证,要求安卓的SHELL环境下有"avbctl"命令,经博主实测,GOOGLE提供的构建标识为"user"的镜像,不会包含此命令。大部分情况下,博主推荐使用构建标识为"userdebug"的镜像。
实际上,要完成上面的三步操作,对大部分人来说并不简单,包括博主自己;关于"ROOT"的话题,网络上有非常多的教程,ROOT这个概念还算好理解(实际上,这些教程的所谓ROOT并不能算真正意义上的ROOT,这么说吧,即使你已经ROOT了,你会发觉在安卓系统中,依然有非常大的限制,太多的事不能做了,这也是为什么会有本篇博文);但对于"AVB"验证与"dm-verity"验证,大部分人应该是无法理解的,虽然博主在GOOGLE的开发文档上花费了不少时间,但也依然无法确切的清楚这两个安全措施的实际管控范围(其管控范围与安卓系统的分区有关,而关于安卓系统的分区,又是另一个复杂的话题了)。
相对于博主这种,安卓系统的非专业研究玩家来说,博主只能是给出一点建议以让读这篇博文的读者更简单的实现上面说的三个必要条件:
1、建议安卓手机使用原厂GOOGLE手机,如:PIXEL 4/5/...
2、建议使用构建标识为"userdebug"的镜像(解锁ROOT、禁止两个安全验证可在刷机过程中实现)
3、在向手机刷入镜像时,直接禁用"AVB"验证与"dm-verity"验证("fastboot"中的"--disable-verity"、"--disable-verification")
*、重要:安卓系统的安全措施复杂,版本变化快,博主无法保证以上建议的通用性,对于安卓手机的刷机与获取ROOT,读者请量力而行;
二、CA证书注入教程
本博文的所有操作均在 PIXEL 4 上实现,使用的安卓系统为 Android 13,使用的安卓镜像构建标识为"userdebug";
1、从Charles工具中导出CA证书,例如导出文件名为"CharlesCA.pem";
2、将"CharlesCA.pem"上传至任意拥有"openssl"工具的主机上,并计算CA证书的名称(安卓系统上的证书必须按其独有的安全规则对证书进行命名);
1 2 3 4 5 |
# 按安卓系统证书命名规则,获取"CharlesCA.pem"的名称; openssl x509 -inform PEM -subject_hash_old -in CharlesCA.pem | head -1 # 修正证书名称; mv CharlesCA.pem b0ba53e2.0 |
3、将手机连接上ADB(确认已正确连接至ADB服务并可用于调试);
1 2 3 4 5 |
# 将手机连接上ADB,并确认已正确连接; adb devices # 将"b0ba53e2.0"证书上传至安卓系统上的任意目录; adb push b0ba53e2.0 /sdcard/Download/b0ba53e2.0 |
*、本部分为补充内容:本博文已假设你已经禁用了"AVB"验证与"dm-verity"验证;假若你未停用相关安全验证功能,可尝试使用以下命令停用;下面的提示截图,为博主:"已经解锁了ROOT"、"禁用了AVB验证"、"禁用了dm-verity验证"时重复执行禁用命令的截个图;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 将ADB服务切换至ROOT模式(注:构建标识为"user"系统不可以使用本命令) adb root # 禁用"AVB"验证 adb shell avbctl disable-verification # 禁用"dm-verity"验证 adb shell avbctl disable-verity # 首次禁用相关安全验证措施,必须重启设备 adb reboot # 注意:以上操作只生效于当前的"SLOT"("A/B"分区中的活动分区) # 提示:可以在刷机的时候主动禁用"dm-verity"验证与"AVB"验证!!! |
4、修改"system"目录使其具有读写权限
1 2 3 4 5 6 7 8 9 10 |
# 将ADB服务切换至ROOT模式(注:构建标识为"user"系统不可以使用本命令) adb root # 重新挂载系统中的分区使其具有写权限(并非所有分区都能获取到写权限) # 使用本命令,系统会按实际情况决定是否执行重启操作 adb remount -R # 注意:"adb remount"会重新将系统以读写方式挂载 # 注意:"mount -o remount,rw /system"这种方式在"ANDROID 10(含)"之后就失效了 |
5、备份系统CA证书与自有CA证书;严格来说不能算是备份,在手机重启后,自定义CA证书的注入操作就会失效;本处实际是把相关证书收集起来,并进行统一的挂载操作,以保证在自有CA证书注入后,原来的相关的证书能一起正常使用;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# 进入安卓系统的SHELL环境 adb shell # 创建目录用于保存系统CA证书("/data/local/MY_CA_RULE/os") # 创建目录用于保存自有CA证书("/data/local/MY_CA_RULE/customize") $ mkdir -p -m 700 /data/local/MY_CA_RULE/{customize,os} # 复制系统证书 $ cp /apex/com.android.conscrypt/cacerts/* /data/local/MY_CA_RULE/os # 复制自定义证书 $ cp /sdcard/Download/b0ba53e2.0 /data/local/MY_CA_RULE/customize # 注:"/apex/com.android.conscrypt/cacerts/"目录是"Android 13/14"系统, # 为了保障系统证书安全而引入的一个安全措施,部分"Android 13"可能不存在本目录从而不适用本方法。 # 注:关于本目录的说明,请GOOGLE更多的资料,这是一个新的安全机制,博主也不太能说清这一部分的内容。 |
6、创建SHELL脚本文件;这个文件主要作用就注入自定义CA证书的相关操作,这部分内容是来源国外CA注入博文的个人优化版本。由于每次重启设备后,CA的注入操作会被还原,所以每次重启设备后,应该重新执行本脚本以注入自定义CA,写成脚本文件让一切更简单;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# 在 ADB SHELL 环境创建脚本文件 $ cat > /data/local/MY_CA_RULE/CARule.sh << "EOF" # =========================================================================================== # SELINUX权限的定义 # 可以使用"ls -Z /system/etc/security/cacerts/a1b2c3d4.0"查询 CA_SELINUX_TAG="u:object_r:system_file:s0" # 创建一个名为"CARule"的"tmpfs临时文件系统",并将其挂载至"/system/etc/security/cacerts/" # 注:"tmpfs"是一种内存型的"临时文件系统" mount -t tmpfs CARule /system/etc/security/cacerts # 复制证书至"tmpfs临时文件系统"[CARule] cp /data/local/MY_CA_RULE/os/* /system/etc/security/cacerts/ cp /data/local/MY_CA_RULE/customize/* /system/etc/security/cacerts/ # 所有者、权限、SELINUX权限修正 chown root:root /system/etc/security/cacerts/* chmod 644 /system/etc/security/cacerts/* chcon $CA_SELINUX_TAG /system/etc/security/cacerts/* # =========================================================================================== # 获取"Zygote"进程的PID ZYGOTE_PID=$(pidof zygote || true) ZYGOTE64_PID=$(pidof zygote64 || true) # 向"Zygote"进程所在命名空间注入CA证书(APP需要重新启动来应用注入的CA证书) for Z_PID in "$ZYGOTE_PID" "$ZYGOTE64_PID"; do if [ -n "$Z_PID" ]; then nsenter --mount=/proc/$Z_PID/ns/mnt -- \ /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts fi done # =========================================================================================== # 获取父进程为"Zygotes"的每一个进程的PID APP_PIDS=$( echo "$ZYGOTE_PID $ZYGOTE64_PID" | \ xargs -n1 ps -o 'PID' -P | \ grep -v PID ) # 将CA证书注入至每一个APP进程的命名空间并等待操作完成 for PID in $APP_PIDS; do nsenter --mount=/proc/$PID/ns/mnt -- \ /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts & done wait # 成功提示 echo "System Certificate Injected ..." EOF |
7、查询系统CA证书文件的SELINUX权限;安卓系统使用了SELINUX安全措施,不同安卓系统的SELINUX规则可能不同,请按实际情况进行查询;注意,"a1b2c3d4.0"并不真实的文件名称,你应该使用你系统上实际存在的系统证书进行查询;
1 2 3 4 |
# 在 ADB SHELL 环境下,查询系统证书的SELINUX规则定义 # 本处查询出来的规则定义为"u:object_r:system_security_cacerts_file:s0" $ ls -Z /system/etc/security/cacerts/a1b2c3d4.0 u:object_r:system_security_cacerts_file:s0 /system/etc/security/cacerts/a1b2c3d4.0 |
8、修改"/data/local/MY_CA_RULE/CARule.sh"文件中变量"CA_SELINUX_TAG"的值(注意:其默认值为"u:object_r:system_file:s0",这个值的来源是原国外博文中的教程,对于应该将该"SELINUX"的规则应该配置为国外博文中所描述的值,还是配置为系统中实际的SELINUX规则值,博主也不确定那个值才是正确的,这个应该由读者自行判断,只是博主认为其匹配与系统中的实际定义更合适[见脚本,但这也可能是错的方法])
1 2 |
# 修改脚本中的SELINUX规则定义 >>sed -i 's#u:object_r:system_file:s0#u:object_r:system_security_cacerts_file:s0#g' /data/local/MY_CA_RULE/CARule.sh |
9、运行"/data/local/MY_CA_RULE/CARule.sh"文件;注意,这种CA证书注入的方式,在设备重启后就会失效;重启设备后需要重新执行脚本进行证书注入操作;证书是否注入成功,可至安卓系统中的"可信凭据"中查询,图为成功注入后的示例;
1 2 |
$ chmod 700 /data/local/MY_CA_RULE/CARule.sh $ source /data/local/MY_CA_RULE/CARule.sh |
结、
本博文介绍了如何将自有的CA证书注入到安卓系统的系统证书组中,但据博主的实测,使用效果非常不好,在实行中间人攻击进行流量解密的测试中,博主发现其甚至无法解密一些常规的WEB的HTTPS内容,而这些内容,通常情况下是可以进行解密的~当然后,博主只是简单的测试了一下,可能是博主的操作错误吧~
能将自定义的CA证书注入至系统中,这确实是一件危险的事,因为系统的证书实在是太重要了。但虽然如此,当我了解了一些安卓的安全机制后,发现,即使能成功的注入了自定义的CA证书,实际能做事的也不算太多,对于APP应用如何使用证书,安卓有很多方案,而使用系统证书只是其中之一。
这篇博文就到这里结束吧(2023.11.20)~
Android 13/14 注入系统级自定义CA证书:等您坐沙发呢!