Bảo vệ thông tin trong ứng dụng Android

Hệ sinh thái Android cung cấp nhiều tiện ích cho việc phát triển ứng dụng di động và một trong số đó có những tiện ích liên quan đến bảo vệ tính an toàn của thông tin. Các nhà phát triển và nhà sản xuất phần cứng tận dụng những khả năng này để cung cấp các tính năng bảo mật mà người dùng mong đợi mà không cần phải tự viết lại toàn bộ quy trình đó. Một số tính năng bảo mật cấp nền tảng quan trọng trên Android là:

Dữ liệu cục bộ
- Mã hóa toàn bộ thiết bị: Cung cấp mã hóa dữ liệu ở cấp độ thiết bị để bảo vệ khỏi các cuộc tấn công nhân bản thiết bị di động
- Cô lập dữ liệu của từng ứng dụng: Sử dụng mô hình người dùng dựa trên Linux để cô lập dữ liệu cho các ứng dụng và ngăn chặn một ứng dụng bị xâm nhập, truy cập trái phép dữ liệu từ một ứng dụng khác trên thiết bị của người dùng
Dữ liệu trên kênh truyền
- SSL/TLS: Cung cấp mã hóa kênh truyền trong quá trình trao đổi thông tin giữa ứng dụng và các API.

- Certificate pinning: Yêu cầu các API của máy chủ trình bày một chứng chỉ cụ thể, được xác định trước, cho ứng dụng. Ứng dụng có mã khóa công khai của chứng chỉ mong đợi được cài đặt cứng vào ứng dụng, và chỉ có chứng chỉ này mới được chấp nhận.

Assumptions phổ biến của các nhà phát triển

Mặc dù một lợi thế của việc tận dụng các tính năng bảo mật cấp nền tảng Android là các nhà phát triển không cần phải tìm hiểu chi tiết về việc triển khai những tính năng này, nhưng điều này có thể là con dao hai lưỡi. Cũng như nhiều vấn đề trong lĩnh vực bảo mật, việc thiếu hiểu biết có thể nhanh chóng dẫn đến những sai sót trong quá trình triển khai và sau đó là các lỗ hổng bảo mật.

Một cách trừu tượng, hầu hết các lỗ hổng xuất phát từ:

  • Một hoặc nhiều assumption được thực hiện
  • Một số điều kiện tấn công assumption, dẫn đến có lỗ hổng bảo mật

Vì vậy, với người làm bảo mật, mục tiêu của chúng ta là xác định các assumption được tạo bởi ứng dụng và hệ thống, sau đó tìm cách làm suy yếu các assumption này để dẫn đến các vấn đề về bảo mật. Với ý tưởng đó, chúng ta nên bắt đầu bằng cách xem xét cách các nhà phát triển sử dụng các tính năng bảo mật được Android cung cấp, có thể phát hiện các assumption được sử dụng không hợp lý hoặc kém an toàn. Trong bài viết này, ta sẽ xem xét một vài ví dụ:

  • Kẻ tấn công không có quyền truy cập vào mã nguồn của ứng dụng
  • Kẻ tấn công không thể truy cập dữ liệu riêng tư của ứng dụng
  • SSL/TLS và certificate pinning ngăn chặn kẻ tấn công chặn và thay đổi các yêu cầu đến các API server.

Vô hiệu hóa các Assumptions của nhà phát triển

Hãy cùng xem nhanh cách chúng ta có thể vô hiệu hóa một số assumption phổ biến của nhà phát triển

  • Kẻ tấn công không có quyền truy cập vào mã nguồn của ứng dụng
    • Với các công cụ có sẵn miễn phí (ví dụ: Jadx GUI), kẻ tấn công có thể dễ dàng dịch ngược các APK thành mã nguồn Java (hoặc Kotlin) mà có thể đọc được.
  • Kẻ tấn công không thể truy cập dữ liệu riêng tư của ứng dụng
    • Kẻ tấn công có thể đặt “debuggable=true” ở trong AndroidManifest.xml để truy cập thư mục dữ liệu “private” tại đường dẫn /data/data/<com.app.name>/
  • SSL/TLS và certificate pinning ngăn chặn kẻ tấn công chặn và thay đổi các yêu cầu đến các API server.
    • Kẻ tấn công có thể sử dụng các công cụ mới giúp loại bỏ ghim chứng chỉ và chặn bắt lưu lượng truy cập mạng từ ứng dụng một cách dễ dàng

Các công cụ - Thiết lập phần cứng

Để có thể triển khai các kỹ thuật vô hiệu hóa các assumption phổ biến này, trước tiên chúng ta cần thiết lập môi trường kiểm thử của mình bằng các công cụ cụ thể, cả về phần cứng và phần mềm. Các công cụ phần cứng khá đơn giản, chủ yếu bao gồm:

  • Các thiết bị Android test
    • Điện thoại “Burner”, chẳng hạn như điện thoại của Tracfone, có thể là được xem xét bởi giá tương đối thấp và khả năng truy cập dễ dàng. Có thể mua những thiết bị di động này ở hầu hết các cửa hàng truyền thống với giá $29-$45, dẫn đến khả năng có nhiều thiết bị thử nghiệm. Nên có nhiều thiết bị để thử nghiệm các tính năng ngang hàng có trong nhiều ứng dụng hiện đại.
  • Cáp USB
  • Máy tính Mac hoặc Linux
    • Máy tính Windows cũng sử dụng được, nhưng hầu hết các công cụ và hướng dẫn tìm thấy trên Internet thường sẽ sử dụng máy Mac và Linux. Vì vậy, sẽ dễ dàng hơn khi sử dụng Mac hay Linux.

Các công cụ - Thiết lập phần mềm

Các công cụ phần mềm sẽ cần bao gồm:

apk-mitm

Các công cụ và kỹ thuật để loại bỏ ghim chứng chỉ khỏi ứng dụng Android đã có từ khá lâu. Tuy nhiên, quá trình này trước đây thường diễn ra thủ công, phức tạp và dễ xảy ra sai sót. Thông thường, điều này liên quan đến việc giải nén APK, tìm kiếm mã smali để thực hiện hook vào các hàm thực hiện ghim chứng chỉ, chỉnh sửa mã smali theo cách thủ công để bỏ qua điều này và đóng gói lại APK.

Ngày nay, thông qua shroudedcode, chúng ta có một công cụ mới giúp đơn giản hóa đáng kể quá trình tước chứng chỉ ghim khỏi ứng dụng Android. Với gói NodeJS apk-mitm này, quy trình thực hiện được rút gọn chỉ còn “một dòng”. Trang apk-mitm GitHub nêu chi tiết các yêu cầu cần thiết để thiết lập công cụ, về cơ bản chỉ bao gồm cài đặt Node và sau đó chạy:

npm install -g apk-mitm

Sau khi cài đặt xong, chúng ta có thể loại bỏ ghim chứng chỉ khỏi bất kỳ APK nào bằng câu lệnh:

$ apk-mitm example.apk

  ✔ Decoding APK file
  ✔ Modifying app manifest
  ✔ Replacing network security config
  ✔ Disabling certificate pinning
  ✔ Encoding patched APK file
  ✔ Signing patched APK file

   Done!  Patched APK: ./example-patched.apk

Sau khi hoàn tất, chúng ta có thể tải bản vá APK bằng cách chạy:

adb install <app-patched.apk>

Truy cập dữ liệu riêng tư của ứng dụng

Mặc dù các tính năng bảo mật cô lập mỗi ứng dụng ở cấp độ nền tảng Android có hiệu quả trong việc ngăn chặn một ứng dụng độc hại truy cập vào dữ liệu riêng tư của các ứng dụng khác trên thiết bị của người dùng, tuy nhiên chúng ta vẫn có thể bỏ qua các tính năng này để hiểu rõ hơn về hoạt động bên trong của ứng dụng mục tiêu cũng như khả năng sử dụng và/hoặc tiết lộ thông tin nhạy cảm. Trong nhiều trường hợp, người kiểm thử phải thực hiện kiểm thử hộp đen, trong đó thông tin về hoạt động bên trong của mục tiêu là rất ít. Trong những trường hợp này, chúng ta có thể áp dụng lý luận suy diễn để thu thập thông tin về những gì thiết bị làm, nhưng những điều như vậy chủ yếu vẫn chỉ là phỏng đoán.

Khi đó, nếu chúng ta có cách để vượt qua tấm chắn và xem ứng dụng thực sự hoạt động ở đằng sau như thế nào là rất hữu ích. Đó chính xác là những gì chúng ta có thể đạt được qua các bước ở bên dưới. Giả sử chúng ta đã tải xuống và cài đặt một ứng dụng di động bản phát hành từ cửa hàng Google Play và chúng ta được giao nhiệm vụ thực hiện thử nghiệm thâm nhập đối với ứng dụng đó.

Chúng ta sẽ bắt đầu bằng cách liệt kê các gói được cài đặt trên thiết bị di động bằng lệnh:

adb shell pm list packages -f | grep -i app-name

Và ví dụ ở đây có thể thấy tôi đã cài đặt một ứng dụng demo có tên com.example.self

Tiếp theo, ta sao chép APK của ứng dụng mục tiêu từ thiết bị di động bằng lệnh

adb pull /data/app/path-from-pm-list-packages-output

Tiếp theo, chúng ta gỡ cài đặt bản phát hành của ứng dụng mục tiêu khỏi thiết bị di động của mình vì cuối cùng, chúng ta sẽ tải một phiên bản có thể debug và chúng ta sẽ gặp phải sự cố về không gian tên nếu không gỡ cài đặt phiên bản hiện có trước.

adb uninstall com.example.self

Sau đó, chúng ta giải nén APK đã sao chép từ thiết bị di động bằng lệnh bên dưới, lệnh này sẽ trích xuất nội dung của tệp base.apk vào một thư mục mới có tên là extracted_apk

java -jar ./apktool.jar d -o extracted_apk ./base.apk

Bây giờ chúng ta chỉnh sửa tệp AndroidManifest.xml trong thư mục extracted_apk và đặt cờ android:debuggable=”true”.

LƯU Ý: Trong hầu hết các ứng dụng xây dựng bản phát hành, AndroidManifest.xml sẽ không bao gồm android:debuggable=”false” . Nếu có cờ này, chúng ta có thể thay đổi false thành true; nếu không, chúng ta phải thêm android:debuggable=”true” .

Ví dụ ta thêm như sau:

Tiếp theo, chúng ta sẽ đóng gói lại APK để triển khai trên thiết bị di động thử nghiệm của mình, thiết bị này yêu cầu tạo Java keystore bằng lệnh:

keytool -genkey -v -keystore resign.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000

Sau đó, chúng ta sử dụng công cụ apktool.jar để dựng lại APK có thể debug bằng cách tạo một APK mới có tên self-debuggable.apk từ thư mục extracted_apk :

java -jar apktool.jar b -o self–debuggable.apk ./extracted_apk/

Tiếp theo, chúng ta ký APK mới và cài đặt vào thiết bị:

java -jar ./uber-apk-signer.jar -a ./self–debuggable.apk -ks resign.keystore -ksAlias alias_name

adb install ./self-debuggable-aligned-signed.apk

Sau khi quá trình này hoàn tất, chúng ta đã có thể truy cập dữ liệu riêng tư của ứng dụng bằng cách chạy:

$ adb shell

$ run-as com.example.self

Bằng cách này, chúng ta có thể tìm thấy các dữ liệu nhạy cảm của ứng dụng mà không cần lên quyền root.

Theo Bugcrowd.

Chia sẻ bài viết này