HTTP抓包在WEB开发和数据分析中经常用到。Wireshark可以完整地抓住网络层的数据包,可惜使用HTTPS的无法解析,都是乱码。
一、PC端浏览器
这个问题其实好解决,Chrome可以直接打开开发者工具,查看所有的URL、HTTP头和响应。这是最简单的方法。
二、Wireshark抓包
如果想通过捕获HTTPS包后解密是困难的——加密机制的目的就是让人不能非法解密。而浏览器与服务器之间协商生成数据密钥时,浏览器用服务器提供公钥加密,服务器用自己的私钥解密,因此尽管捕捉了所有数据包,如果无法计算出用于加密数据的密钥,数据也就无法解密。这个密钥,要么直接从浏览器内获取,要么取得服务器的私钥。
不过CHrome等浏览器提供了获取密钥的办法——对于浏览器来说,是不是因为网页源代码都已经毫无保留地提供了,所以这个密钥在调试时是可以提供的。设置办法是增加一个环境变量:
在电脑的 设置——高级系统设置——环境变量——用户变量——新建:变量名 SSLKEYLOGFILE 变量值:d:\log\sslkey.log(提前建立好文件夹和一个空文件)
这样,在浏览器访问HTTPS网站,会记下一系列的值。
然后,在Wireshark中,编辑——首选项(Preference)——Protocols——SSL(或TLS,任一),然后在右边的(Pre)-Master-Secretlog filename 中填入刚才的密钥文件d:\log\sslkey.log
这样在浏览器访问时,WIreshark中捕获的数据包也会解码,可以看到正常的URL数据了。
如果HTTPS不是通过PC浏览器访问的,比如QQ、微信APP,手机浏览器,因为无法记录浏览器的私钥,上面的办法就无效了。
三、Fiddler 或 Charles这类代理抓包软件
1、安装软件
从https://www.telerik.com/download 下载安装 https://downloads.getfiddler.com/win/Fiddler%20Everywhere%205.2.0.exe
这个是10天免费试用版,第一次使用要注册、登录。
软件运行后,点右上角的设置。
首先,检查HTTPS:将Capture HTTPS CONNECTs打上V ,将Ignore server certificate errors也打上V.
其次,检查Connections:填写代理服务端口:8866。这个后面手机连接WIFI时要填写代理服务器,就是这个端口。再将from remote clients only等打上V。注意设置后,要及时“SAVE”
这样,代理设置和抓包软件就准备好了。
2、配置手机
手机要与PC在同一网段,检查手机连接的WIFI的IP。并长按WIFI连接,修改网络:设置代理为手动,服务器主机名为PC的IP地址,服务器端口为Fiddler设置的代理端口8866.
然后,要安装Fiddler的根证书:在手机浏览器中打开网址 http://PC的IP:8866 根据提示,最下面一行,是下载证书,然后在手机设置中搜索 CA证书。打开安装CA证书,选择刚才下载的证书文件:FiddlerRoot.crt
这样,手机浏览器的访问会通过Fiddler代理,而Fiddler会作为中介来中转,因而服务器数据实际是发给Fiddler的,当然也是可以解密的。
3、部分APP不使用系统代理的问题
测试中手机浏览器的访问的确是在Fiddler中有了记录,可以看到URL。当然,手机会有证书问题的提示。特别是像百度网站,反复提示,不能正常打开——这是那个自己安装的根证书的问题。
而像支付宝等APP,在Fiddler中没有任何记录,而用Wireshark抓包也是没有记录。先前用PC作为手机热点,用Wireshark是可以捕获到数据包的。
原因:在手机网络设置代理后,一般情况下,浏览器等APP在进行http请求时,会检查系统代理,如果设置了代理,APP直接使用完整uri去连接代理服务器。但像支付宝这样的,它可能并不理会系统设置的代理,而是直接访问服务器。这样,数据并不经过代理服务器,Fiddler上就没有记录了。
可能的解决办法 :使用V**将终端设备的流量转发到代理服务器
首先,要在手机上安装一个V**,如 drony (下载:https://files.cnblogs.com/files/lulianqi/Drony_102.apk,说明 https://github.com/SuppSandroB/sandrop/wiki/Drony-FAQ),drony会在你的手机上创建一个V**,将手机上的所有流量都重定向到drony自身(不是流向V**服务器) ,这样drony就可以管理所有手机上的网络流量,甚至可以对手机上不同APP的流量进行单独配置。
其次,在手机上打开Drony(处于OFF状态),滑动到SETING页,点击选择Networks Wi-Fi 进入配置,在网络列表中选择点击当前手机wifi连接的网络 (需要确保该网络与Fiddler代理服务器网络是联通的)
配置要为当前网络使用的代理入口(这里直接填写fiddler代理地址就可以),选择代理模式为手动(Manual)
注意Proxy type代理方式要选择 Plain http proxy
Filter default value 选择 Direct all ,然后点击下面的Rule设置应用规则
在Network id处 选择当前wifi的SSID
Action 选择 Local proxy chain
Application 选择需要强制代理的APP
Hostname 及 Port 不填 表示所有的都会被强制代理,因为APP可能会使用其他的网络协议不一定都是http,可能不希望把所有流量都引流到http代理服务器,这个时候就会使用这个配置指定ip及端口才转发
完成后保存即可,然后返回到SETTING主页,滑动到LOG页,点击下面按钮,使其处于ON的状态(表示启用)
4、关于CA证书校验的问题
无论Fiddler 或 Charles都使用中间人攻击的方式替换tls链路证书,解密报文然后再加密发送给真实服务器。
不过由于证书的存在,client会校验证书的合法性,然后决定是否连接服务器。我们使用Fiddler或Charles抓取https前在设备中安装根证书正是为了通过client的证书校验。
Filddler没有这些证书里公钥对应的私钥(CA只会把为完整颁发的证书对应的私钥给网站的所有者),所以没有办法与客户端完成TLS握手。Filddler为了完成握手只能自己为不同的站点生成证书,
不过自己的生成的证书肯定是用自己的私钥签名的,客户端在自己信任的CA公钥列表找不到对应根证书,肯定是不能通过证书校验的。所以Filddler要求我们安装他的根证书到设备,这样自己签发的证书就可以通过证书校验,自己就能解密https报文了。
不能解密的原因
其实通过上面的描述也很明白了不能正常建立连接解密https报文的原因就是证书校验失败,我们的根证书安装不够完全。
从Android7.0以后,系统允许每个应用可以定义自己的可信CA集。有部分应用默认只会信任系统预装的CA证书,而不会信任用户安装的CA证书(或者说是应用使用的开发框架默认只信任系统证书,因为开发者通常不关心这些配置,也不会去更改他)。而在Android中用户安装的证书都是用户证书,所以无论是Filddler还是Charles我们都只是把他们的根证书安装到了用户证书,这些应用并不使用他们,所以我们的安装的证书是无效的。
解决方法及操作方法
既然又知道了原因,那就总还是有办法去解决的。我们只要把代理软件的根证书安装成系统证书就可以了。
实际上将证书安装到系统区操作还是相对简单的,将证书用指定的名称放到指定的位置(/system/etc/security/cacerts/)就可以了
先将我们的根证书名称改为<Certificate_Hash>.<Number>
Certificate_Hash表示证书文件的hash值,Number是为了防止证书文件的hash值一致而增加的后缀(用0就行了)
下载自己的根证书FiddlerRoot.cer,使用openssl x509 -subject_hash_old -in <Certificate_File> 计算证书hash ,根据hash将证书重命名为 269953fb.0 (269953fb是笔者证书的hash,大家的肯定不一样)
然后将269953fb.0文件复制到/system/etc/security/cacerts/
完成后我们就可以看到代理软件的证书出现在系统区了。
这里还有一点需要单独说明,/system/etc/security/cacerts/目录的写权限,需要手机root权限。
也就是说复制证书到该目录需要您root自己的设备。