App防抓包的四种绕过方法(详细)

Posted 猫和老鼠__

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了App防抓包的四种绕过方法(详细)相关的知识,希望对你有一定的参考价值。

App防抓包的四种绕过方法

简介:

平时做app渗透的适合,是不是经常会遇到burp抓不到包的问题,本文梳理了一些APP抓不到包的解决思路,有问题可以文章下面评论,看到会一个个回复!
文末有本文对应所有工具包地址

1、ssl证书校验(https证书校验=http请求+ssl证书校验)

http请求是不安全的,能轻易被中间人攻击(能被抓包),https安全的关键在于ssl证书

Ssl证书本质上就是一种安全协议,会在数据传输的时候对数据进行加密,只有接收者才拥有解密的密钥(解密的密码)能解密。

Burp是抓应用层的包,不会抓其他层的包,由于没有安装相对应的ssl证书,burp抓到的是乱码的数据无法识别出是http的请求,burp会默认他为其他层的数据包,就不去抓这个包,导致无法抓包

而ssl证书是需要花钱找指定的颁发机构去购买的,只有花钱买的证书才能被允许在互联网之间访问。

浏览器是不会保存ssl密钥的,如果不同网站的ssl证书密钥不同,那每次访问网站之前都需要下载ssl证书安装好后才能访问,这是不现实的,所以安全给业务做了让步,无论哪家公司的资产,想要使用https协议通信,网站ssl证书密钥都必须相同,这样浏览器就只需要保存一个ssl证书就能访问所有网站

burp只需要安装了证书,就能解密https通信的数据,就可以去绕过进行抓包

而app同样,有的app由于资金有限,所以不会去申请自己的ssl证书,就直接使用和浏览器一样的ssl证书,这个我们直接在安卓模拟器安装burp的ssl证书就能绕过

方法

安卓5.0可以直接在设置安装证书,但是安卓7.0及以上需要把证书安装到系统目录下才可以,因为安卓7.0及以上默认只信任系统目录下的证书,其他默认不信任
(文末会放置本文所需要用到的所有文件和工具包)

演示:安卓5.0怎么安装证书



先下载一个burp的证书,重命名为后缀为.cer,下载好了,插在word可以直接拖出来

然后直接拖进模拟器


记住上面的目录

在模拟器中找到证书文件


后面设置个密码就可以了
证书就安装好了,最后配置一下代理


最后打开burp,配置一下就能正常抓包了

演示:安卓7及以上怎么把证书安卓到系统目录

首先需要


然后需要一个burp的证书,但是需要是pem格式的证书,pem格式证书制作方法繁琐,我上网找了一个burp证书的pem格式如下,可以直接使用

(文末会放置本文所需要用到的所有文件和工具包)
将这个证书拖进模拟器

长按这个文件,点击复制

找到系统目录/system/etc/security/cacerts/





最后找到系统目录/system/etc/security/cacerts/
把鼠标往下滑动,直到出现粘贴的按钮点击粘贴


重启模拟器,系统证书安装成功

2、代理屏蔽

有的app做完ssl证书校验后,为了防止被抓包,多做了一层处理
使用okhttp框架,里面可以设置无代理模式,不走系统代理

我们使用burp测试的时候,会在wifi的地方设置一个手动代理,比如192.168.3.13:9090的代理,把数据包发送到本机代理端口上,这样burp就能接受到包

于是app的开发就利用这个特性,做了处理,给app设置自己的代理地址,可能这个代理地址就是服务器的地址,这样就不走burp的代理了

这个我直接安装一个poster,使用vpn代理就能抓到包,一共需要设置三个



记住,需要关闭wifi处的代理,直接使用vpn代理,burp可以照常抓到包

3、证书绑定 (SSL pinning)

证书绑定又叫单向认证,app不使用公开的ssl证书了,他花钱,去找证书颁发机构,去买一个属于自己的证书,并且自己设置了一个通信的密钥(密码)

Burp是抓应用层的包,不会抓其他层的包,由于burp没安装专属于这个app的ssl证书,burp抓到的是乱码的数据无法识别出是http的请求,burp会默认他为其他层的数据包,就不去抓这个包,导致无法抓包

绕过方法:
1、把App里面的证书揪出来,app和抓包软件的通信用那个证书。
2、删除掉App里面,单向认证的代码,让他能使用系统证书,然后他和抓包软件就能通信了。

揪证书需要逆向,很难,第二种可以使用工具进行hook,类似于断点处理

在已经安装好证书和vpn的情况下操作

使用工具hook有两种方法

1、 Xposed框架中的JustTrustMe
2、 objection绕过单向认证

演示:xposed框架中的JustTrustMe
首先打开安卓模拟器

开机,打开游戏中心,搜索xposed框架,可以直接下载安卓7的xposed框架

下载好后,直接打开xposed的app


需要等待一会下载


重启设备后,框架就安装成功了


直接将工具包中JustTrustMe.apk拖进去
(文末会放置本文所需要用到的所有文件和工具包)

然后直接进去xpsed框架




最后再次重启设备,安装的app消失,模块依然存在
JustTrustMe就激活了,可以直接用poster vpn抓包测试app了


JustTrustMe在测试的时候会自动对app所有具有单向认证的地方进行hook

演示:objection绕过单向认证

该方法较为难需要用到的工具有
adb(可以通过windows的命令行去控制安卓机,可以传文件可以执行命令)
frida (Frida 是一款基于 Python +javascript 的 Hook 与调试框架)
frida_tools (简单的说就是一款动态代码检测工具)
objection(Objection是一款移动设备运行时漏洞利用工具)
(文末会放置本文所需要用到的所有文件和工具包)

演示:

  1. 安装frida 、frida_tools 、objection
    前提是已安装了python3,因为这三个工具包本质都是基于python运行调试的,直接打开命令行执行这段代码,注意!需要开启TLY翻墙再进行pip安装,否则会安装失败或者很慢,可能由于这几个工具都是国外的原因

    pip install frida12.11.17 frida_tools8.1.3 objection==1.9.4
    安装好后,最后一行会出现successly的字,代表安装成功了。
    2.如何使用adb连接安卓模拟器
    首先打开夜神模拟器助手,删除掉其他的模拟器,只能留一个模拟器,否则无法连接adb

    启动仅有的一台模拟器,打开设置,进入关于平板电脑,点击版本号,点击7下





    接着打开adb工具包,输入cmd
adb start-server                //开启adb服务
adb devices                    //查看adb连接状态
adb shell                       //打开手机终端
adb kill-server                  //关闭adb服务
adb connect 127.0.0.1:62001      //连接模拟器
adb root                       //将adb权限升级为root
adb push file file                //将adb文件夹下的文件传入模拟器的文件夹下

先开启adb服务

查看现有连接的安卓手机,暂时没有

连接夜神模拟器的安卓手机,connected代表已连接

不同厂商的模拟器,默认连接的端口不同,部分厂商具体如下:

再次输入adb devices查看连接状态

连接成功了,接着需要将frida的服务端,传到模拟器的/data/local/tmp目录下
Frida的服务端下载地址(https://github.com/frida/frida/releases)
必须要和上面的frida的版本一样否则也会报错,我找了很久,下面这个文件可以直接放进去

将frida-serverx86放入adb的目录下


传入文件
adb push frida-serverx86 /data/local/tmp

查看模拟器,传入成功


接着进入模拟器的终端给这个文件权限,安卓的底层是linux所以直接执行linux的命令
执行adb shell

cd /data/local/tmp
chmod 755 frida-serverx86
./frida-serverx86

一套执行下来

这样就可以了,接着随便打开一个cmd
输入frida-ps -U,出现进程名,代表frida执行成功

接着在模拟器运行长城期权app

然后继续在cmd执行frida-ps -Ua

最后使用这条命令

objection -g 包名 explore -s "android sslpinning disable"

objection工具就会自动对长城期权app所有单向认证的地方进行hook

objection -g com.cgws.hdoption explore -s "android sslpinning disable"


出现关于这个命令框代表执行成功,我们就可以正常使用poster vpn代理进行burp抓包测试了

工具包:
地址:
https://download.csdn.net/download/weixin_43264067/87522327

移动端防抓包实践

01.整体概述介绍

1.1 项目背景

  • 通讯安全是App安全检测过程中非常重要的一项

  • 针对该项的主要检测手段就是使用中间人代理机制对网络传输数据进行抓包、拦截和篡改,以检验App在核心链路上是否有安全漏洞。

  • 保证数据安全

  • 通过charles等工具可以对app的网络请求进行抓包,这样这些信息就会被清除的提取出来,会被不法分子进行利用。

  • 不想被竞争对手逆向抓包

  • 不想自身App的数据被别人轻而易举地抓包获取到,从而进行类似业务或数据分析、爬虫或网络攻击等破坏性行为。

1.2 思考问题

  • 开发项目的时候,都需要抓包,很多情况下即使是Https也能正常抓包正常。那么问题来了:

  • 抓包的原理是?任何Https的 app 都能抓的到吗?如果不能,哪些情况下可以抓取,哪些情况下抓取不到?

  • 什么叫做中间人攻击?

  • 使用HTTPS协议进行通信时,客户端需要对服务器身份进行完整性校验,以确认服务器是真实合法的目标服务器。

  • 如果没有校验,客户端可能与仿冒的服务器建立通信链接,即“中间人攻击”。

1.3 设计目标

  • 防止App被各种方式抓包

  • 做好各种防抓包安全措施,避免各种黑科技抓包。

  • 沉淀为技术库复用

  • 目前只是针对App端有需要做防抓包措施,后期其他业务线可能也有这个需要。因此下沉为工具库,傻瓜式调用很有必要。

  • 该库终极设计目标如下所示

  • 第一点:必须是低入侵性,对原有代码改动少,最简单的加入是一行代码设置即可。完全解耦合。

  • 第二点:可以动态灵活配置,支持配置禁止代理,支持配置是否证书校验,支持配置域名合法性过滤,支持拦截器加解密数据。

  • 第三点:可以检测App是否在双开,挂载,Xposed攻击环境

  • 第四点:可以灵活设置加解密的key,可以灵活替换加解密方式,比如目前采用RC4,另一个项目想用DES,可以灵活更换。

1.4 收益分析

  • 抓包库收益

  • 提高产品App的数据安全,必须对数据传输做好安全保护措施和完整性校验,以防止自身数据在网络传输中裸奔,甚至是被三方恶意利用或攻击。

  • 技能的收益

  • 下沉为功能基础库,可以方便各个产品线使用,提高开发的效率。避免跟业务解耦合。傻瓜式调用,低成本接入!

02.市面抓包的分析

2.1 Https三要素

  • 要清楚HTTPS抓包的原理,首先需要先说清楚 HTTPS 实现数据安全传输的工作原理,主要分为三要素和三阶段。

  • Http传输数据目前存在的问题

  • 1.通信使用明文,内容可能被窃听;2.不验证通信方的身份,因此可能遭遇伪装;3.无法证明报文的完整性,所以有可能遭到篡改。

  • Https三要素分别是:

  • 1.加密:通过对称加密算法实现。

  • 2.认证:通过数字签名实现。(因为私钥只有 “合法的发送方” 持有,其他人伪造的数字签名无法通过验证)

  • 3.报文完整性:通过数字签名实现。(因为数字签名中使用了消息摘要,其他人篡改的消息无法通过验证)

  • Https三阶段分别是:

  • 1.CA 证书校验:CA 证书校验发生在 TLS 的前两次握手,客户端和服务端通过报文获得服务端 CA 证书,客户端验证 CA 证书合法性,从而确认 CA 证书中的公钥合法性(大多数场景不会做双向认证,即服务端不会认证客户端合法性,这里先不考虑)。

  • 2.密钥协商:密钥协商发生在 TLS 的后两次握手,客户端和服务端分别基于公钥和私钥进行非对称加密通信,协商获得 Master Secret 对称加密私钥(不同算法的协商过程细节略有不同)。

  • 3.数据传输:数据传输发生在 TLS 握手之后,客户端和服务端基于协商的对称密钥进行对称加密通信。

  • Https流程图如下

2.2 抓包核心原理

  • HTTPS抓包原理

  • Fiddler、Charles等抓包工具,其实都是采用了中间人攻击的方案: 将客户端的网络流量代理到MITM(中间人)主机,再通过一系列的面板或工具将网络请求结构化地呈现出来。

  • 抓包Https有两个突破点

  • CA证书校验是否合法;数据传递过程中的加密和解密。如果是要抓包,则需要突破这两点的技术,无非就是MITM(中间人)伪造证书和使用自己的加解密方式。

  • 抓包的工作流程如下

  • 中间人截获客户端向发起的HTTPS请求,佯装客户端,向真实的服务器发起请求;

  • 中间人截获真实服务器的返回,佯装真实服务器,向客户端发送数据;

  • 中间人获取了用来加密服务器公钥的非对称秘钥和用来加密数据的对称秘钥,处理数据加解密。

2.3 搞定CA证书

  • Https抓包核心CA证书

  • HTTPS抓包的原理还是挺简单的,简单来说,就是Charles作为“中间人代理”,拿到了服务器证书公钥和HTTPS连接的对称密钥。

  • 前提是客户端选择信任并安装Charles的CA证书,否则客户端就会“报警”并中止连接。这样看来,HTTPS还是很安全的。

  • 安装CA证书到手机中必须洗白

  • 抓包应用内置的 CA 证书要洗白,必须安装到系统中。而 Android 系统将 CA 证书又分为两种:用户 CA 证书和系统 CA 证书(必要Root权限)。

  • Android从7.0开始限制CA证书

  • 只有系统(system)证书才会被信任。用户(user)导入的Charles根证书是不被信任的。相当于可以理解Android系统增加了安全校验!

  • 如何绕过CA证书这种限制呢?已知有以下四种方式

  • 第一种方式:AndroidManifest 中配置 networkSecurityConfig,App 信任用户 CA 证书,让系统对用户 CA 证书的校验给予通过。

  • 第二种方式:调低 targetSdkVersion < 24,不过这种方式谷歌市场有限制,意味着抓 HTTPS 的包越来越难操作。

  • 第三种方式:挂载App抓包,VirtualApp 这种多开应用可以作为宿主系统来运行其它应用,利用xposed避开CA证书校验。

  • 第四种方式:Root手机,把 CA 证书安装到系统 CA 证书目录中,那这个假 CA 证书就是真正洗白了,难度较大。

2.4 突破CA证书校验

  • App版本如何让证书校验安全

  • 1.设置targetSdkVersion大于24,去掉清单文件中networkSecurityConfig文件中的system和user配置,设置不信任用户证书。

  • 2.公钥证书固定。指 Client 端内置 Server 端真正的公钥证书。在 HTTPS 请求时,Server 端发给客户端的公钥证书必须与 Client 端内置的公钥证书一致,请求才会成功。

  • 证书固定的一般做法是,将公钥证书(.crt 或者 .cer 等格式)内置到 App 中,然后创建 TrustManager 时将公钥证书加进去。

  • 那么如何突破CA证书校验

  • 第一种:JustTrustMe 破解证书固定。Xposed 和 Magisk 都有相应的模块,用来破解证书固定,实现正常抓包。破解的原理大致是,Hook 创建 SSLContext 等涉及 TrustManager 相关的方法,将固定的证书移除。

  • 第二种:基于 VirtualApp 的 Hook 机制破解证书固定。在 VirtualApp 中加入 Hook 代码,然后利用 VirtualApp 打开目标应用进行抓包。具体看:VirtualHook

2.5 如何搞定加解密

  • 目前使用对称加密和解密请求和响应数据

  • 加密和解密都是用相同密钥。只有一把密钥,如果密钥暴露,内容就会暴露。但是这一块逆向破解有些难度。而破解解密方式就是用密钥逆向解密,或者中间人冒充使用自己的加解密方式!

  • 加密后数据镇兼顾了安全性吗

  • 不一定安全。中间人伪造自己的公钥和私钥,然后拦截信息,进行篡改。

2.6 Charles原理

  • Charles类似代理服务器

  • Charles 通过将软件本身设置成系统的网络访问代理服务器,使得所有的网络请求都会走一遍 Charles 代理,从而 Charles 可以截取经过它的请求,然后我们就可以对其进行网络包的分析。

  • 截取设备网络封包数据

  • Charles对应设置:将代理功能打开,并设置一个固定的端口。默认情况下,端口号为:8888 。

  • 移动设备设置:在手机上设置 WIFI 的 HTTP 代理。注意这里的前提是,Phone 和 Charles 代理设备链接的是同一网络(同一个ip地址和端口号)。

  • 截取Https的网络封包

  • 正常情况下,Charles 是不能截取Https的网络包的,这涉及到 Https 的证书问题。

2.7 抓包原理图

  • Charles抓包原理图

  • Android上的网络抓包原来是这样工作的

2.8 抓包核心流程

  • 抓包核心流程关键节点

  • 第一步,客户端向服务器发起HTTPS请求,charles截获客户端发送给服务器的HTTPS请求,charles伪装成客户端向服务器发送请求进行握手 。

  • 第二步,服务器发回相应,charles获取到服务器的CA证书,用根证书(这里的根证书是CA认证中心给自己颁发的证书)公钥进行解密,验证服务器数据签名,获取到服务器CA证书公钥。然后charles伪造自己的CA证书(这里的CA证书,也是根证书,只不过是charles伪造的根证书),冒充服务器证书传递给客户端浏览器。

  • 第三步,与普通过程中客户端的操作相同,客户端根据返回的数据进行证书校验、生成密码Pre_master、用charles伪造的证书公钥加密,并生成HTTPS通信用的对称密钥enc_key。

  • 第四步,客户端将重要信息传递给服务器,又被charles截获。charles将截获的密文用自己伪造证书的私钥解开,获得并计算得到HTTPS通信用的对称密钥enc_key。charles将对称密钥用服务器证书公钥加密传递给服务器。

  • 第五步,与普通过程中服务器端的操作相同,服务器用私钥解开后建立信任,然后再发送加密的握手消息给客户端。

  • 第六步,charles截获服务器发送的密文,用对称密钥解开,再用自己伪造证书的私钥加密传给客户端。

  • 第七步,客户端拿到加密信息后,用公钥解开,验证HASH。握手过程正式完成,客户端与服务器端就这样建立了”信任“。

  • 在之后的正常加密通信过程中,charles如何在服务器与客户端之间充当第三者呢?

  • 服务器—>客户端:charles接收到服务器发送的密文,用对称密钥解开,获得服务器发送的明文。再次加密, 发送给客户端。

  • 客户端—>服务端:客户端用对称密钥加密,被charles截获后,解密获得明文。再次加密,发送给服务器端。由于charles一直拥有通信用对称密钥enc_key,所以在整个HTTPS通信过程中信息对其透明。

03.防止抓包思路

3.1 先看如何抓包

  • 使用Charles需要做哪些操作

  • 1.电脑上需要安装证书。这个主要是让Charles充当中间人,颁布自己的CA证书。

  • 2.手机上需要安装证书。这个是访问Charles获取手机证书,然后安装即可。

  • 3.Android项目代码设置兼容。Google 推出更加严格的安全机制,应用默认不信任用户证书(手机里自己安装证书),自己的app可以通过配置解决,相当于信任证书的一种操作!

  • 尤其可知抓包的突破口集中以下几点

  • 第一点:必须链接代理,且跟Charles要具有相同ip。思路:客户端是否可以判断网络是否被代理了

  • 第二点:CA证书,这一块避免使用黑科技hook证书校验代码,或者拥有修改CA证书权限。思路:集中在可以判断是否挂载

  • 第三点:冒充中间人CA证书,在客户端client和服务端server之间篡改拦截数据。思路:可以做CA证书校验

  • 第四点:为了可以在7.0上抓包,App往往配置清单文件networkSecurityConfig。思路:线上环境去掉该配置

3.2 设置配置文件

  • 一个是CA证书配置文件

  • debug包为了能够抓包,需要配置networkSecurityConfig清单文件的system和user权限,只有这样才会信任用户证书。

  • 一个是检验证书配置

  • 不论是权威机构颁发的证书还是自签名的,打包一份到 app 内部,比如存放在 asset 里。然后用这个KeyStore去引导生成的TrustManager来提供证书验证。

  • 一个是检验域名合法性

  • Android允许开发者重定义证书验证方法,使用HostnameVerifier类检查证书中的主机名与使用该证书的服务器的主机名是否一致。

  • 如果重写的HostnameVerifier不对服务器的主机名进行验证,即验证失败时也继续与服务器建立通信链接,存在发生“中间人攻击”的风险。

  • 如何查看CA证书的数据

3.3 数据加密处理

  • 网络数据加密的需求

  • 为了项目数据安全性,对请求体和响应体加密,那肯定要知道请求体或响应体在哪里,然后才能加密,其实都一样不论是加密url里面的query内容还是加密body体里面的都一样。

  • 对数据哪里进行加密和解密

  • 目前对数据返回的data进行加解密。那么如何做数据加密呢?目前项目中采用RC4加密和解密数据。

  • 抓取到的内容为乱码

  • 有的APP为了防止抓取,在返回的内容上做了层加密,所以从Charles上看到的内容是乱码。这种情况下也只能反编译APP,研究其加密解密算法进行解密。难度极大!

3.4 避免黑科技抓包

  • 基于Xposed(或者)黑科技破解证书校验

  • 这种方式可以检查是否有Xposed环境,大概的思路是使用ClassLoader去加载固定包名的xp类,或者手动抛出异常然后捕获去判断是否包含Xposed环境。

  • 基于VirtualApp挂载App突破证书访问权限

  • 这个VirtualApp相当于是一个宿主App(可以把它想像成桌面级App),它突破证书校验。然后再实现挂载App的抓包。判断是否是双开环境!

04.防抓包实践开发

4.1 App安全配置

  • 添加配置文件

  • android:networkSecurityConfig="@xml/network_security_config"

  • 配置networkSecurityConfig抓包说明

  • 中间人代理之所有能够获取到加密密钥就是因为我们手机上安装并信任了其代理证书,这类证书安装后都会被归结到用户证书一类,而不是系统证书。

  • 那我们可以选择只信任系统内置的系统证书,而屏蔽掉用户证书(Android7.0以后就默认是只信任系统证书了),就可以防止数据被解密了。

  • 实现App防抓包安全配置方式有两种:

  • 一种是Android官方提供的网络安全配置;另一种也可以通过设置网络框架实现(以okhttp为例)。

  • 第一种:具体可以看清单配置文件,相当于base-config标签下去掉 这组标签。

  • 第二种:需要给okhttpClient配置 X509TrustManager 来监听校验服务端证书有效性。遍历设备上信任的证书,通过证书别名将用户证书(别名中含有user字段)过滤掉,只将系统证书添加到验证列表中。

  • 该方案优点和缺点分析说明

  • 优点:network_security_config配置简单,对整个app网络生效,无需修改代码;代码实现对通过该网络框架请求的生效,能兼容7.0以前系统。

  • 缺陷:network_security_config配置方式,7.0以前的系统配置不生效,依然可以通过代理工具进行抓包。okhttp配置的方式只能对使用该网络框架进行数据传输的接口生效,并不能对整个app生效。

  • 破解:将手机进行root,然后将代理证书放置到系统证书列表内,就可以绕过代码或配置检查了。

4.2 关闭代理

  • charles 和 fiddler 都使用代理来进行抓包,对网络客户端使用无代理模式即可防止抓包,如

OkHttpClient.Builder()
    .proxy(Proxy.NO_PROXY)
    .build()
  • no_proxy实际上就是type属性为direct的一个proxy对象,这个type有三种

  • direct,http,socks。这样因为是直连,所以不走代理。所以charles等工具就抓不到包了,这样一定程度上保证了数据的安全,这种方式只是通过代理抓不到包。

  • 通常情况下上述的办法有用,但是无法防住使用 VPN 导流进行的抓包

  • 使用VPN抓包的原理是,先将手机请求导到VPN,再对VPN的网络进行Charles的代理,绕过了对App的代理。

  • 该方案优点和缺点分析说明

  • 优点:实现简单方便,无系统版本兼容问题。

  • 缺陷:该方案比较粗暴,将一切代理都切断了,对于有合理诉求需要使用网络代理的场景无法满足。

  • 破解:使用ProxyDroid全局代理工具通过iptables对请求进行强制转发,可以有效绕过代理检测。

4.3 证书校验(单向认证)

  • 下载服务器端公钥证书

  • 为了防止上面方案可能导致的“中间人攻击”,可以下载服务器端公钥证书,然后将公钥证书编译到Android应用中一般在assets文件夹保存,由应用在交互过程中去验证证书的合法性。

  • 如何设置证书校验

  • 通过OkHttp的API方法 sslSocketFactory(sslSocketFactory,trustManager) 设置SSL证书校验。

  • 如何设置域名合法性校验

  • 通过OkHttp的API方法 hostnameVerifier(hostnameVerifier) 设置域名合法性校验。

  • 证书校验的原理分析

  • 按CA证书去验证的,若不是CA可信任的证书,则无法通过验证。

  • 单向认证流程图

  • 该方案优点和缺点分析说明

  • 优点:安全性比较高,单向认证校验证书在代码中是方便的,安全性相对较高。

  • 缺陷:CA证书存在过期的问题,证书升级。

  • 破解:证书锁定破解比较复杂,比如老牌的JustTrustMe插件,通过hook各网络框架的证书校验方法,替换原有逻辑,使校验失效。

4.4 双向认证

  • 什么叫做双向认证

  • SSL/TLS 协议提供了双向认证的功能,即除了 Client 需要校验 Server 的真实性,Server 也需要校验 Client 的真实性。

  • 双向认证的原理

  • 双向认证需要 Server 支持,Client 必须内置一套公钥证书 + 私钥。在 SSL/TLS 握手过程中,Server 端会向 Client 端请求证书,Client 端必须将内置的公钥证书发给 Server,Server 验证公钥证书的真实性。

  • 用于双向认证的公钥证书和私钥代表了 Client 端身份,所以其是隐秘的,一般都是用 .p12 或者 .bks 文件 + 密钥进行存放。

  • 代码层面如何做双向认证

  • 双向校验就是自定义生成客户端证书,保存在服务端和客户端,当客户端发起请求时在服务端也校验客户端的证书合法性,如果不是可信任的客户端发送的请求,则拒绝响应。

  • 服务端根据自身使用语言和网络框架配置相应证书校验机制即可。

  • 双向认证流程图

  • 该方案优点和缺点分析说明

  • 优点:安全性非常高,使用三方工具不易破解。

  • 缺陷:服务端需要存储客户端证书,一般服务端会对应多个客户端,就需要分别存储和校验客户端证书,增加校验成本,降低响应速度。该方案比较适合对安全等级要求比较高的业务(如金融类业务)。

  • 破解:由于在服务端也做校验,在服务端安全的情况下很难被攻破。

4.5 防止挂载抓包

  • Xposed是一个牛逼的黑科技

  • Xposed + JustTrustMe 可以破解绕过校验CA证书。那么这样CA证书的校验就形同虚设了,对App的危险性也很大。

  • App多开运行在多个环境上

  • 多开App的原理类似,都是以新进程运行被多开的App,并hook各类系统函数,使被多开的App认为自己是一个正常的App在运行。

  • 一种是从多开App中直接加载被多开的App,如平行空间、VirtualApp等,另一种是让用户新安装一个App,但这个App本质上就是一个壳,用来加载被多开的App。

  • VirtualApp是一个牛逼的黑科技

  • 它破坏了Android 系统本身的隔离措施,可以进行免root hook和其他黑科技操作,你可以用这个做很多在原来APP里做不到事情,于此同时Virtual App的安全威胁也不言而喻。

  • 如何判断是否具有Xposed环境

  • 第一种方式:获取当前设备所有运行的APP,根据安装包名对应用进行检测判断是否有Xposed环境。

  • 第二种方式:通过自造异常来检测堆栈信息,判断异常堆栈中是否包含Xposed等字符串。

  • 第三种方式:通过ClassLoader检查是否已经加载了XposedBridge类和XposedHelpers类来检测。

  • 第四种方式:获取DEX加载列表,判断其中是否包含XposedBridge.jar等字符串。

  • 第五种方式:检测Xposed相关文件,通过读取/proc/self/maps文件,查找Xposed相关jar或者so文件来检测。

  • 如何判断是否是双开环境

  • 第一种方式:通过检测app私有目录,多开后的应用路径会包含多开软件的包名。还有一种思路遍历应用列表如果出现同样的包名,则被认为双开了。

  • 第二种方式:如果同一uid下有两个进程对应的包名,在"/data/data"下有两个私有目录,则该应用被多开了。

  • 判断了具有xposed或者多开环境怎么处理App

  • 目前使用VirtualApp挂载,或者Xposed黑科技去hook,前期可以先用埋点统计。测试学而思App发现挂载在VA上是推出App。

4.5 数据加解密

  • 针对数据加解密入口

  • 目前在网络请求类里添加拦截器,然后在拦截器中处理request请求和response响应数据的加密和解密操作。

  • 主要是加密什么数据

  • 在request请求数据阶段,如果是get请求加密url数据,如果是post请求则加密url数据和requestBody数据。

  • 在response响应数据阶段,

  • 如何进行加密:发起请求(加密)

  • 第一步:获取请求的数据。主要是获取请求url和requestBody,这一块需要对数据一块处理。

  • 第二步:对请求数据进行加密。采用RC4加密数据

  • 第三步:根据不同的请求方式构造新的request。使用 key 和 result 生成新的 RequestBody 发起网络请求

  • 如何进行解密:接收返回(解密)

  • 第一步:常规解析得到 result ,然后使用RC4工具,传入key去解密数据得到解密后的字符串

  • 第二步:将解密的字符串组装成ResponseBody数据传入到body对象中

  • 第三步:利用response对象去构造新的response,然后最后返回给App

4.7 证书锁定

  • 证书锁定是Google官方比较推荐的一种校验方式

  • 原理是在客户端中预先设置好证书信息,握手时与服务端返回的证书进行比较,以确保证书的真实性和有效性。

  • 如何实现证书锁定

  • 有两种实现方式:一种通过network_security_config.xml配置,另一种通过代码设置;

//第一种方式:配置文件 api.zuoyebang.cn 38JpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhK90= 9k1a0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM90K=

//第二种方式:代码设置fun sslPinning(): OkHttpClient val builder = OkHttpClient.Builder()val pinners = CertificatePinner.Builder().add("api.zuoyebang.cn", "sha256//89KpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRh00L=").add("api.zuoyebang.com", "sha256//a8za0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1o=09").build()builder.apply certificatePinner(pinners)return builder.build()

  • 该方案优点和缺点分析说明

  • 优点:安全性高,配置方式也比较简单,并能实现动态更新配置。

  • 缺陷:网络安全配置无法实现证书证书的动态更新,另外该配置也受Android系统影响,对7.0以前的系统不支持。代码配置相对灵活些。

  • 破解:证书锁定破解比较复杂,比如老牌的JustTrustMe插件,通过hook各网络框架的证书校验方法,替换原有逻辑,使校验失效

4.8 Sign签名

  • 先说一下背景和问题

  • 这种方式简单粗暴,通过调用getbanner方法即可获取轮播图列表信息,但是这样的方式会存在很严重的安全性问题,没有进行任何的验证,大家都可以通过这个方法获取到数据,导致产品信息泄露。

  • 在写开放的API接口时是如何保证数据的安全性的?

  • 请求来源(身份)是否合法?请求参数被篡改?请求的唯一性(不可复制)?

  • 问题的解决方案设想

  • 解决方案:为了保证数据在通信时的安全性,我们可以采用参数签名的方式来进行相关验证。

  • 最终决定的解决方案

  • 调用接口之前需要验证签名和有效时间,要生成一个sign签名。先拼接-后转码-再加密-再发请求!

  • sign签名校验实践

  • 需要对请求参数进行签名验证,签名方式如下:key1=value1&key2=value2&key3=value3&secret=yc 。对这个字符串进行md5一下。

  • 为什么在获取sign的时候建议使用secret参数?secret仅作加密使用,添加在参数中主要是md5,为了保证数据安全请不要在请求参数中使用。

  • 服务端对sign校验

  • 这样请求的时候就需要合法正确签名sign才可以获取数据。这样就解决了身份验证和防止参数篡改问题,如果请求参数被人拿走,没事,他们永远也拿不到secret,因为secret是不传递的。再也无法伪造合法的请求。

  • 如何保证请求的唯一性

  • 通过stamp时间戳用来验证请求是否过期。这样就算被人拿走完整的请求链接也是无效的。

  • Sign签名安全性分析:

  • 通过上面的案例,安全的关键在于参与签名的secret,整个过程中secret是不参与通信的,所以只要保证secret不泄露,请求就不会被伪造。

05.架构设计说明

5.1 整体架构设计

  • 如下所示

5.2 关键流程图

5.3 稳定性设计

  • 对于请求和响应的数据加解密要注意

  • 在网络上交换数据(网络请求数据)时,可能会遇到不可见字符,不同的设备对字符的处理方式有一些不同。

  • Base64对数据内容进行编码来适合传输。准确说是把一些二进制数转成普通字符用于网络传输。统统变成可见字符,这样出错的可能性就大降低了。

5.4 降级设计

  • 可以一键配置AB测试开关

.setMonitorToggle(object : IMonitorToggle 
    overridefunisOpen(): Boolean 
        //todo 是否降级,如果降级,则不使用该功能。留给AB测试开关returnfalse
    
)
复制代码

5.5 异常设计说明

  • base64加密和解密导致错误问题

  • Android 有自带的Base64实现,flag要选Base64.NO_WRAP,不然末尾会有换行影响服务端解码。导致解码失败。

5.6 Api文档

  • 关于初始化配置

NotCaptureHelper.getInstance().config = CaptureConfig.builder()
        //设置debug模式
    .setDebug(true)
        //设置是否禁用代理
    .setProxy(false)
        //设置是否进行数据加密和解密,
    .setEncrypt(true)
        //设置cer证书路径
    .setCerPath("")
        //设置是否进行CA证书校验
    .setCaVerify(false)
        //设置加密和解密key
    .setEncryptKey(key)
        //设置参数
    .setReservedQueryParam(OkHttpBuilder.RESERVED_QUERY_PARAM_NAMES)
    .setMonitorToggle(object : IMonitorToggle 
        overridefunisOpen(): Boolean 
            //todo 是否降级,如果降级,则不使用该功能。留给AB测试开关returnfalse
        
    )
    .build()
复制代码
  • 设置okHttp配置

NotCaptureHelper.getInstance().setOkHttp(app,okHttpBuilder)
复制代码
  • 如何设置自己的加解密方式

NotCaptureHelper.getInstance().encryptDecryptListener = object : EncryptDecryptListener 
    /**
     * 外部实现自定义加密数据
     */overridefunencryptData(key: String, data: String): String 
        LoggerReporter.report("NotCaptureHelper", "encryptData data : $data")
        val str = data.encryptWithRC4(key) ?: ""
        LoggerReporter.report("NotCaptureHelper", "encryptData str : $str")
        return str
    
    /**
     * 外部实现自定义解密数据
     */overridefundecryptData(key: String, data: String): String 
        LoggerReporter.report("NotCaptureHelper", "decryptData data : $data")
        val str = data.decryptWithRC4(key) ?: ""
        LoggerReporter.report("NotCaptureHelper", "decryptData str : $str")
        return str
    

复制代码

5.7 防抓包功能自测

  • 网络请求测试

  • 正常请求,测试网络功能是否正常

  • 抓包测试

  • 配置fiddler,charles等工具

  • 手机上设置代理

  • 手机上安装证书

  • 单向认证测试:进行网络请求,会提示SSLHandshakeException即ssl握手失败的错误提示,即表示app端的单向认证成功。

  • 数据加解密:进行网络请求,看一下请求参数和响应body数据是否加密,如果看不到实际json实体则表示加密成功。

防抓包库:github.com/yangchong21…

综合库:github.com/yangchong21…

视频播放器:github.com/yangchong21…

以上是关于App防抓包的四种绕过方法(详细)的主要内容,如果未能解决你的问题,请参考以下文章

Android逆向之http/https网络抓包

httpanalyzerstdv7怎么抓包

iOS 绕过SSL认证抓包(需越狱)

如何用Fiddler对Android应用进行抓包

防抓包(证书攻击)策略-iOS

移动端防抓包实践