Giới thiệu
Trong kỷ nguyên 4.0 hiện nay, sự tiến bộ trong công nghệ đã mang lại nhiều lợi ích đáng kể cho cuộc sống của con người. Tuy nhiên, cùng với sự phát triển này, chúng ta cũng phải đối mặt với những vấn đề về mặt trái của công nghệ, đặc biệt là những mối lo ngại về quyền riêng tư và lỗ hổng bảo mật thông tin. Nhận thức được rằng công nghệ càng phát triển thì yêu cầu về an toàn và bảo mật thông tin càng trở nên quan trọng, bài viết này sẽ thảo luận về các quy tắc nhằm nâng cao bảo mật và giảm thiểu rủi ro mà các lập trình viên Flutter có thể áp dụng khi phát triển ứng dụng của mình.
1. Obfuscate code
Thông thường, mã nguồn sau khi được biên dịch thành tệp nhị phân có thể bị phân tích ngược (reverse engineering) để khôi phục lại mã nguồn gốc, từ đó tạo điều kiện cho việc đánh cắp thông tin quan trọng. Do đó, việc mã hóa mã nguồn (obfuscation) trở thành một bước quan trọng trong bảo mật. Quá trình này thay đổi cấu trúc mã nguồn, chẳng hạn như thay đổi tên hàm, tên biến, mã hóa chuỗi, và thêm các tệp giả, mà không làm ảnh hưởng đến kết quả của chương trình. Điều này làm tăng độ khó cho những kẻ tấn công khi cố gắng đánh cắp mã nguồn hoặc tìm kiếm thông tin giá trị trong đó.
Hiểu một cách đơn giản, obfuscate code sẽ sắp xếp, thay đổi để code trở nên rối tung và không thể đọc được.
Đối với Flutter, ta sẽ thêm biến --obfuscate
, kết hợp với --split-debug-info
vào lệnh build như sau:
flutter build apk --obfuscate --split-debug-info=/<project-name>/<directory>
Ở đây, --split-debug-info
có nhiệm vụ cung cấp địa chỉ của thư mục để Flutter lưu trữ file output debug. Ngoài ra, ta có thể thay thế apk
thành appbundle
, ipa
, hay ios
để build các file tương ứng cho iOS và Android.
Lưu ý: khi sử dụng --obfuscate
trong lệnh build, ta mới chỉ obfuscate code của Dart. Nếu muốn obfuscate code native Android hay iOS, ta sẽ cần cấu hình hai phần riêng biệt trong từng thư mục /ios
và /android
.
2. Bảo mật API key
API key là một trong những thông tin quan trọng nhất cần được bảo vệ và không nên để lọt vào tay kẻ xấu. Nếu API key bị lộ, hacker có thể sử dụng nó để truy cập vào thông tin của người dùng và hệ thống. Để đảm bảo an toàn và tăng cường bảo mật, cần thực hiện bảo vệ API key từ cả hai phía: Server side và Client side.
Server side
Đối với server, việc hạn chế quyền truy cập của API key là rất quan trọng. Thay vì cho phép API key truy cập vào toàn bộ dịch vụ của hệ thống, ta chỉ cung cấp những dịch vụ tối thiểu cần thiết cho API key đó. Thêm vào đó, ta có thể thực hiện mã hóa và giải mã API key ngay tại thời điểm chạy (runtime), chẳng hạn như trong quá trình xác thực người dùng. Cách làm này tạo thêm một lớp bảo mật để bảo vệ API key, giúp ngăn chặn hacker dễ dàng lấy và đọc thông tin.
Client side
Thứ nhất, không bao giờ commit key trực tiếp lên git, đặc biệt là những dự án public hay open-source. Với những dự án này, để sử dụng API key, ta sẽ dùng các biến môi trường.
Trong Flutter, ta có thể sử dụng thư viện flutter_dotenv để tạo file .env và lưu các key vào trong đó.
Thứ hai, việc sử dụng biến môi trường giúp giảm thiểu rủi ro bằng cách không công khai API key lên Git, nhưng điều này không thể ngăn chặn hoàn toàn việc key vẫn được sử dụng trong quá trình biên dịch mã. Do đó, hacker có thể vẫn có khả năng phân tích ngược để lấy được key. Trong trường hợp này, ta cần quay lại điểm trước và thực hiện obfuscate code để mã hóa các key, nhằm tăng cường bảo mật.
3. Hạn chế truy cập mạng
Khi ứng dụng thực hiện yêu cầu API, thông tin trao đổi giữa ứng dụng và server sẽ được bảo mật thông qua tầng giao thức Transport Layer Security (TLS). Mục tiêu chính của giao thức TLS là đảm bảo sự riêng tư và toàn vẹn của dữ liệu giữa hai ứng dụng trong môi trường mạng.
Để hạn chế truy cập và đảm bảo rằng chỉ những địa chỉ đã được xác thực mới có thể truy cập, một phương pháp là liệt kê các tên miền được phép sử dụng trong ứng dụng.
Với Android, ta sẽ tạo file config android/src/main/res/xml/network_security_config.xml
và thêm đoạn code sau:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <trust-anchors> <certificates src="@raw/my_ca"/> </trust-anchors> </domain-config>
</network-security-config>
Với iOS, ta sẽ config trong file ios/Info.plist:
<key>NSAppTransportSecurity</key>
<dict> <key>NSAllowsArbitraryLoads</key> <false/> <key>NSExceptionDomains</key> <dict> <key>cocoacasts.com</key> <dict> <key>NSIncludesSubdomains</key> <true/> <key>NSExceptionAllowsInsecureHTTPLoads</key> <true/> </dict> </dict>
</dict>
Tổng kết
Trong bài viết này, chúng ta đã khám phá ba bước để cải thiện và nâng cao bảo mật cho một ứng dụng Flutter. Bài viết cũng trình bày những phương pháp khác có thể giúp ứng dụng an toàn hơn trước các nguy cơ tiềm ẩn của việc bị đánh cắp thông tin, từ đó nâng cao hiệu quả bảo mật cho ứng dụng.