正常安卓网络请求
用我们之前写的 第一个 APP 把 click 动作替换为以下代码,这段代码将访问 www.android.com 并把他的网页前端代码显示在 APP 页面上
publicvoidonClick(View v){ ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(()->{try { URL url = new URL("http://www.android.com/"); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); InputStream in = new BufferedInputStream(urlConnection.getInputStream()); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder sb = new StringBuilder(); String line;while ((line = reader.readLine()) != null) { sb.append(line).append('n'); } String result = sb.toString(); runOnUiThread(() -> homeText.setText(result)); } catch (Exception e) { e.printStackTrace(); } });}
但是当你运行时会发现没有任何响应,查看 logcat 会发现其实是你请求的是 HTTP,安卓默认要求你使用 HTTPS 而不是明文的 HTTP,因此修改源码中的 http 为 https
再次运行仍然没有效果,此时再查看 logcat 会发现提示为没有联网的权限
APP 的权限管控是在 AndroidManifest.xml 中添加的,因此添加联网的权限如下
再次编译 APP 请求,还是请求不到,感觉是国内网络的问题,换成 baidu.com 就成功了...
但是换成 http 还是没有权限,难道不能请求 http 吗
当然不是,只需要在权限中添加一句使用明文传输就好啦
android:usesCleartextTraffic="true"
其实也可以使用 socket 直接请求,这样就能避免明文传输权限的声明了,但是网络权限还是要有的
publicvoidonClick(View v){ ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(()->{try { Socket socket = new Socket("www.baidu.com",80); OutputStream outputStream = socket.getOutputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String request = "GET / HTTP/1.1rnHost: www.baidu.comrnUser-Agent: apprnAccept: */*rnrn"; outputStream.write(request.getBytes()); outputStream.flush(); StringBuilder sb = new StringBuilder(); String line;while ((line = reader.readLine()) != null) { String finalLine = line; runOnUiThread(()->homeText.append(finalLine)); } String result = sb.toString(); } catch (Exception e) { e.printStackTrace(); } });}
使用 tcpdump 记录数据包
该 APP 使用明文的方式传输 flag,使用 tcpdump 抓取通信流量找到 flag 【附件可阅读原文语雀下载】
如果是在真实设备上,直接 push 一个对应架构的静态编译 tcpdump,然后在 adb shell 中运行即可,在模拟器上想体验一下 tcpdump 抓包方式的话需要找到模拟器的安装路径,指定好使用哪个虚拟机运行
C:UsersxxxAppDataLocalAndroidSdkemulatoremulator.exe -tcpdump 1.cap -avd Pixel_7_API_30
使用 adb install 将 app 安装到模拟器后,点击运行,随便点点,然后关掉模拟器,用 wireshark 打开流量包,过滤 http 协议,得到 flag
使用 burp 抓包
首先需要给安卓配置代理,在设置中找到 WiFi,点击编辑按钮
配置代理为手动,IP 设置为 burp 主机所在的 IP 地址,并在 burp 中配置代理
再打开上次的软件,可以看到 HTTP 请求与返回结果,同时 burp 还支持中间人攻击,自动替换匹配的字符串,例如现在页面
我们可以设置规则把 Seychelles 替换成 Hacked_BY_yichen
这样再次打开软件就会发现文字变化了
使用 burp 抓 HTTPS 包
安装用户证书(安卓6-)
在 Android 6(API 级别 23)或更低版本中信任用户证书的,因此可以直接安装 burp 的证书就能抓包了,在手机浏览器访问 burp 的代理,点击 CA Certificate 下载 CA 证书,下载后在设置中搜索 CA 找到 CA 证书安装页面安装
安装系统证书(安卓7~13)
在高版本安卓中是不认 cer 证书的,可以用 openssl 转换为 pem 证书,然后同样的安装步骤
openssl x509 -inform DER -in .cacert.der -out .cacert.pem
安装完成证书后发现就可以抓取某些 app 的 HTTPS 包,例如我通过 chrome 访问百度可以看到是走的 HTTPS 协议
但是如果你换一个 APP 就会发现又抓不到了,这是因为 chrome 这个应用程序的 xml/network_security_config.xml 中同时信任了 user 和 system 证书
安卓 7 及以上版本,默认的配置下大部分 APP 只会信任系统证书,因此需要把 burp 的证书安装到系统证书中,但是这需要 ROOT 权限,如果你没有真实设备,也可以用不带 Google APIs 的系统镜像模拟器来操作(Default Android System Image)
只需要 adb root 即可
然后按照前面的步骤安装证书到 User 证书
接下来使用 root 权限进入 adb,首先看一下我们安装的用户证书,路径为:
/data/misc/user/0/cacerts-added/
可以看到有一个名为 9a5ba575.0 的证书,查看该证书内容包含 PortSwigger 可确认就是 burp 的证书
再来看一下系统证书,路径为:
/system/etc/security/cacerts/
那我们能够通过 root 权限将用户证书拷贝到系统证书目录吗,答案是不行的,提示:Read-only file system
接下来通过一个小 trick 来完成这一操作,首先备份系统证书到用户证书目录下
cp /system/etc/security/cacerts/* /data/misc/user/0/cacerts-added/
此时用户证书下应该有所有系统和用户证书,在设置中查看也是如此
然后执行以下命令,在系统证书文件夹顶部创建内存挂载
mount -t tmpfs tmpfs /system/etc/security/cacerts
这时候查看系统证书文件夹里面是空的,从用户证书文件夹拷贝过来
cp /data/misc/user/0/cacerts-added/* /system/etc/security/cacerts/
但此时仍然无法被系统识别,需要再给他们配置好权限等
# Fix any permissions & selinux context labelschown root:root /system/etc/security/cacerts/*chmod 644 /system/etc/security/cacerts/*chcon u:object_r:system_file:s0 /system/etc/security/cacerts/*
然后你就可以在系统证书处找到 burp 的证书了,可以愉快的抓各种 HTTPS 啦
安装系统证书(安卓14~?)
安卓 14 以上的版本又改了证书机制,即使是 root 也不能随便去修改了,参考 httptoolkit 的文章:
https://httptoolkit.com/blog/android-14-install-system-ca-certificate/#how-to-install-system-ca-certificates-in-android-14
首先还是正常安装证书,然后把下面的脚本 push 到系统目录(注意保存的时候要以 Unix 换行形式)
然后直接赋予执行权限执行即可,再新一点的版本没有试过了
其他拦截截技巧
使用 apktool 修补网络安全配置
通过 apktool 解包之后修改 network_security_config.xml 配置,学 chrome 那样添加上信任用户证书,这样就可以在不 root 的情况下直接添加用户证书来抓包了
高级 VPN HTTP 拦截
虽然我们可以在 WiFi 连接的时候设置代理,但是有些 APP 可以通过代码中设置 Proxy.NO_PROXY 以忽略系统代理,以 Github 上这位师傅写的示例来看(https://github.com/act0rn/https-capture),当在代码中设置了 Proxy.NO_PROXY 时就不会走代理了,这时候就抓不到包了
这时候可以通过 VPN 直接重定向流量,例如 rethink-app
https://github.com/celzero/rethink-app
然后在设置 APP 中的 DNS 为系统 DNS
这时候就正常抓到了
DNS 欺骗和透明代理
首先下载 docker 镜像:docker pull andyshinn/dnsmasq
,然后启用 docker 容器
docker run --name my-dnsmasq --rm -it -p 0.0.0.0:53:53/udp -v dnsmasq.conf:/etc/dnsmasq.conf andyshinn/dnsmasq
修改 dnsmasq.conf 为下面的配置文件
address=/baidu.com/192.168.2.16log-queries
然后设置 rethink APP DNS 为 docker 的服务
这时候用 chrome 去查看 dns(chrome://net-internals)已经生效了
接下来在 burp 中设置监听 80 和 443 端口透明代理,启用透明代理后 Burp 将充当一个真实的网络服务器,监听端口 80 和 443。它将接收传入的 HTTP 请求,查看 HOST 头,并相应地转发它们
最后效果如下,同样可以实现抓包
示例:PocketHexMap
接下来做一个示例挑战【附件可阅读原文语雀下载】,通过 HTTP 中间人 + 路径穿越漏洞 让 APP 下载一个 hax 文件到指定路径下
/data/media/0/Android/data/io.hextree.pocketmaps/files/Download/pocketmaps/downloads/hax
通过 jadx 逆向,发现该 APP 允许明文传输
妈的,连不上外网... 他是从谷歌的一个什么存储上下载的,有时候能下载成功,有时候访问不到... 就先不用 burp 抓包了,让我来操作一番
首先在自己电脑上开 clash 代理,然后电脑开一个热点,手机连接热点后把手机 WiFi 的代理设为 clash 的 7890 端口,这样起码就能访问的到目标服务器了,然后用 wireshark 抓包先看看流程,可以看到当我下载 Nauru 这个地图时,下载的文件名其实是:australia-oceania_nauru.ghz
而且是明文的,也就是说,我可以在我自己的电脑上起一个 HTTP 的服务,然后把 storage.googleapis.com 的 hosts 改成电脑的 IP,这样一来它下载的就是我的电脑上的文件了
还需要注意的是在应用一启动的时候会访问一个 json 文件,也要配置好:map_url-0.13.0_0.json 这直接复制之前的内容即可
{"maps-0.13.0_0-path": "maps","hextree-flag": "HXT{cleartext-traffic-g19g2is}","maps-0.13.0_0": [ { "name": "australia-oceania_wallis-et-futuna", "size": "812K", "time": "2024-02" }, { "name": "australia-oceania_niue", "size": "684K", "time": "2024-02" }, { "name": "australia-oceania_nauru", "size": "500K", "time": "2024-02" }, { "name": "europe_monaco", "size": "752K", "time": "2024-02" }, { "name": "africa_seychelles", "size": "3.4M", "time": "2024-02" }, { "name": "africa_sao-tome-and-principe", "size": "1.6M", "time": "2024-02" } ]}
那么怎么把 hax 文件下载到指定路径下面呢,先来看看我们的文件下载到了哪里,如果前面你注意一下 wireshark 的流量就会发现,下载的 ghz 其实是个压缩包,这个目录就是压缩包解压出来的内容
然而还是不知道该怎么把 hax 放在目标目录呀,怎么办呢,再来分析一下 apk 吧,看看他是如何处理压缩包的,代码中通过 nextEntry.getName() 获得解压后的文件名,直接拼接到目标目录路径下,未对文件名进行严格的过滤和验证。如果构造一个包含 “../” 的特殊文件名,可能会导致解压后的文件被放置在目标目录之外的其他位置,从而引发路径遍历漏洞
因此修改我们的压缩包,其中放置一个文件名为:../../downloads/hax
的文件,然后下载即可
import zipfilewith zipfile.ZipFile(file='australia-oceania_nauru.ghz',mode='w') as zipf: zipf.writestr("../../downloads/hax",'hello yichen')
然而我只成功下载了一次,后面不管怎么重启手机、重装 APP 都只会访问到 json 文件,不会访问压缩包路径了... 后来手机电脑全部重启了一下又好了
原文始发于微信公众号(陈冠男的游戏人生):【安卓安全】安卓网络抓包技巧
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论