TL;DR

Lý do mình viết bài này là do mình đã viết blog về cách bypass SSL Pinning cho Flutter application trên hệ điều hành Android, nên đã lỡ viết bypass cho Android thì viết nốt iOS cho có đôi có cặp, hehe :v

  • Giới thiệu

Mình xin nhắc lại mấy ý trong bài viết trước như sau:

Phần lớn các mobile app hiện nay dùng các framework như Flutter hoặc React Native, có thể vừa buid android và iOS applications với cùng một codebase. Đặc biệt là thằng Flutter này không tuân theo cấu hình proxy của thiết bị được cài đặt bởi pentester mà sẽ sử dụng certificate của lập trình viên cài đặt. Do đó, không thể bắt được request theo cách thông thường được.

Thông tin thêm cho bạn nào tìm hiểu về thư viện BoringSSL mà Flutter apps sử dụng để áp dụng cho TLS connection.

Dưới đây, là hai cách mình dùng để bypass SSL Pinning cho nền tảng iOS.

  • Sử dụng reFlutter

Hiện nay có tool reFlutter cho phép bypass SSL Pinning và ý tưởng của tool này khá đơn giản như sau: vì Flutter app thường sử dụng binary (libflutter.so bao gồm các Flutter engine) đã được complied (ahead-of-time – AOT), vậy nên tool này chỉ cần sử dụng bản patch của Flutter library đã được complied sẵn, sau đó re-packing app là ok. Nhưng sẽ có vấn đề xãy ra là nếu version Dart khác nhau sẽ không thể hoạt động được.

Cài đặt 

# Linux, Windows, MacOS

pip3 install reflutter==0.7.2

Cách sử dụng

reflutter your_app.ipa

 

Cài đặt IPA file sau khi thực hiện reFlutter ở trên với 3uTools hoặc appinst với command appinst your_app.ipa (thiết bị đã jailbreak)

Tiếp theo, cần cấu hình trên Burp Suite theo đúng hướng dẫn của reFlutter framework như hình phía trên nhé

 

Chuyển qua Request Handling Tab

  • Sử dụng OpenVPN Server bắt http request

Qua đọc blog của các tiền nhân thì có nhiều cách để bypass SSL Pinning, trong đó có 2 cách thông dụng nhất là:

    • Sử dụng WIFI adapter và iptable command để chuyển hướng tất cả request đến Burp Suite
    • Sử dụng OpenVPN server.

Đối với bản thân thì cảm thấy rằng sử dụng OpenVPN server là cách thuận tiện nhất vì không phải lúc nào cũng có WIFI adapter sẵn ngay cạnh, nên bài viết này sẽ chỉ trình bày cách thứ 2 thôi (Sử dụng OpenVPN server). Bạn nào muốn tìm hiểu thêm thì đọc blog ở đây nhé

Sử dụng script này để thực hiện cài đặt cho OpenVPN server trên Kali (dùng Kali cho tiện).

Để cài đặt được trên Kali thì phải xóa câu lệnh exit trong phần kiểm tra Debian version.

wget https://git.io/vpn -O openvpn-install.sh

sed -i “$(($(grep -ni “debian is too old” openvpn-install.sh | cut  -d : -f 1)+1))d” ./openvpn-install.sh

chmod +x openvpn-install.sh 

sudo ./openvpn-install.sh

(Nếu các command ở trên không hoạt động thì thực hiện thủ công nhé.)

Sau khi thực hiện command trên, việc cài đặt sẽ được thực hiện và chúng ta chỉ cần cấu hình lại cho phù hợp nha

This server is behind NAT. What is the public IPv4 address or hostname?

Public IPv4 address / hostname [14.177.136.222]: 192.168.1.22

 

Which protocol should OpenVPN use?

   1) UDP (recommended)

   2) TCP

Protocol [1]: 1

 

What port should OpenVPN listen to?

Port [1194]: 1194

 

Select a DNS server for the clients:

   1) Current system resolvers

   2) Google

   3) 1.1.1.1

   4) OpenDNS

   5) Quad9

   6) AdGuard

DNS server [1]: 3

 

Enter a name for the first client:

Name [client]: pentest

Script trên sẽ cài đặt, cấu hình mọi thứ cần thiết. Giờ bạn thực hiện command ifconfig bạn sẽ thấy tun0 interface đã được cấu hình

Thực hiện cấu hình iptable để bắt traffic từ OpenVPN interface đến eth0 interface

sudo iptables -t nat -A PREROUTING -i tun0 -p tcp –dport 80 -j REDIRECT –to-port 8080

sudo iptables -t nat -A PREROUTING -i tun0 -p tcp –dport 443 -j REDIRECT –to-port 8080

sudo iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE

Thực hiện tải file cấu hình VPN về thiết bị iOS bằng cách sau

Trên máy kali tạo python server port  80

python3 -m http.server 80

 

Trên thiết bị iOS truy cập với địa chỉ và port tương ứng: http://192.168.1.22:80, thực hiện download file pentest.ovpn

 

Khởi động OpenVPN service

sudo service openvpn start

hoặc

sudo systemctl status openvpn

Tiếp theo, cài đặt OpenVPN client ở iphone

 

Cài đặt file cấu hình

 

 

 

 

Cuối cùng, bật Burp Suite lắng nghe port 8080 (trên máy Kali nha)

Lúc này bạn sẽ bắt được tất cả các http request từ Flutter app, đôi khi các ứng dụng sử dụng https thì sao?? làm tiếp theo các bước phía dưới chứ sao …

 

  • Bắt HTTPS request

Giờ bạn đã thực hiện Man-in-the-middle với http request, phần này sẽ tiếp tục thực hiện với HTTPS request. 

Như đã nói Flutter app sử dụng thư viện BoringSSL để áp dụng cho TLS connection mà không sử dụng bất kỳ thư viện mặc định của iOS nên SSLKillSwitch không dùng được trong trường hợp này. Để thực hiện được mục đích là bắt HTTPS request, chúng ta cần thực hiện:

    • Lấy được Flutter binary
    • Import vào Ghidra
    • Tìm đúng method để hook bằng Frida

Đầu tiên, bạn phải lấy được file Flutter framework file từ thiết bị, mà điều này phụ thuộc vào cách ứng dụng được cài đặt (SSH vào thiết bị iOS để thực hiện các command)

Nếu ứng dụng được cài từ ipa file: (nhớ cài đặt ipa installer trong cydia nhé)

ipainstaller -b <package_name>

 

Nếu ứng dụng được cài đặt từ App Store thì dùng Clutch:

Clutch -d <package_name>

Sau bước trên lấy được ipa file từ thiết bị iOS, và nằm ở đường dẫn sau: /private/var/mobile/Documents/flutter_app (be.nviso.flutterApp) v1.0.0.ipa 

Tiếp tục thực hiện các command sau:

# Unzip the ipa file

unzip flutter_app.ipa

# Find the Flutter binary

file Payload/Runner.app/Frameworks/Flutter.framework/Flutter

 

Thực hiện các command sau để tìm kiến trúc của thiết bị (nhớ cài đặt Darwin CC Tools trong cydia nhé)

lipo -thin arm64 Flutter -output FlutterThin

file FlutterThin

 

Sau khi có được thư viện của ứng dụng, tiếp tục bước tiếp theo là import vào Ghidra và tìm chuỗi bytes đầu bắt đầu của hàm session_verify_cert_chain mà trong blog trước mình đã nhắc đến (chưa đọc thì đọc ủng hộ luôn nhé :v)

Mục đích của việc tìm chuỗi bytes này là dùng Frida hook vào hàm session_verify_cert_chain và chỉnh sửa giá trị theo ý muốn.

Import file FlutterThin vào Ghidra (Import này lâu vãi chưởng, tranh thủ thời gian này đi pha cốc cafe uống cho tỉnh táo :v), đợi quá trình import xong thì click Search -> For Strings… tìm ssl_x509.cc sẽ nhận được kết quả như hình bên dưới

 

Double click vào XREF[9] sẽ hiển thị như hình dưới

 

Lúc này phải duyệt qua tất cả các Xrefs để tìm được function có 3 arguments và return 0

 

Như hình dưới thì FUN_004068C8 chính là hàm mà chúng ta đang tìm kiếm

 

 

Chuối bytes đầu tiên của hàm FUN_004068C8 là 

ff 03 05 d1 fc 6f 0f a9 f8 5f 10 a9 f6 57 11 a9 f4 4f 12 a9 fd 7b 13 a9

 

Có thể sử dụng tool binwalk để xác định được chính xác offset

Đến đây thì rồi thì dùng Frida script để bypass SSL Pinning thôi (đoạn code dưới được tham khảo ở (1))

function hook_ssl_verify_result(address)
{
Interceptor.attach(address, {
onEnter: function(args) {
console.log("Disabling SSL validation")
},
onLeave: function(retval)
{
retval.replace(0x1);
}
});
}
function disablePinning()
{
var pattern = "Inject here"
Process.enumerateRangesSync('r-x').filter(function (m)
{
if (m.file) return m.file.path.indexOf('Flutter') > -1;
return false;
}).forEach(function (r)
{
Memory.scanSync(r.base, r.size, pattern).forEach(function (match) {
console.log('[+] ssl_verify_result found at: ' + match.address.toString());
hook_ssl_verify_result(match.address);
});
});
}
setTimeout(disablePinning, 1000)
  • Tham khảo
    • https://blog.nviso.eu/2020/06/12/intercepting-flutter-traffic-on-ios/ (1)
    • https://sec.vnpt.vn/2022/04/frida-hooking-va-bypass-ssl-pinning-cho-flutter-aplication/ (2)

ndtoan

2.434 lượt xem