Lượt xem: 1018 | Gửi lúc: 23/03/2017 16:27:38
Bookmark and Share

Lưu thông tin mật trong ứng dụng Android như thế nào?

Một trong những nguyên tắc lập trình an toàn là không lưu thông tin mật trong ứng dụng hay các tệp cấu hình. Vì thế các thông tin mật của ứng dụng Android không nên lưu ở SharedPreferences hay cơ sở dữ liệu SQLite.

Cả hai cách lưu trữ này đều có cơ chế phân quyền dựa trên hệ thống quyền của Linux, tương tự như hệ thống tệp. SharedPreferences trong Android gần tương tự như tệp INI trong Windows, vì dù đặt thuộc tính cấm đọc (ứng dụng khác) thì cũng chỉ là "phòng người ngay". Tin tặc có thể dùng lệnh run-as của adb (nếu ứng dụng có thể debug) hay sao lưu dữ liệu ra thẻ nhớ (nếu trong tệp manifest có dòng android:allowBackup="true") để đọc dữ liệu trong SharedPreferences. Ngay cả nếu lập trình viên đã dập các cờ debug và backup thì vẫn còn một lỗ hổng khác: với điện thoại đã bị root, phân quyền của Android là vô nghĩa.



Google khuyến cáo nên dùng KeyStore để lưu trữ các giá trị bí mật của ứng dụng. KeyChainAPI được giới thiệu từ Android 4.0 đã cho phép các ứng dụng nhập khóa vào kho lưu trữ thông tin của hệ thống, nhưng những khóa đó thuộc sở hữu của hệ thống và các ứng dụng chỉ có thể yêu cầu truy cập. Android 4.3 bổ sung hỗ trợ cho khóa bí mật của ứng dụng, cho phép bất kỳ ứng dụng nào sinh và lưu khóa bí mật sao cho chỉ mình nó có thể truy cập. Hướng dẫn lập trình với KeyStore có thể xem tại đây.

KeyStore dùng chung nguyên lý với DPAPI của Windows, bảo vệ dữ liệu nhờ mật khẩu đăng nhập của người dùng. Nhưng chính điều đó khiến KeyStore “bó tay” khi người dùng xóa bỏ mật khẩu đăng nhập (chuyển sang chế độ "vuốt" để mở màn hình cho nhanh). Khi đó, hệ thống sẽ xóa các giá trị bí mật của người dùng.

Để ngăn chặn việc người dùng đổi chế độ mở khóa màn hình thành None hay Swipe, ứng dụng cần thêm quyền Device Manager và lập trình thêm khá phức tạp. Hơn thế nữa, điều đó có thể khiến khách hàng nghi ngờ/khó chịu. 

Vậy nếu không dùng KeyStore thì phải lưu các giá trị bí mật vào đâu? Để đảm bảo an toàn, lập trình viên có thể yêu cầu người dùng thiết lập password/passcode truy cập ứng dụng rồi dùng một trong hai cách sau: 

1. Dùng SQLCipher để mã hóa database chứa các giá trị bí mật (bằng khóa sinh từ password/passcode truy cập ứng dụng của người dùng);

2. Mã hóa giá trị bí mật (cũng bằng khóa sinh từ password/passcode truy cập ứng dụng của người dùng – sau khi biến đổi với PBKDF2).

Với cách thứ nhất, ứng dụng sẽ báo lỗi nếu người dùng nhập sai password/passcode. Với cách thứ hai, ứng dụng không báo lỗi, nhưng nếu người dùng nhập sai password/passcode, thì giá trị bí mật sai sẽ khiến ứng dụng không thể hoạt động bình thường (và do đó người dùng không bị thiệt hại).

Anh Tuấn