Android memiliki fitur keamanan bawaan yang secara signifikan mengurangi frekuensi dan dampak masalah keamanan aplikasi. Sistem ini dirancang agar Anda secara khusus dapat membuat aplikasi dengan izin file dan sistem default, serta menghindari opsi keamanan yang sulit dipilih.
Fitur keamanan inti berikut membantu Anda membuat aplikasi yang aman:
- Sandbox Aplikasi Android, yang memisahkan data aplikasi dan eksekusi kode dari aplikasi lainnya.
- Framework aplikasi dengan implementasi fungsionalitas keamanan umum yang canggih, seperti kriptografi, izin, dan IPC aman.
- Teknologi seperti ASLR, NX, ProPolice, safe_iop, OpenBSD dlmalloc, OpenBSD calloc, dan Linux mmap_min_addr untuk mengurangi risiko yang berkaitan dengan error umum pengelolaan memori.
- Sistem file terenkripsi yang dapat diaktifkan untuk melindungi data di perangkat yang hilang atau dicuri.
- Izin yang diberikan pengguna untuk membatasi akses ke fitur sistem dan data pengguna.
- Izin yang ditetapkan aplikasi untuk mengontrol data aplikasi pada basis per-aplikasi.
Penting bagi Anda untuk memahami praktik terbaik keamanan Android dalam dokumen ini. Mengikuti praktik ini sebagai kebiasaan coding umum dapat mengurangi kemungkinan timbulnya masalah keamanan secara tidak sengaja yang berdampak buruk pada pengguna Anda.
Menyimpan data
Permasalahan keamanan yang paling umum untuk aplikasi di Android adalah apakah data yang Anda simpan di perangkat dapat diakses oleh aplikasi lain. Ada tiga cara mendasar untuk menyimpan data di perangkat:
- Penyimpanan internal.
- Penyimpanan eksternal.
- Penyedia konten.
Menggunakan penyimpanan internal
Secara default, file yang Anda buat di penyimpanan internal hanya dapat diakses oleh aplikasi Anda. Android mengimplementasikan perlindungan ini, yang cukup memadai untuk sebagian besar aplikasi.
Secara umum, hindari mode MODE_WORLD_WRITEABLE
atau MODE_WORLD_READABLE
untuk file IPC karena mode tersebut tidak memungkinkan pembatasan akses data ke aplikasi tertentu, juga tidak memberikan kontrol atas format data. Jika Anda ingin berbagi data dengan proses aplikasi lain, sebaiknya gunakan penyedia konten, yang menawarkan izin membaca dan menulis ke aplikasi lain, serta dapat memberikan izin dinamis secara kasus per kasus.
Untuk memberikan perlindungan tambahan bagi data sensitif, Anda dapat mengenkripsi file lokal menggunakan library Keamanan. Tindakan ini dapat memberikan perlindungan pada perangkat yang hilang tanpa enkripsi sistem file.
Menggunakan penyimpanan eksternal
File yang dibuat di penyimpanan eksternal, seperti kartu SD, secara umum dapat dibaca dan ditulis. Jangan menyimpan informasi sensitif menggunakan penyimpanan eksternal, karena penyimpanan eksternal dapat dihapus oleh pengguna dan juga diubah oleh aplikasi apa saja.
Untuk membaca dan menulis file di penyimpanan eksternal dengan cara yang lebih aman, pertimbangkan penggunaan library Keamanan yang menyediakan class EncryptedFile
.
Anda harus Melakukan validasi input saat menangani data dari penyimpanan eksternal, seperti saat menangani data dari sumber yang tidak tepercaya. Anda sebaiknya tidak menyimpan file executable atau file class di penyimpanan eksternal sebelum pemuatan dinamis. Jika aplikasi Anda tidak mengambil file executable dari penyimpanan eksternal, file seharusnya ditandai dan diverifikasi secara kriptografi sebelum pemuatan dinamis.
Menggunakan penyedia konten
Penyedia konten menawarkan mekanisme penyimpanan terstruktur yang dapat dibatasi hanya untuk aplikasi Anda sendiri atau diekspor untuk mengizinkan akses oleh aplikasi lainnya.
Jika tidak ingin menyediakan akses bagi aplikasi lain ke ContentProvider
, tandai sebagai
android:exported=false
dalam manifes aplikasi. Atau, tetapkan atribut android:exported
ke true
agar aplikasi lain dapat mengakses data yang tersimpan.
Saat membuat ContentProvider
yang diekspor untuk digunakan oleh aplikasi lain, Anda dapat menentukan satu izin untuk membaca dan menulis, atau menentukan izin yang berbeda untuk membaca dan menulis.
Anda harus membatasi izin hanya untuk yang diperlukan guna menyelesaikan tugas yang ada. Perlu diingat bahwa, biasanya, akan lebih mudah untuk menambahkan izin di lain waktu untuk menampilkan fungsionalitas baru daripada meniadakannya dan memengaruhi pengguna yang ada.
Jika Anda menggunakan penyedia konten untuk berbagi data di antara aplikasi Anda sendiri saja, sebaiknya gunakan atribut android:protectionLevel
yang ditetapkan ke perlindungan signature
.
Izin tanda tangan tidak memerlukan konfirmasi pengguna sehingga akan memberikan pengalaman pengguna yang lebih baik dan akses yang lebih terkontrol ke data penyedia konten ketika aplikasi yang mengakses data ditandatangani dengan kunci yang sama.
Penyedia konten juga dapat memberikan akses yang lebih terperinci dengan mendeklarasikan atribut android:grantUriPermissions
serta menggunakan flag FLAG_GRANT_READ_URI_PERMISSION
dan FLAG_GRANT_WRITE_URI_PERMISSION
dalam objek Intent
yang mengaktifkan komponen. Cakupan izin ini dapat dibatasi lebih lanjut oleh elemen
<grant-uri-permission>
.
Ketika mengakses penyedia konten, gunakan metode kueri berparameter seperti query()
, update()
, dan delete()
untuk menghindari potensi injeksi SQL dari sumber yang tidak tepercaya. Perlu diperhatikan bahwa penggunaan metode berparameter tidak memadai jika argumen selection
dibuat dengan menyambungkan data pengguna sebelum mengirimkannya ke metode.
Jangan salah memahami keamanan terkait izin menulis.
Izin menulis mengizinkan pernyataan SQL yang memungkinkan beberapa data untuk dikonfirmasi menggunakan klausa WHERE
kreatif dan menguraikan hasilnya. Sebagai contoh, penyerang dapat memeriksa keberadaan nomor telepon tertentu dalam log panggilan hanya dengan memodifikasi satu baris kode jika nomor telepon tersebut sudah ada. Jika data penyedia konten memiliki struktur yang dapat diprediksi, izin menulis mungkin setara dengan menyediakan izin membaca dan menulis.
Menggunakan izin
Karena Android melakukan sandbox aplikasi satu dengan lainnya, aplikasi harus secara jelas membagikan resource dan data. Caranya yaitu dengan menyatakan izin yang dibutuhkan untuk kapabilitas tambahan yang tidak disediakan oleh sandbox dasar, termasuk akses ke fitur perangkat seperti kamera.
Meminta izin
Anda harus meminimalkan jumlah izin yang diminta aplikasi Anda.
Membatasi akses ke izin sensitif akan mengurangi izin tersebut secara tidak sengaja, meningkatkan adopsi yang dilakukan pengguna, dan menurunkan kerentanan aplikasi Anda terhadap penyerang. Secara umum, jangan meminta izin jika tidak diperlukan untuk menjalankan aplikasi Anda.
Jika ada fitur yang benar-benar dibutuhkan agar aplikasi dapat berjalan, deklarasikan menggunakan elemen <uses-feature>
dalam file manifes.
Apabila memungkinkan, akan lebih baik jika aplikasi Anda dirancang sedemikian rupa agar tidak memerlukan izin apa pun. Misalnya, daripada meminta akses ke informasi perangkat untuk membuat ID unik, Anda dapat membuat GUID untuk aplikasi (lihat bagian tentang Menangani data pengguna). Atau, daripada menggunakan penyimpanan eksternal (yang memerlukan izin), simpan data di penyimpanan internal.
Selain meminta izin, aplikasi Anda dapat menggunakan elemen <permission>
untuk melindungi IPC yang sensitif terhadap keamanan dan terbuka ke aplikasi lain, seperti ContentProvider
.
Secara umum, sebaiknya gunakan kontrol akses selain izin yang dikonfirmasi pengguna jika memungkinkan karena izin tersebut dapat membingungkan pengguna. Misalnya, pertimbangkan penggunaan tingkat perlindungan tanda tangan pada izin untuk komunikasi IPC antara aplikasi yang disediakan oleh satu developer.
Jangan bocorkan data yang dilindungi dengan izin. Hal ini terjadi jika aplikasi Anda mengekspos data melalui IPC yang tersedia hanya karena aplikasi memiliki izin untuk mengakses data tersebut. Klien antarmuka IPC aplikasi Anda mungkin tidak memiliki izin akses data yang sama. Detail lebih lanjut tentang frekuensi dan kemungkinan efek masalah ini disajikan dalam makalah penelitian Permission Re-Delegation: Attacks and Defenses, yang diterbitkan di USENIX.
Membuat izin
Umumnya, Anda harus mencoba menetapkan izin seminimal mungkin sembari memenuhi persyaratan keamanan. Membuat izin baru bukanlah hal biasa untuk sebagian besar aplikasi, karena izin yang ditentukan sistem mencakup banyak situasi. Jika memungkinkan, lakukan pemeriksaan akses menggunakan izin yang ada.
Jika Anda harus membuat izin baru, pertimbangkan apakah Anda dapat menyelesaikan tugas dengan tingkat perlindungan tanda tangan. Izin tanda tangan bersifat transparan bagi pengguna, dan hanya memungkinkan akses dari aplikasi yang ditandatangani oleh developer yang sama dengan aplikasi yang melakukan pemeriksaan izin. Jika izin yang baru masih diperlukan, izin tersebut dideklarasikan dalam manifes aplikasi menggunakan elemen <permission>
. Aplikasi yang ingin menggunakan izin baru tersebut dapat mereferensikannya dengan menambahkan elemen <uses-permission>
dalam masing-masing file manifesnya. Anda juga dapat menambahkan izin secara dinamis menggunakan metode addPermission()
.
Jika Anda membuat izin dengan tingkat perlindungan berbahaya, ada beberapa kerumitan yang perlu dipertimbangkan:
- Izin harus memiliki string yang secara singkat menyatakan kepada pengguna tentang keputusan keamanan yang harus mereka buat.
- String izin harus dilokalkan ke berbagai bahasa.
- Pengguna dapat memilih untuk tidak menginstal aplikasi karena adanya izin yang membingungkan atau dianggap berisiko.
- Aplikasi dapat meminta izin ketika pembuat izin belum diinstal.
Masing-masing hal tersebut memberikan tantangan non-teknis yang besar untuk Anda sebagai developer, sekaligus membingungkan pengguna. Itulah sebabnya kami tidak merekomendasikan penggunaan tingkat izin berbahaya.
Menggunakan jaringan
Transaksi jaringan secara inheren berisiko terhadap keamanan, karena melibatkan pengiriman data yang kemungkinan bersifat pribadi kepada pengguna. Orang-orang semakin sadar akan masalah privasi pada perangkat seluler, terutama ketika perangkat melakukan transaksi jaringan, sehingga sangat penting bagi aplikasi Anda untuk mengimplementasikan semua praktik terbaik guna menjaga keamanan data pengguna setiap saat.
Menggunakan jaringan IP
Jaringan di Android tidak berbeda secara signifikan dari lingkungan Linux lainnya. Pertimbangan utamanya adalah memastikan protokol yang tepat digunakan untuk data sensitif, seperti HttpsURLConnection
untuk traffic web yang aman. Sebaiknya gunakan HTTPS daripada HTTP setiap kali HTTPS didukung pada server, karena perangkat seluler sering terhubung pada jaringan yang tidak aman, seperti hotspot Wi-Fi publik.
Komunikasi tingkat soket yang dienkripsi dan diautentikasi dapat diimplementasikan dengan mudah menggunakan class SSLSocket
. Mengingat seringnya perangkat Android terhubung ke jaringan nirkabel tidak aman menggunakan Wi-Fi, penggunaan jaringan aman sangat direkomendasikan untuk semua aplikasi yang berkomunikasi melalui jaringan.
Beberapa aplikasi menggunakan port jaringan localhost untuk menangani IPC sensitif. Sebaiknya jangan gunakan pendekatan ini karena antarmuka ini dapat diakses oleh aplikasi lain di perangkat. Sebagai gantinya, gunakan mekanisme IPC Android yang memungkinkan autentikasi, misalnya dengan Service
.
Melakukan binding ke INADDR_ANY akan lebih tidak efektif dibandingkan menggunakan loopback, karena aplikasi Anda dapat menerima permintaan dari mana saja.
Pastikan Anda tidak memercayai data yang didownload dari HTTP atau protokol tidak aman lainnya. Ini mencakup validasi input dalam WebView
dan respons apa pun pada intent yang dikeluarkan terhadap HTTP.
Menggunakan jaringan telepon
Protokol SMS dirancang terutama untuk komunikasi antarpengguna dan tidak cocok untuk aplikasi yang ingin mentransfer data. Karena pembatasan SMS ini, Anda harus menggunakan Google Cloud Messaging (GCM) dan jaringan IP untuk mengirim pesan data dari server web ke aplikasi Anda di perangkat pengguna.
Berhati-hatilah karena SMS tidak dienkripsi dan tidak diautentikasi dengan baik di jaringan maupun perangkat. Khususnya, setiap penerima SMS harus memperkirakan jika pengguna yang berbahaya mungkin telah mengirim SMS ke aplikasi Anda. Jangan mengandalkan data SMS yang tidak diautentikasi untuk melakukan perintah sensitif.
Anda juga perlu mengetahui bahwa SMS dapat menjadi objek spoofing dan/atau intersepsi pada jaringan. Di perangkat dengan sistem operasi Android, pesan SMS dikirim untuk tujuan siaran, sehingga pesan tersebut dapat dibaca atau ditangkap oleh aplikasi lain yang memiliki izin READ_SMS
.
Melakukan validasi input
Validasi input yang tidak memadai adalah salah satu masalah keamanan paling umum yang memengaruhi aplikasi, terlepas dari platform yang digunakan. Android menawarkan langkah penanggulangan tingkat platform yang mengurangi kemunculan masalah validasi input pada aplikasi, dan Anda harus menggunakan fitur tersebut jika memungkinkan. Perlu diperhatikan juga bahwa pemilihan bahasa yang mudah diketik cenderung mengurangi kemungkinan masalah validasi input.
Jika Anda menggunakan kode native, data apa pun yang dibaca dari file, diterima melalui jaringan, atau diterima dari IPC berpotensi menimbulkan masalah keamanan. Masalah yang paling umum adalah buffer overflow, penggunaan setelah tersedia, dan nonaktif karena satu error. Android menyediakan sejumlah teknologi seperti ASLR dan DEP yang mengurangi dampak eksploitasi error ini, tetapi tidak mengatasi masalah yang mendasarinya. Anda dapat menghindari kerentanan ini dengan menangani pointer dan mengelola buffer secara hati-hati.
Bahasa berbasis string yang dinamis seperti JavaScript dan SQL juga dapat terpengaruh oleh masalah validasi input karena karakter escape dan injeksi skrip.
Jika Anda menggunakan data dalam kueri yang dikirim ke database SQL atau penyedia konten, injeksi SQL mungkin akan menjadi masalah. Pertahanan terbaik adalah dengan menggunakan kueri yang diparameterisasi, seperti yang dibahas di bagian sebelumnya tentang penyedia konten. Membatasi izin ke hanya-baca atau hanya-tulis juga dapat mengurangi potensi bahaya yang berhubungan dengan injeksi SQL.
Jika tidak dapat menggunakan fitur keamanan di atas, Anda harus memastikan untuk menggunakan format data yang terstruktur dengan baik dan memverifikasi bahwa data sesuai dengan format yang diharapkan. Meskipun pemblokiran atau penggantian karakter dapat menjadi strategi efektif, teknik ini rawan mengalami error dalam praktiknya dan harus dihindari jika memungkinkan.
Menangani data pengguna
Secara umum, pendekatan terbaik untuk keamanan data pengguna adalah dengan meminimalkan penggunaan API yang mengakses data sensitif atau pribadi pengguna. Jika Anda memiliki akses ke data pengguna dan tidak perlu menyimpan atau mengirimnya, jangan simpan atau kirim data tersebut. Pertimbangkan apakah ada cara untuk mengimplementasikan logika aplikasi Anda menggunakan hash atau format data non-reversibel. Misalnya, aplikasi Anda mungkin menggunakan hash alamat email sebagai kunci utama untuk menghindari pengiriman atau penyimpanan alamat email. Hal ini mengurangi kemungkinan tereksposnya data secara tidak sengaja, serta mengurangi kemungkinan penyerang mencoba mengeksploitasi aplikasi Anda.
Jika aplikasi Anda mengakses informasi pribadi seperti sandi atau nama pengguna, harap ingat bahwa sebagian wilayah hukum mewajibkan Anda untuk memberikan kebijakan privasi yang menjelaskan penggunaan dan penyimpanan data tersebut. Jadi, mengikuti praktik terbaik keamanan untuk meminimalkan akses ke data pengguna juga dapat menyederhanakan kepatuhan.
Anda juga harus mempertimbangkan apakah aplikasi mungkin secara tidak sengaja mengekspos informasi pribadi kepada pihak lain seperti komponen pihak ketiga untuk iklan atau layanan pihak ketiga yang digunakan oleh aplikasi Anda. Jangan berikan informasi pribadi jika Anda tidak tahu alasan mengapa komponen atau layanan memerlukan informasi tersebut. Secara umum, mengurangi akses aplikasi ke informasi pribadi akan mengurangi potensi masalah di area ini.
Jika aplikasi Anda memerlukan akses ke data sensitif, lakukan evaluasi apakah Anda perlu mengirimkannya ke server atau dapat menjalankan operasi pada klien. Pertimbangkan untuk menjalankan semua kode menggunakan data sensitif pada klien untuk menghindari pengiriman data pengguna. Selain itu, pastikan juga bahwa Anda tidak secara tidak sengaja mengekspos data pengguna ke aplikasi lain pada perangkat melalui IPC yang terlalu permisif, file yang dapat ditulis publik, atau soket jaringan. IPC yang terlalu permisif adalah kasus khusus untuk kebocoran data yang dilindungi izin, yang dibahas di bagian Meminta Izin.
Jika GUID diperlukan, buat nomor unik yang panjang, lalu simpan. Jangan gunakan ID telepon seperti nomor telepon atau IMEI, yang mungkin terkait dengan informasi pribadi. Topik ini dibahas secara lebih mendetail dalam Blog Developer Android.
Hati-hati saat menulis ke log di perangkat.
Di Android, log adalah resource bersama, dan tersedia untuk aplikasi dengan izin READ_LOGS
.
Meskipun data log ponsel bersifat sementara dan akan dihapus saat perangkat di-reboot, logging yang tidak benar atas informasi pengguna dapat secara tidak sengaja membocorkan data pengguna ke aplikasi lain. Selain tidak boleh melakukan logging PII, aplikasi produksi harus membatasi penggunaan log. Untuk mengimplementasikannya dengan mudah, gunakan flag debug dan class Log
khusus dengan tingkat logging yang mudah dikonfigurasi.
Menggunakan WebView
Karena WebView
menggunakan konten web yang mungkin menyertakan HTML dan JavaScript, penggunaan yang tidak tepat dapat memunculkan masalah keamanan web umum seperti pembuatan skrip lintas situs (injeksi JavaScript). Android menyertakan sejumlah mekanisme untuk mengurangi cakupan masalah potensial ini dengan membatasi kemampuan WebView
pada fungsionalitas minimal yang diperlukan aplikasi Anda.
Jika aplikasi Anda tidak menggunakan JavaScript secara langsung dalam WebView
, jangan panggil setJavaScriptEnabled()
.
Beberapa kode contoh menggunakan metode ini, yang mungkin Anda gunakan kembali dalam aplikasi produksi, oleh karena itu, hapus panggilan metode ini jika tidak diperlukan. Secara default, WebView
tidak mengeksekusi JavaScript sehingga pembuatan skrip lintas situs tidak dimungkinkan.
Gunakan addJavaScriptInterface()
dengan penanganan khusus karena metode ini mengizinkan JavaScript untuk memanggil operasi yang biasanya dikhususkan bagi aplikasi Android. Jika Anda menggunakannya, hanya tunjukkan addJavaScriptInterface()
ke halaman web yang semua inputnya dapat dipercaya. Jika input yang tidak tepercaya diizinkan, JavaScript yang tidak tepercaya dapat memanggil metode Android dalam aplikasi Anda. Secara umum, sebaiknya hanya perlihatkan addJavaScriptInterface()
ke JavaScript yang terdapat dalam APK aplikasi.
Jika aplikasi Anda mengakses data sensitif dengan WebView
, Anda mungkin perlu menggunakan metode clearCache()
untuk menghapus file yang disimpan secara lokal. Anda juga dapat menggunakan header sisi server seperti no-cache
untuk menunjukkan bahwa aplikasi tidak boleh meng-cache konten tertentu.
Perangkat yang menjalankan platform yang lebih lama dari Android 4.4 (API level 19) menggunakan versi webkit
yang memiliki sejumlah masalah keamanan.
Sebagai solusinya, jika aplikasi Anda berjalan di perangkat ini, aplikasi harus mengonfirmasi bahwa objek WebView
hanya menampilkan konten tepercaya. Untuk memastikan aplikasi Anda terhindar dari potensi kerentanan di SSL, gunakan objek Provider
keamanan yang dapat diperbarui seperti yang dijelaskan dalam Mengupdate Penyedia Keamanan agar Terlindung dari Exploit SSL. Jika aplikasi harus merender konten dari web terbuka, pertimbangkan untuk menyediakan perender Anda sendiri sehingga Anda dapat selalu mengupdatenya dengan patch keamanan terbaru.
Menangani kredensial
Untuk membuat serangan phising terlihat lebih jelas dan memperkecil kemungkinannya untuk berhasil, minimalkan frekuensi permintaan kredensial pengguna. Sebaiknya, gunakan token otorisasi dan refresh.
Jika memungkinkan, jangan menyimpan nama pengguna dan sandi di perangkat. Namun, lakukan autentikasi awal menggunakan nama pengguna dan sandi yang diberikan oleh pengguna, lalu gunakan token otorisasi khusus layanan berjangka pendek.
Layanan yang dapat diakses oleh beberapa aplikasi harus diakses menggunakan AccountManager
. Jika memungkinkan, gunakan class AccountManager
untuk memanggil layanan berbasis cloud dan jangan menyimpan sandi di perangkat.
Setelah menggunakan AccountManager
untuk mengambil Account
, gunakan CREATOR
sebelum meneruskan kredensial apa pun sehingga Anda tidak meneruskan kredensial secara tidak sengaja ke aplikasi yang salah.
Jika kredensial hanya digunakan oleh aplikasi yang Anda buat, Anda dapat memverifikasi aplikasi yang mengakses AccountManager
menggunakan checkSignature()
.
Atau, jika hanya ada satu aplikasi yang menggunakan kredensial, Anda dapat menggunakan KeyStore
untuk penyimpanan.
Menggunakan kriptografi
Selain menyediakan isolasi data, mendukung enkripsi sistem file penuh, dan menyediakan saluran komunikasi yang aman, Android juga memberikan beragam algoritme untuk melindungi data menggunakan kriptografi.
Secara umum, Anda harus tahu jenis penyedia keamanan Java Cryptography Architecture (JCA) yang digunakan software Anda. Cobalah untuk menggunakan tingkat implementasi framework tertinggi yang sudah ada sebelumnya, yang dapat mendukung kasus penggunaan Anda. Jika sesuai, gunakan penyedia yang disediakan Google dalam urutan yang ditentukan Google.
Untuk membaca dan menulis file lokal dengan lebih aman, gunakan library Keamanan.
Jika perlu mengambil file dengan aman dari lokasi jaringan yang diketahui, URI HTTPS sederhana mungkin sudah memadai dan tidak mengharuskan Anda memahami kriptografi. Jika memerlukan saluran yang aman, pertimbangkan penggunaan HttpsURLConnection
atau SSLSocket
, bukan menulis protokol Anda sendiri. Jika Anda menggunakan SSLSocket, perlu diketahui bahwa SSLSocket tidak melakukan verifikasi hostname. Lihat Peringatan tentang penggunaan SSLSocket secara langsung.
Jika merasa perlu mengimplementasikan protokol Anda sendiri, jangan implementasikan algoritme kriptografis milik Anda. Gunakan algoritme kriptografis yang ada, seperti implementasi AES dan RSA yang disediakan dalam class Cipher
. Selain itu, Anda harus mengikuti praktik terbaik berikut:
- Gunakan AES 256 bit untuk tujuan komersial. (Jika tidak tersedia, gunakan AES 128 bit).
- Gunakan kunci publik ukuran 224- atau 256 bit untuk kriptografi elliptic curve (EC).
- Ketahui kapan harus menggunakan mode blok CBC, CTR, atau GCM.
- Hindari penggunaan ulang IV/counter dalam mode CTR. Pastikan semuanya acak secara kriptografis.
- Saat menggunakan enkripsi, implementasikan integritas menggunakan mode CBC atau CTR dengan salah satu fungsi berikut:
- HMAC-SHA1
- HMAC-SHA-256
- HMAC-SHA-512
- Mode GCM
Gunakan generator angka acak yang aman, SecureRandom
, untuk menginisialisasi kunci kriptografis apa pun yang dibuat oleh KeyGenerator
.
Penggunaan kunci yang tidak dibuat dengan generator angka acak yang aman dapat secara signifikan melemahkan kekuatan algoritme, dan memungkinkan serangan offline.
Jika perlu menyimpan kunci untuk penggunaan berulang, gunakan mekanisme seperti KeyStore
yang menyediakan mekanisme untuk penyimpanan jangka panjang dan pengambilan kunci kriptografis.
Menggunakan komunikasi antarproses
Beberapa aplikasi mencoba untuk mengimplementasikan IPC menggunakan teknik Linux tradisional, seperti soket jaringan dan file bersama. Namun, Anda harus menggunakan fungsionalitas sistem Android untuk IPC seperti Intent
, Binder
, atau Messenger
dengan Service
, dan BroadcastReceiver
.
Mekanisme IPC Android memungkinkan Anda memverifikasi identitas aplikasi yang terhubung ke IPC dan menetapkan kebijakan keamanan bagi setiap mekanisme IPC.
Banyak elemen keamanan dibagikan dalam mekanisme IPC.
Jika mekanisme IPC Anda tidak dimaksudkan untuk digunakan oleh aplikasi lain, tetapkan atribut android:exported
ke false
dalam elemen manifes komponen, seperti untuk elemen <service>
. Cara ini berguna untuk aplikasi yang terdiri dari beberapa proses dalam UID yang sama, atau jika Anda baru membuat keputusan dalam proses pengembangan bahwa sebenarnya Anda tidak ingin menunjukkan fungsionalitas sebagai IPC, tetapi tidak ingin menulis ulang kodenya.
Jika IPC dapat diakses oleh aplikasi lain, Anda dapat menerapkan kebijakan keamanan menggunakan elemen <permission>
. Jika IPC berada di antara aplikasi Anda sendiri yang ditandatangani dengan kunci yang sama, sebaiknya gunakan izin tingkat signature
di android:protectionLevel
.
Menggunakan intent
Untuk aktivitas dan penerima siaran, intent adalah mekanisme yang lebih baik untuk IPC asinkron di Android.
Bergantung pada persyaratan aplikasi Anda, Anda dapat menggunakan sendBroadcast()
, sendOrderedBroadcast()
, atau intent eksplisit untuk komponen aplikasi tertentu. Untuk tujuan keamanan, sebaiknya gunakan intent eksplisit.
Perhatian: Jika Anda menggunakan intent untuk mengikat Service
, pastikan aplikasi Anda sudah aman dengan menggunakan intent eksplisit. Menggunakan intent implisit untuk memulai layanan dapat membahayakan keamanan, karena Anda tidak dapat memastikan layanan yang akan merespons intent tersebut, dan pengguna tidak dapat melihat layanan yang dimulai. Mulai dari Android 5.0 (API level 21), sistem akan menampilkan pengecualian jika Anda memanggil bindService()
dengan intent implisit.
Perlu diperhatikan bahwa siaran yang dipesan dapat dipakai oleh penerima sehingga tidak dapat dikirimkan ke semua aplikasi. Jika mengirim intent yang harus dikirimkan ke penerima tertentu, Anda harus menggunakan intent eksplisit yang menyatakan nama penerima.
Pengirim intent dapat memverifikasi bahwa penerima memiliki izin dengan menetapkan izin yang bukan null dengan panggilan metode. Hanya aplikasi dengan izin tersebut yang akan menerima intent. Jika data dalam intent siaran bersifat sensitif, Anda harus mempertimbangkan penerapan izin guna memastikan agar aplikasi berbahaya tidak dapat mendaftar untuk menerima pesan tersebut tanpa izin yang sesuai. Dalam situasi seperti itu, Anda juga dapat mempertimbangkan pemanggilan penerima secara langsung, daripada menaikkan siaran.
Catatan: Filter intent tidak boleh dianggap sebagai fitur keamanan. Komponen dapat dipanggil dengan intent eksplisit dan mungkin tidak memiliki data yang sesuai dengan filter intent. Untuk mengonfirmasi format yang benar bagi penerima, layanan, atau aktivitas yang dipanggil, lakukan validasi input di dalam penerima intent Anda.
Menggunakan layanan
Service
sering kali digunakan untuk menyediakan fungsionalitas yang perlu digunakan oleh aplikasi lain. Setiap class layanan harus memiliki deklarasi <service>
yang sesuai dalam file manifesnya.
Secara default, layanan tidak diekspor dan tidak dapat dipanggil oleh aplikasi lain. Namun, jika Anda menambahkan filter intent ke deklarasi layanan, pengeksporan akan dilakukan secara default. Sebaiknya deklarasikan atribut android:exported
secara eksplisit untuk memastikan perilakunya sesuai dengan keinginan Anda.
Layanan juga dapat dilindungi menggunakan atribut android:permission
. Dengan cara ini, aplikasi lain harus mendeklarasikan elemen <uses-permission>
yang sesuai dalam manifesnya agar dapat memulai, menghentikan, atau mengikat layanan.
Catatan: Jika aplikasi Anda menargetkan Android 5.0 (API level 21) atau yang lebih tinggi, sebaiknya gunakan JobScheduler
untuk menjalankan layanan latar belakang. Untuk informasi selengkapnya tentang JobScheduler
, lihat API-reference documentation
-nya.
Layanan dapat melindungi setiap panggilan IPC yang ditujukan padanya dengan izin, dengan memanggil checkCallingPermission()
sebelum mengeksekusi implementasi panggilan tersebut. Sebaiknya gunakan izin deklaratif dalam manifes karena lebih tahan terhadap pengawasan.
Perhatian: Jangan salah membedakan izin klien dan server; pastikan aplikasi yang dipanggil memiliki izin yang sesuai dan verifikasi bahwa Anda memberikan izin yang sama ke aplikasi yang memanggil.
Menggunakan antarmuka binder dan messenger
Menggunakan Binder
atau Messenger
adalah mekanisme yang dipilih untuk IPC bergaya RPC di Android. Keduanya menyediakan antarmuka dengan tampilan yang jelas dan memungkinkan autentikasi endpoint dua arah, jika diperlukan.
Sebaiknya desain antarmuka aplikasi Anda sedemikian rupa agar tidak memerlukan pemeriksaan izin khusus antarmuka. Objek Binder
dan Messenger
tidak dideklarasikan dalam manifes aplikasi sehingga Anda tidak dapat menerapkan izin deklaratif secara langsung pada keduanya. Objek tersebut umumnya mewarisi izin yang dinyatakan dalam manifes aplikasi untuk Service
atau Activity
tempatnya diimplementasikan. Jika akan membuat antarmuka yang memerlukan autentikasi dan/atau kontrol akses, Anda harus menambahkan kontrol tersebut secara eksplisit sebagai kode dalam antarmuka Binder
atau Messenger
.
Jika akan menyediakan antarmuka yang memerlukan kontrol akses, gunakan checkCallingPermission()
untuk memverifikasi apakah pemanggil memiliki izin yang diperlukan. Tindakan ini khususnya perlu dilakukan sebelum mengakses layanan atas nama pemanggil, karena identitas aplikasi Anda akan diteruskan ke antarmuka lain. Jika Anda memanggil antarmuka yang disediakan oleh Service
, pemanggilan bindService()
mungkin gagal jika Anda tidak memiliki izin untuk mengakses layanan yang diberikan.
Jika Anda memanggil antarmuka yang disediakan secara lokal oleh aplikasi Anda sendiri, akan lebih baik untuk menggunakan metode clearCallingIdentity()
, yang menyamarkan izin pemanggil terhadap izin aplikasi, untuk memenuhi pemeriksaan keamanan internal. Anda dapat memulihkan izin pemanggil nanti menggunakan metode restoreCallingIdentity()
.
Untuk mengetahui informasi selengkapnya tentang melakukan IPC dengan layanan, lihat Layanan Terikat.
Menggunakan penerima siaran
BroadcastReceiver
menangani permintaan asinkron yang diinisiasi oleh Intent
.
Secara default, penerima diekspor dan dapat dipanggil oleh aplikasi lain. Jika BroadcastReceiver
dimaksudkan untuk digunakan oleh aplikasi lain, Anda mungkin perlu menerapkan izin keamanan kepada penerima menggunakan elemen
<receiver>
dalam manifes aplikasi. Cara ini akan mencegah pengiriman intent ke BroadcastReceiver
oleh aplikasi yang tidak memiliki izin yang sesuai.
Memuat kode secara dinamis
Kami sangat tidak menyarankan pemuatan kode selain dari APK aplikasi Anda. Cara ini akan secara signifikan meningkatkan risiko penyerangan terhadap aplikasi karena injeksi kode atau sabotase kode. Cara ini juga menambah kerumitan pengelolaan versi dan pengujian aplikasi. Hal tersebut juga dapat membuat verifikasi perilaku aplikasi tidak mungkin dilakukan, sehingga di beberapa lingkungan mungkin dilarang.
Jika aplikasi Anda memuat kode secara dinamis, hal terpenting untuk diingat mengenai kode yang dimuat secara dinamis adalah bahwa kode berjalan dengan izin keamanan yang sama dengan APK aplikasi. Pengguna membuat keputusan untuk menginstal aplikasi berdasarkan identitas Anda, dan mengharapkan Anda untuk menyediakan setiap kode yang berjalan di dalam aplikasi, termasuk kode yang dimuat secara dinamis.
Risiko keamanan utama terkait pemuatan kode secara dinamis adalah kode harus berasal dari sumber yang dapat diverifikasi. Jika modul disertakan langsung ke dalam APK, modul tersebut tidak dapat diubah oleh aplikasi lain.
Hal ini akan tetap berlaku baik jika kodenya berupa library native atau class yang dimuat menggunakan DexClassLoader
. Beberapa aplikasi yang mencoba memuat kode dari lokasi yang tidak aman, seperti didownload dari jaringan melalui protokol tidak terenkripsi atau dari lokasi yang dapat ditulis oleh publik, seperti penyimpanan eksternal. Lokasi tersebut memungkinkan seseorang di jaringan untuk mengubah konten dalam proses transit, atau aplikasi lain di perangkat pengguna untuk mengubah konten di perangkat.
Keamanan dalam mesin virtual
Dalvik adalah mesin virtual (VM) waktu proses Android. Dalvik secara khusus dibuat untuk Android, tetapi berbagai kekhawatiran terkait kode aman di mesin virtual lainnya juga berlaku untuk Android. Biasanya, Anda tidak perlu mengkhawatirkan masalah keamanan yang menyangkut mesin virtual. Aplikasi Anda berjalan di lingkungan sandbox yang aman, sehingga proses lain pada sistem tidak dapat mengakses kode atau data pribadi Anda.
Jika Anda tertarik mempelajari keamanan mesin virtual lebih lanjut, pahami beberapa literatur yang ada pada topik ini. Dua contoh referensi yang populer antara lain:
Dokumen ini berfokus pada area khusus Android atau area yang berbeda dengan lingkungan VM lainnya. Untuk developer yang berpengalaman dengan pemrograman VM di lingkungan lain, ada dua persoalan umum yang mungkin berbeda tentang penulisan aplikasi untuk Android:
- Beberapa mesin virtual, seperti JVM atau .NET runtime, berfungsi sebagai batasan keamanan, yang mengisolasi kode dari kemampuan sistem operasi yang mendasarinya. Di Android, VM Dalvik bukanlah batasan keamanan, sandbox aplikasinya diimplementasikan di tingkat OS, sehingga Dalvik dapat saling bertukar dan menggunakan data dengan kode native di aplikasi yang sama tanpa kendala keamanan apa pun.
- Dengan keterbatasan penyimpanan di perangkat seluler, sering kali developer ingin membuat aplikasi modular dan menggunakan pemuatan class dinamis. Saat melakukannya, pertimbangkan kedua sumber tempat Anda mengambil logika aplikasi dan tempat Anda menyimpannya secara lokal. Jangan gunakan pemuatan class dinamis dari sumber yang tidak diverifikasi, seperti sumber jaringan yang tidak aman atau penyimpanan eksternal, karena kode dapat dimodifikasi untuk dimasukkan ke dalam perilaku berbahaya.
Keamanan dalam kode native
Umumnya, sebaiknya gunakan Android SDK untuk pengembangan aplikasi, bukan kode native dengan Android NDK. Aplikasi yang dibuat dengan kode native akan lebih rumit, kurang ringkas, dan sering kali memiliki error kerusakan memori umum, seperti buffer overflow.
Android dibuat menggunakan kernel Linux. Oleh karena itu, memahami praktik terbaik keamanan pengembangan Linux sangat berguna jika Anda menggunakan kode native. Praktik keamanan Linux tidak termasuk dalam cakupan dokumen ini, tetapi salah satu referensi yang populer adalah Secure Programming HOWTO - Creating Secure Software.
Perbedaan penting antara Android dan sebagian besar lingkungan Linux terletak pada Sandbox Aplikasi. Di Android, semua aplikasi berjalan di Sandbox Aplikasi, termasuk aplikasi yang ditulis dengan kode native. Pada tingkat yang paling dasar, pertimbangan terbaik bagi developer yang sudah terbiasa dengan Linux adalah mengetahui bahwa setiap aplikasi diberi UID unik dengan izin yang sangat terbatas. Hal ini dibahas secara mendetail dalam Ringkasan Keamanan Android, dan Anda harus sudah memahami izin aplikasi meskipun menggunakan kode native.