--- Bài mới hơn ---
Top 4 Ứng Dụng, Phần Mềm Hack Tiền Game Android Tốt Nhất 2022
Làm Thế Nào Để Có Tiền Vô Hạn Trong Sim ▷ ➡️ Điểm Dừng Sáng Tạo ▷ ➡️
Hack Tiền Tiến Lên Zingplay Cực Đơn Giản Hiệu Quả 100%
Crab War Hack V3.31.0 Full Tiền (Mod Rất Nhiều Money)
European War 6: 1914 Apk
TL;DR: Mình phát hiện ra một lỗ hổng trong bộ API của một nhà mạng cho phép nạp tiền vào bất cứ số điện thoại nào của nhà mạng đó mà không cần thanh toán.
Mở đầu
Nói ví dụ về game cho các bạn dễ hiểu. Bài writeup của mình cũng về vấn đề “hack tiền”, nhưng thứ mà mình lấy được là tiền trong tài khoản điện thoại. Cũng là những mơ mộng ấy, cũng cảm giác hồi hộp như vậy, và với mình là cảm giác vui mừng khi thành công cũng như hào hứng khi được chia sẻ những dòng này, và hi vọng rằng những phát hiện của mình sẽ không làm bạn thất vọng.
Vì mục đích bảo mật và cũng để phân biệt với lỗ hổng trước đó mà mình tìm được (https://goo.gl/f83SAn), nên mình sẽ gọi bên công ty này là “Y”. Tất cả tên gọi trong bài viết cũng như trong ảnh đều sẽ sử dụng tên này.
Lỗ hổng của Y nằm ở đâu?
Lỗ hổng của Y nằm trong bộ API của ứng dụng Android, khá giống với lỗ hổng của X mình đã đề cập ở trên. Tuy nhiên, vì app của Y bảo mật hơn (theo mình đoán là có SSL Pinning) nên mình không thể dùng Fiddler để capture request theo cách thông thường mà phải dịch ngược mã nguồn để phân tích.
Quá trình dịch ngược ứng dụng của Y
Để dịch ngược ứng dụng của Y, trước hết mình cần một bản apk của ứng dụng, có thể tìm một cách dễ dàng trên các trang lưu trữ như apkpure, còn cách mình hay dùng là pull trực tiếp từ Android thông qua adb.
Việc đầu tiên mình thường làm sau khi có apk đó là sử dụng 2 công cụ dex2jar và jd-gui để dịch ngược mã nguồn của ứng dụng về code Java, sau đó nghiên cứu những phần code chức năng để tìm ra lỗ hổng.
Sau khi dịch ngược ứng dụng của Y, mình được một cấu trúc thư mục mã nguồn như thế này:
Theo kinh nghiệm bản thân, mình tìm kiếm mã nguồn trong thư mục com/y/, tuy nhiên trong thư mục này chỉ gồm một file chúng tôi vốn chỉ để chứa thông tin. Mình cũng đã đọc hết file này và y rằng không tìm được đoạn code nào có vẻ có giá trị :(.
Sau khi lục tung hết mấy thư mục mã nguồn mà không có kết quả, mình đoán rằng cần phải tiếp cận vấn đề này theo một hướng khác. Và đó cũng chính là lúc mình bắt đầu để ý đến từ khóa xamarin. Vì trước đó đã từng đọc qua nên mình biết Xamarin là một nền tảng cho phép lập trình ứng dụng di động bằng ngôn ngữ C# của .NET framework. Mình thì chỉ nhớ mấy thư viên của C# có phần mở rộng .dll thôi, nên là quyết định quay lại tìm xem trong apk có file .dll nào không.
Vì file .apk thực chất cũng chỉ là một file nén, nên mình đổi định dạng lại thành .zip và giải nén, mình lại được một cấu trúc thư mục thế này:
Mở thư mục assemblies, được một nùi file .dll thế này. Mình thì chú ý đến file Y.dll.
Để dịch ngược file .NET chúng ta cũng cần chơi theo kiểu .NET. Vì vậy mình dùng Telerik JustDecompile để mở và phân tích file Y.dll.
Đầu tiên, trong file .dll này, mình tìm được một hàm khai báo base API của server
Từ hàm này mình biết được một số thông tin như:
Và để biết cụ thể ứng dụng tương tác với server thế nào thì mình cần tìm thêm các hàm gọi API.
Trong file .dll vừa mở, mình tiếp tục tìm được một class có tên AccountService mà thông qua tên các hàm xử lý (Register, Login, ResetPassword, GetProfile), mình đoán class này có nhiệm vụ xử lý các tác vụ trên tài khoản như đăng ký, đăng nhập, đặt lại mật khẩu,…
Đây là phần code xử lý của class nói trên:
- Ứng dụng này giao tiếp với server qua HTTP requests.
- Định dạng dữ liệu JSON.
- Base API của server là https://y.com.vn/api/.
Từ đây, mình bắt đầu thử tạo ra một request hợp lệ tới server. Ví dụ từ hàm login:
Mình biết được một số thông tin như sau:
Cộng với việc biết base API và định dạng dữ liệu JSON, mình xây dựng được một request thế này:
Và qua việc đăng nhập thử mình biết được định dạng request như trên của mình là hợp lệ, và nếu thông tin đăng nhập đúng thì server trả về một số thông tin tài khoản như thế này:
- Method của request là POST
- Path là login/
- Request body gồm loginId và password
Sau khi biết cách tạo request đến server, mình tiếp tục để ý đến 2 hàm sau:
Hàm đầu tiên mình đoán có tác dụng gọi API để nạp thẻ, với msisdn là số điện thoại cần nạp và voucherCode là mã thẻ, và Settings.CurrentUser.Msisdn là số điện thoại của tài khoản hiện tại (trong trường hợp bạn nạp thẻ cho một tài khoản khác).
Từ đó mình xây dựng được một request như sau:
Với các tham số:
Để biết response khi nạp thẻ đúng thì mình đã nạp thử 1 thẻ 20.000đ của nhà mạng này bằng cách gửi request như trên, và tham số trả về chỉ gồm một con số 20000 nên mình đoán đây là giá trị của thẻ nếu nạp thẻ thành công.
Nếu thử nạp lại thẻ đó một lần nữa thì response trả về sẽ là ERROR: VOUCHER_IS_ALREADY_CONSUMED.
Thử với một mã thẻ không tồn tại thì response trả về là ERROR: VOUCHER_PIN_NOT_FOUND_IN_DB
Sau đó mình thử lặp lại request nạp tiền nhiều lần với nhiều mã thẻ random khác nhau, tuy không nạp được thẻ nào nhưng cũng không thấy dấu hiệu bị rate limit. Như vậy hệ thống của Y có khả năng bị bruteforce mã thẻ, bằng cách thử nạp tất cả các mã thẻ có độ dài bằng với độ dài hợp lệ.
Từ hàm thứ hai:
Ta biết được một số thông tin như sau:
Dựa vào từ khóa TopUpSuccessfulNotification, mình đoán hàm này dùng để thông báo việc nạp tiền thành công.
Tuy nhiên…
Liệu hàm này là để thông báo việc nạp tiền thành công cho người dùng ứng dụng, hay cho server?
Tuy nhiên đó vẫn chưa phải lỗi khiến mình viết ra bài này…
Tại sao một hàm có chức năng thông báo lại sử dụng biến amount? Phải chăng biến này dùng để “thông báo” số tiền cần nạp?
Để giải quyết mối nghi này, mình tạo một request có dạng như sau đến server của Y (mặc dù method ghi là GET nhưng mình dùng POST thấy được nên sau đó không để ý test lại luôn):
- Method của request là GET
Thật kì lạ, server trả về con số 21337, bằng với số tiền trong tài khoản của mình là 20000 cộng thêm con số 1337 ở trên.
Ngay sau đó mình check thử số tiền trong tài khoản bằng cú pháp *101#
Proof of Concept
Phân tích dài vậy, tại sao có thể gọi là hack được của Y “sau một nốt nhạc”?
Sau khi phân tích và lấy được API của Y, những lần sau để nạp tiền mình chỉ cần request đến đúng API đó là được, thậm chí có thể viết script để chỉ cần nhập số điện thoại và số tiền là nạp được. Mình đã demo ngay chính trong PoC ở trên bằng một đoạn script Python.
Lỗ hổng này từ đâu mà có?
Mình đã tìm thử xem hàm gây ra lỗ hổng được sử dụng ở đâu trong code, tuy nhiên tìm không thấy, nên mình đoán đây là phần code đã bị Y “bỏ quên” trong ứng dụng cũng như API trên server.
Chẳng hiểu ai lại đi làm ra cái “tính năng” này, nhưng nếu ít nhất anh ta chịu remove dead code đi thì có lẽ mọi việc đã chả đến nỗi, ít ra thì sẽ không bị một đứa rảnh ruồi nào đó như mình dịch ngược ứng dụng và phát hiện ra chẳng hạn :D.
Timeline
P/S: Vì mình không có nhiều hiểu biết về Android cũng như C# nên có chỗ nào sai sót mong được góp ý thêm.
- 2/3/2018: Báo cáo lỗ hổng tới Y
- 1/4/2018: Xác nhận Y đã fix lỗ hổng
--- Bài cũ hơn ---
Anh Em Trong Arms® 3 + Mod
Brother In Arms 3 Hack Apk V1.4.9A + Data Android
Tải Game Brothers In Arms 3 Mod Apk 1.5.2A (Mua Sắm Miễn Phí)
Brothers In Arms 3 V1.5.2A Mod Vip Tiền Vàng Sao Online Android & Ios, Tải Game Mod
Tải Game Injustice 2 Mod Apk 4.3.1 (Vô Hạn Năng Lượng)