Hack tiền điện thoại chỉ trong một nốt nhạc?! – J2TEAM Blog

Hack tiền điện thoại chỉ trong một nốt nhạc?!

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

Thời còn nhỏ, khi chơi game những bạn có khi nào mơ mộng đến những thứ như ” hack tiền “, ” hack đồ ” trong game, những thứ mà nôm na sẽ khiến bạn trở nên ” giàu ” hơn so với phần còn lại ( khác với kiểu hack game bắn bách phát bách trúng nhé : v ). Đã khi nào bạn dùng lệnh coinage trong đế chế hay IFIWEREARICHMAN trong GTA ? Cảm giác nhấn nút cái có đầy tiền quả thật rất sung sướng phải không ? Nhưng ngược lại, có khi nào bạn tuyệt vọng khi thử ” hack ” mà chẳng nhận được gì chưa ? Mình thì bị nhiều rồi, thử mấy trang quảng cáo ” hack tiền ” với mấy game trực tuyến mà xem, tiền thì không có mà thậm chí còn còn mất cả thông tin tài khoản ấy chứ. Lớn lên mới biết người ta dựng lên những thứ như vậy chỉ để lừa bạn nạp thẻ hoặc chiếm thông tin đăng nhập của bạn ( phishing ), hay lừa bạn click vào quảng cáo trên website để kiếm lời ( clickbait ). Nếu có là lỗi thật thì thường cũng sẽ bị fix trong vòng một nốt nhạc, và chẳng ai nhắc đến nó nữa .

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 tiêu bảo mật thông tin 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 thông tin hơn ( theo mình đoán là có SSL Pinning ) nên mình không hề dùng Fiddler để capture request theo cách thường thì mà phải dịch ngược mã nguồn để nghiên cứu và 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, hoàn toàn có thể tìm một cách thuận tiện trên những trang tàng trữ như apkpure, còn cách mình hay dùng là pull trực tiếp từ Android trải qua adb .Việc tiên phong 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 đó điều tra và nghiên cứu những phần code công dụ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 :

J2TEAM

Theo kinh nghiệm tay nghề 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 R.java 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ẻ như có giá trị : ( .

J2TEAM

Sau khi lục tung hết mấy thư mục mã nguồn mà không có tác dụng, mình đoán rằng cần phải tiếp cận yếu tố này theo một hướng khác. Và đó cũng chính là lúc mình khởi đầu chú ý đế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 được cho phép lập trình ứng dụng di động bằng ngôn từ C # của. NET framework. Mình thì chỉ nhớ mấy thư viên của C # có phần lan rộng ra. dll thôi, nên là quyết định hành động quay lại tìm xem trong apk có file. dll nào không .Vì file. apk thực ra 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 :

J2TEAM

Mở thư mục assemblies, được một nùi file. dll thế này. Mình thì chú ý quan tâm đến file Y.dll.

J2TEAM

Để dịch ngược file. NET tất cả chúng ta cũng cần chơi theo kiểu. NET. Vì vậy mình dùng Telerik JustDecompile để mở và nghiên cứu 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ố ít thông tin như :

  • Ứ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/. 

Và để biết đơn cử ứng dụng tương tác với server thế nào thì mình cần tìm thêm những hàm gọi API .Trong file. dll vừa mở, mình liên tục tìm được một class có tên AccountService mà trải qua tên những hàm giải quyết và xử lý ( Register, Login, ResetPassword, GetProfile ), mình đoán class này có trách nhiệm giải quyết và xử lý những tác vụ trên thông tin tài khoản như ĐK, đăng nhập, đặt lại mật khẩu, …Đây là phần code giải quyết và xử lý của class nói trên :

Từ đây, mình mở màn thử tạo ra một request hợp lệ tới server. Ví dụ từ hàm login :

Mình biết được 1 số ít thông tin như sau :

  • Method của request là POST
  • Path là login/
  • Request body gồm loginId và password

Cộng với việc biết base API và định dạng tài liệu JSON, mình thiết kế xây dựng được một request thế này :

J2TEAM

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ề 1 số ít thông tin thông tin tài khoản như thế này :

J2TEAM

Sau khi biết cách tạo request đến server, mình liên tục chú ý đến 2 hàm sau :

Nhìn vào từ khóa Topup, mình đoán công dụng của 2 hàm này tương quan tới việc nạp tiền điện thoại .Hàm tiên phong mình đoán có tính nă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 thông tin tài khoản hiện tại ( trong trường hợp bạn nạp thẻ cho một thông tin tài khoản khác ) .Từ đó mình kiến thiết xây dựng được một request như sau :

J2TEAM

Với những tham số :

  • là số điện thoại của tài khoản hiện tại
  • là mã thẻ
  • là số điện thoại cần nạp

Để 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 số lượng 20000 nên mình đoán đây là giá trị của thẻ nếu nạp thẻ thành công xuất sắc .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 sống sót thì response trả về là ERROR : VOUCHER_PIN_NOT_FOUND_IN_DBSau đó 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 tín hiệu bị rate limit. Như vậy mạng lưới hệ thống của Y có năng lực bị bruteforce mã thẻ, bằng cách thử nạp toàn bộ những mã thẻ có độ dài bằng với độ dài hợp lệ .

Tuy nhiên đó vẫn chưa phải lỗi khiến mình viết ra bài này…

Từ hàm thứ hai :

Ta biết được một số ít thông tin như sau :

  • Method của request là GET
  • Request URL có dạng subscriber/etopup//, với msisdn, là số điện thoại của tài khoản hiện tại, và một biến

Dựa vào từ khóa TopUpSuccessfulNotification, mình đoán hàm này dùng để thông tin việc nạp tiền thành công xuất sắc .Tuy nhiên …Liệu hàm này là để thông tin việc nạp tiền thành công xuất sắc cho người dùng ứng dụng, hay cho server ?Tại sao một hàm có công dụng thông tin lại sử dụng biến amount ? Phải chăng biến này dùng để ” thông tin ” số tiền cần nạp ?Để xử lý 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ầu method ghi là GET nhưng mình dùng POST thấy được nên sau đó không chú ý test lại luôn ) :

J2TEAM

Với là số điện thoại của mình, mình thử con số 1337

Thật kì quặc, server trả về số lượng 21337, bằng với số tiền trong thông tin tài khoản của mình là 20000 cộng thêm số lượng 1337 ở trên .Ngay sau đó mình check thử số tiền trong thông tin tài khoản bằng cú pháp * 101 #

J2TEAM

Thì thấy số tiền lúc này đã biến hóa đúng như trong response trả về. Sau khi thử đi thử lại vài lần trên những số điện thoại khác nhau, mình nhận thấy rằng hoàn toàn có thể dùng API này để nạp tiền vào bất kỳ thông tin tài khoản nào thuộc nhà mạng Y, chậm chí khi nạp xong còn có tin nhắn quảng cáo của nhà mạng gửi về giống như khi nạp tiền bằng thẻ cào .

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ối thiểu anh ta chịu remove dead code đi thì có lẽ rằng 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 ví dụ điển hình : D .

Timeline

  • 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

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 .

Source: https://final-blade.com
Category custom BY HOANGLM with new data process: Tiền Điện Tử – Tiền Ảo