移动安卓App+BurpSuite的渗透测试
从Android 7.0及以上版本开始,安卓系统更改了信任用户安装证书的默认行为,默认不信任用户证书,用户安装的证书都是用户证书,因此不管是filddle还是burp,都是把他们的根证书安装到了用户证书。
还有移动app默认只信任系统预装的CA证书(开发人员可通过定义配置文件的方式,定义哪些证书可以信任),不会信任用户安装的CA证书,因此导致我们手动生成的burpsuite证书导入手机后,已经不能拦截App的请求,同时,通过Burp代理访问https网站,系统会提示"该证书并非来自可信的授权中心"。
移动App的渗透,一般推荐安卓7.0及以下为测试环境,但如今越老越多的APP已经不支持安卓5等旧版本了
所以,就以夜神模拟器为例,记录下自定义安卓系统级CA证书以方便抓取HTTPS的包,如使用安卓真机,可能在细节上略有差异
整体流程:
1.证书导出
将burp证书导出,把后缀改为.der
2.计算证书HASH
计算证书HASH,我这里使用Linux下的命令
安卓系统CA证书名字都是hash .0 ,文件名是 hash ,后缀名是 0 ,即pem证书文件名组成为:hash值+.0,故先计算出证书 hash 最后重命名证书
ubuntu@VM-16-11-ubuntu:~/Public$ openssl x509 -inform DER -in burpca.der -out burpca.pem
ubuntu@VM-16-11-ubuntu:~/Public$ ls
burpca.der burpca.pem
ubuntu@VM-16-11-ubuntu:~/Public$ openssl x509 -inform PEM -subject_hash_old -in burpca.pem
9a5ba575
-----BEGIN CERTIFICATE-----
MIIDyTCCArGgAwIBAgIEU6k7MzANBgkqhkiG9w0BAQsFADCBijEUMBIGA1UEBhML
UG9ydFN3aWdnZXIxFDASBgNVBAgTC1BvcnRTd2lnZ2VyMRQwEgYDVQQHEwtQb3J0
U3dpZ2dlcjEUMBIGA1UEChMLUG9ydFN3aWdnZXIxFzAVBgNVBAsTDlBvcnRTd2ln
Z2VyIENBMRcwFQYDVQQDEw5Qb3J0U3dpZ2dlciBDQTAeFw0xNDA2MjQwODQ3NDda
Fw00MTA2MjQwODQ3NDdaMIGKMRQwEgYDVQQGEwtQb3J0U3dpZ2dlcjEUMBIGA1UE
CBMLUG9ydFN3aWdnZXIxFDASBgNVBAcTC1BvcnRTd2lnZ2VyMRQwEgYDVQQKEwtQ
b3J0U3dpZ2dlcjEXMBUGA1UECxMOUG9ydFN3aWdnZXIgQ0ExFzAVBgNVBAMTDlBv
cnRTd2lnZ2VyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjSEb
Hg/kfMjoj7sh9vQsPpvI1/Bfypwdp8Xm8fTBZEXPwfI7nUZ4Gn8c0P/QFQwZ1xMn
g7Jct+D2C0x6zosMT1Kv0/UsRN7NRQm1R1pv9EMbR//JCGwQU2ORxV9dU1HU9x7m
L/f5hkQcMz680YoUKnfW/kDODnbIIQkUmBTFKSvti4SlPyKkIvaNSskf1ReAxVHi
txbNpl8QiL+xBrvq3Vg4nwh70NpXD40FSplYaxD3ffbVgxYCMzp0ZT+Ud3AaiOAA
9IB/9ZyhS36IlfBZXRcYNoLUBmfYEEE44eX3cFvmOYcewHHAJbqPa2Y79slWeKIp
K5XaWkuHvsPtogyfkwIDAQABozUwMzASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1Ud
DgQWBBS7nfTpuNhzlKzbtuJ8/QTDRkZ7JTANBgkqhkiG9w0BAQsFAAOCAQEAQj4T
PpNBluUkUIRBCr/ATxJGogGDukvolexLGiMU6CKBVbdLwsp0rIxZJojtfvYxSrK/
iz3S9XWKcZFJyY142GALhyClLYhWKw4zLjQVik5tw0r236JKox3oOWhze5QLHnO/
aAjePpYo360N5enuXwCWfDSeb5YLVGx2HH+HNNvfzTf6YVRzYKvQeGHfjUlb5+xU
0DM1nPlDckH5xR0NL0IIbyfzEHA43ZDiEwT9/OjWnXCarOe/IWzh1nu1jem4J9/0
yySuKkg/+xLr3d+n/6kUqplOz4AvyAaYt7ZOTMpTQQo+ykTB82YWdQYr8OXg+6b+
j1Hi/AZ/MAdZhILQ3g==
-----END CERTIFICATE-----
计算证书hash一定要用subject_hash_old,而不是subject_hash
因为subject_hash使用SHA-1算法,subject_hash_old使用OpenSSL 1.0.0之前老算法MD5计算
经过测试在Android 7 64bit上只能使用subject_hash_old系统才能正确识别出证书。
TIPS:
文件名是一个Hash值,而后缀是一个数字。后缀名的数字是为了防止文件名冲突的,比如如果两个证书算出的Hash值是一样的话,那么一个证书的后缀名数字可以设置成0,而另一个证书的后缀名数字可以设置成1
3.移动到系统根证书目录
将刚才生成的pem改名为xxxx.0
ubuntu@VM-16-11-ubuntu:~/Public$ mv burpca.pem 9a5ba575.0
ubuntu@VM-16-11-ubuntu:~/Public$ ls
9a5ba575.0 burpca.der
3.1安装系统CA证书
-
系统证书路径:
/system/etc/security/cacerts/
-
用户证书路径:
/data/misc/user/0/cacerts-added/
通过模拟器自带的文件共享将自定义证书9a5ba575.0从移动到模拟器下的对应目录 /system/etc/security/cacerts/ 9a5ba575 .0
注意:虽然到这里自定义证书已导入,但暂时无法被读取,因为系统证书都是644权限,所以还需将自定义证书权限也改为644,防止普通用户无权读取写入。 /system目录默认是只读,这里只需配合本地adb命令以读写权限重新挂载 /system ,一般该命令存放在模拟器安装目录/bin目录下
PS D:\Program Files\Nox\bin> .\adb.exe shell
beyond1q:/ # ls
acct default.prop init.qcom.rc mnt seapp_contexts ueventd.qcom.rc
bugreports dev init.rc oem selinux_version ueventd.rc
cache etc init.superuser.rc proc sepolicy vendor
charger file_contexts.bin init.usb.configfs.rc property_contexts service_contexts
config fstab.qcom init.usb.rc root storage
d init init.zygote32.rc sbin sys
data init.environ.rc lib sdcard system
beyond1q:/ # su
beyond1q:/ # whoami
root
beyond1q:/ # cd system/etc/security/cacerts/
beyond1q:/system/etc/security/cacerts # mount -o remount,rw /system
//这里需要以读写权限重新挂载/system,否则权限为只读无法修改
beyond1q:/system/etc/security/cacerts # chmod 644 ./9a5ba575.0
beyond1q:/system/etc/security/cacerts # ll | grep 9a5ba575.0
-rw-r--r-- 1 root root 1375 2021-11-7 22:38 9a5ba575.0
4.查看导入的自定义证书
以上步骤全部完成后,在手机的设置->安全->加密与凭据->信任的凭据 能看到新加入burp的证书已被安装到系统证书
5.重启-结束
最后手动重启设备,这时就可以愉快的抓到安卓7下APP的HTTPS数据包了
这里还有一点就是,模拟器打开手机浏览器,可能会提示“该网站的安全证书有问题”,解决办法:弹出安全警告的提示框中点击继续按钮,直到点击没有窗口为止,然后在浏览器右上角的设置里,找到隐私和安全下拉框下的“显示安全警告”选项,取消打勾后返回,这一步之后浏览任何https网站都不会跳出证书安全警告了。
总结
写在最后:以上方法只是最常规的解决办法,现下各种移动APP也出现越来越多对抗抓包的检测方法
如APP预埋固定证书:
证书固定(Certificate Pinning)是指Client端内置Server端真正的公钥证书。表现就是抓包时,无法连接网络并且也接收不到任何数据(代理日志里 TLS 握手失败)。这是因为在HTTPS请求时,Server端发给客户端的公钥证书必须与Client端内置的公钥证书一致,请求才会成功。
APP内置了仅接受指定域名的证书,不接受操作系统或者浏览器内置的CA根证书对应的任何证书,当服务器返回的证书和代码中的证书不一致就不进行通信,这使得App只能和服务器进行通信,这样就保障了APP与服务端通信的唯一性和安全性,这个时候就需要绕过,比如利用Xposed + JustTrustMe + SSLUnpinning
双向认证:
APP客户端和服务端都互相验证对方证书,具体为客户端先验服务端证书,通过后就会把本地的证书发给服务器去验证,成功后才开始正常通信。
关于双向认证的原理。
首先,双向认证需Server支持,Client必须内置一套公钥证书 + 私钥。在SSL/TLS握手过程中,Server端会向Client端请求证书,Client端必须将内置的公钥证书发给Server,Server验证公钥证书的真实性。
注意:这里的内置的公钥证书有区别于前面预埋证书(固定),双向认证内置的公钥证书+私钥是额外的一套,不同于证书固定内置的公钥证书。如果一个Client既使用证书固定,又使用双向认证,那么Client端应该内置一套公钥证书 + 一套公钥证书和私钥。第一套与Server端的公钥证书相同,用于Client端系统校验与Server发来的证书是否相同,即证书固定;第二套SSL/TLS握手时公钥证书发给Server端,Server端进行签名校验,即双向认证。
使用了双向认证的HTTPS请求,同样无法直接抓包,这种情况需要找证书安装在抓包软件,一般证书会在安装包下,如Assets、Res等目录下
代理检测:
当设置手机代理后,APP无法获取网络数据,出现无法连接网络的情况出现。但手机网络是正常的,但就是抓不到包。这时候可能就是这个原因了。
还有模拟器和Root权限检测等等,所以你会发现,当千难万险绕过证书问题后,还会继续有其他问题导致无法抓包🤣🤣🤣,
就此又会涉及到更多的方法来绕过和流量转发,这一部分后面遇到会补。