Kategori OWASP: MASVS-CODE: Kualitas Kode
Ringkasan
Tidak jarang kita melihat aplikasi yang menerapkan fungsi yang memungkinkan pengguna mentransfer data, atau berinteraksi dengan perangkat lain, menggunakan komunikasi frekuensi radio (RF) atau koneksi kabel. Teknologi yang paling umum digunakan di Android untuk tujuan ini adalah Bluetooth klasik (Bluetooth BR/EDR), Bluetooth Hemat Energi (BLE), Wifi P2P, NFC, dan USB.
Teknologi ini biasanya diterapkan dalam aplikasi yang diharapkan dapat berkomunikasi dengan aksesori smart home, perangkat pemantauan kesehatan, kios transportasi umum, terminal pembayaran, dan perangkat lain yang didukung Android.
Seperti saluran lainnya, komunikasi antar-mesin rentan terhadap serangan yang bertujuan untuk membahayakan batas kepercayaan yang ditetapkan antara dua perangkat atau lebih. Teknik seperti peniruan identitas perangkat dapat dimanfaatkan oleh pengguna berbahaya untuk mencapai sejumlah besar serangan terhadap saluran komunikasi.
API ini harus digunakan dengan hati-hati karena error saat menerapkan protokol komunikasi dapat menyebabkan data pengguna atau perangkat terekspos ke pihak ketiga yang tidak sah. Dalam skenario terburuk, penyerang mungkin dapat mengambil alih satu atau beberapa perangkat dari jarak jauh, sehingga mendapatkan akses penuh ke konten di perangkat.
Dampak
Dampak dapat bervariasi menurut teknologi perangkat ke perangkat yang diterapkan dalam aplikasi.
Penggunaan atau konfigurasi saluran komunikasi antar-mesin yang salah dapat membuat perangkat pengguna terekspos ke upaya komunikasi yang tidak tepercaya. Hal ini dapat menyebabkan perangkat rentan terhadap serangan tambahan seperti man-in-the-middle (MiTM), injeksi perintah, DoS, atau serangan peniruan identitas.
Risiko: Penyusupan data sensitif melalui saluran nirkabel
Saat menerapkan mekanisme komunikasi antar-mesin, pertimbangan yang cermat harus diberikan pada teknologi yang digunakan dan jenis data yang harus ditransmisikan. Meskipun koneksi kabel pada praktiknya lebih aman untuk tugas semacam itu, karena memerlukan link fisik antara perangkat yang terlibat, protokol komunikasi yang menggunakan frekuensi radio seperti Bluetooth klasik, BLE, NFC, dan Wifi P2P dapat dicegat. Penyerang mungkin dapat meniru identitas salah satu terminal atau titik akses yang terlibat dalam pertukaran data, mencegat komunikasi melalui udara, sehingga mendapatkan akses ke data pengguna yang sensitif. Selain itu, aplikasi berbahaya yang diinstal di perangkat, jika diberi izin runtime khusus komunikasi, mungkin dapat mengambil data yang dipertukarkan antar-perangkat dengan membaca buffer pesan sistem.
Mitigasi
Jika aplikasi memerlukan pertukaran data sensitif antar-mesin melalui saluran nirkabel, solusi keamanan lapisan aplikasi, seperti enkripsi, harus diterapkan dalam kode aplikasi. Hal ini akan mencegah penyerang mengendus saluran komunikasi dan mengambil data yang dipertukarkan dalam teks yang jelas. Untuk mengetahui resource tambahan, lihat dokumentasi Kriptografi.
Risiko: Injeksi data berbahaya nirkabel
Saluran komunikasi antar-mesin nirkabel (Bluetooth klasik, BLE, NFC, Wifi P2P) dapat dirusak menggunakan data berbahaya. Penyerang yang cukup terampil dapat mengidentifikasi protokol komunikasi yang digunakan dan merusak alur pertukaran data, misalnya dengan meniru identitas salah satu endpoint, mengirim payload yang dibuat secara khusus. Traffic berbahaya semacam ini dapat menurunkan kualitas fungsi aplikasi dan, dalam skenario terburuk, menyebabkan perilaku aplikasi dan perangkat yang tidak terduga, atau mengakibatkan serangan seperti DoS, injeksi perintah, atau pengambilalihan perangkat.
Mitigasi
Android menyediakan API yang canggih bagi developer untuk mengelola komunikasi antar-mesin seperti Bluetooth klasik, BLE, NFC, dan Wifi P2P. API ini harus digabungkan dengan logika validasi data yang diterapkan dengan cermat untuk membersihkan data apa pun yang dipertukarkan antara dua perangkat.
Solusi ini harus diterapkan di tingkat aplikasi dan harus menyertakan pemeriksaan yang memverifikasi apakah data memiliki panjang, format, dan berisi payload valid yang dapat ditafsirkan oleh aplikasi.
Cuplikan berikut menunjukkan contoh logika validasi data. Hal ini diterapkan melalui contoh developer Android untuk menerapkan transfer data Bluetooth:
Kotlin
class MyThread(private val mmInStream: InputStream, private val handler: Handler) : Thread() {
private val mmBuffer = ByteArray(1024)
override fun run() {
while (true) {
try {
val numBytes = mmInStream.read(mmBuffer)
if (numBytes > 0) {
val data = mmBuffer.copyOf(numBytes)
if (isValidBinaryData(data)) {
val readMsg = handler.obtainMessage(
MessageConstants.MESSAGE_READ, numBytes, -1, data
)
readMsg.sendToTarget()
} else {
Log.w(TAG, "Invalid data received: $data")
}
}
} catch (e: IOException) {
Log.d(TAG, "Input stream was disconnected", e)
break
}
}
}
private fun isValidBinaryData(data: ByteArray): Boolean {
if (// Implement data validation rules here) {
return false
} else {
// Data is in the expected format
return true
}
}
}
Java
public void run() {
mmBuffer = new byte[1024];
int numBytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs.
while (true) {
try {
// Read from the InputStream.
numBytes = mmInStream.read(mmBuffer);
if (numBytes > 0) {
// Handle raw data directly
byte[] data = Arrays.copyOf(mmBuffer, numBytes);
// Validate the data before sending it to the UI activity
if (isValidBinaryData(data)) {
// Data is valid, send it to the UI activity
Message readMsg = handler.obtainMessage(
MessageConstants.MESSAGE_READ, numBytes, -1,
data);
readMsg.sendToTarget();
} else {
// Data is invalid
Log.w(TAG, "Invalid data received: " + data);
}
}
} catch (IOException e) {
Log.d(TAG, "Input stream was disconnected", e);
break;
}
}
}
private boolean isValidBinaryData(byte[] data) {
if (// Implement data validation rules here) {
return false;
} else {
// Data is in the expected format
return true;
}
}
Risiko: Injeksi data berbahaya USB
Koneksi USB antara dua perangkat dapat ditargetkan oleh pengguna berbahaya yang tertarik untuk mencegat komunikasi. Dalam hal ini, link fisik yang diperlukan merupakan lapisan keamanan tambahan karena penyerang harus mendapatkan akses ke kabel yang menghubungkan terminal agar dapat menyadap pesan apa pun. Vektor serangan lain diwakili oleh perangkat USB yang tidak tepercaya yang, baik secara sengaja maupun tidak sengaja, dicolokkan ke perangkat.
Jika aplikasi memfilter perangkat USB menggunakan PID/VID untuk memicu fungsi dalam aplikasi tertentu, penyerang mungkin dapat merusak data yang dikirim melalui saluran USB dengan meniru identitas perangkat yang sah. Serangan semacam ini dapat memungkinkan pengguna berbahaya mengirim penekanan tombol ke perangkat atau menjalankan aktivitas aplikasi yang, dalam kasus terburuk, dapat menyebabkan eksekusi kode jarak jauh atau download software yang tidak diinginkan.
Mitigasi
Logika validasi tingkat aplikasi harus diterapkan. Logika ini harus memfilter data yang dikirim melalui USB dengan memeriksa bahwa panjang, format, dan konten cocok dengan kasus penggunaan aplikasi. Misalnya, monitor detak jantung tidak boleh dapat mengirim perintah penekanan tombol.
Selain itu, jika memungkinkan, pertimbangkan untuk membatasi jumlah paket USB yang dapat diterima aplikasi dari perangkat USB. Hal ini mencegah perangkat berbahaya melakukan serangan seperti rubber ducky.
Validasi ini dapat dilakukan dengan membuat thread baru untuk memeriksa konten
buffer, misalnya, saat bulkTransfer:
Kotlin
fun performBulkTransfer() {
// Stores data received from a device to the host in a buffer
val bytesTransferred = connection.bulkTransfer(endpointIn, buffer, buffer.size, 5000)
if (bytesTransferred > 0) {
if (//Checks against buffer content) {
processValidData(buffer)
} else {
handleInvalidData()
}
} else {
handleTransferError()
}
}
Java
public void performBulkTransfer() {
//Stores data received from a device to the host in a buffer
int bytesTransferred = connection.bulkTransfer(endpointIn, buffer, buffer.length, 5000);
if (bytesTransferred > 0) {
if (//Checks against buffer content) {
processValidData(buffer);
} else {
handleInvalidData();
}
} else {
handleTransferError();
}
}
Risiko Spesifik
Bagian ini mengumpulkan risiko yang memerlukan strategi mitigasi non-standar atau dimitigasi di tingkat SDK tertentu dan dilakukan untuk menyelesaikan.
Risiko: Bluetooth – waktu penemuan yang salah
Seperti yang ditunjukkan dalam dokumentasi Bluetooth developer Android, saat
mengonfigurasi antarmuka Bluetooth dalam aplikasi, menggunakan metode
startActivityForResult(Intent, int) untuk mengaktifkan penemuan perangkat dan menetapkan EXTRA_DISCOVERABLE_DURATION ke nol akan
menyebabkan perangkat dapat ditemukan selama aplikasi berjalan di latar belakang atau latar depan. Untuk spesifikasi Bluetooth klasik, perangkat yang dapat ditemukan terus-menerus menyiarkan pesan penemuan tertentu
yang memungkinkan perangkat lain mengambil data perangkat atau terhubung ke perangkat tersebut. Dalam skenario seperti itu, pihak ketiga yang berbahaya dapat mencegat pesan tersebut dan terhubung ke perangkat yang didukung Android. Setelah terhubung, penyerang dapat melakukan serangan lebih lanjut seperti pencurian data, DoS, atau injeksi perintah.
Mitigasi
EXTRA_DISCOVERABLE_DURATION tidak boleh ditetapkan ke nol. Jika parameter EXTRA_DISCOVERABLE_DURATION tidak ditetapkan, secara default, Android akan membuat perangkat dapat ditemukan selama 2 menit. Nilai maksimum yang dapat ditetapkan untuk parameter EXTRA_DISCOVERABLE_DURATION adalah 2 jam (7.200 detik). Sebaiknya pertahankan waktu durasi penemuan ke waktu sesingkat mungkin, sesuai dengan kasus penggunaan aplikasi.
Risiko: NFC – filter intent yang dikloning
Aplikasi berbahaya dapat mendaftarkan filter intent untuk membaca tag NFC atau perangkat yang mendukung NFC tertentu. Filter ini dapat mereplikasi filter yang ditentukan oleh aplikasi yang sah, sehingga memungkinkan penyerang membaca konten data NFC yang dipertukarkan. Perlu diperhatikan bahwa, jika dua aktivitas menentukan filter intent yang sama untuk tag NFC tertentu, Pemilih Aktivitas akan ditampilkan, sehingga pengguna tetap harus memilih aplikasi berbahaya agar serangan berhasil. Namun, dengan menggabungkan filter intent dengan cloaking, skenario ini masih memungkinkan. Serangan ini hanya signifikan untuk kasus saat data yang dipertukarkan melalui NFC dapat dianggap sangat sensitif.
Mitigasi
Saat menerapkan kemampuan membaca NFC dalam aplikasi, filter intent dapat digunakan bersama dengan catatan aplikasi Android (AAR). Menyematkan catatan AAR di dalam pesan NDEF akan memberikan jaminan yang kuat bahwa hanya aplikasi yang sah, dan aktivitas penanganan NDEF terkait, yang akan dimulai. Hal ini akan mencegah aplikasi atau aktivitas yang tidak diinginkan membaca data tag atau perangkat yang sangat sensitif yang dipertukarkan melalui NFC.
Risiko: NFC – kurangnya validasi pesan NDEF
Saat perangkat yang didukung Android menerima data dari tag NFC atau perangkat yang mendukung NFC, sistem akan otomatis memicu aplikasi atau aktivitas tertentu yang dikonfigurasi untuk menangani pesan NDEF yang ada di dalamnya. Menurut logika yang diterapkan dalam aplikasi, data yang terdapat dalam tag, atau diterima dari perangkat, dapat ditayangkan ke aktivitas lain untuk memicu tindakan lebih lanjut, seperti membuka halaman web.
Aplikasi yang tidak memiliki validasi konten pesan NDEF dapat memungkinkan penyerang menggunakan perangkat yang mendukung NFC atau tag NFC untuk menyuntikkan payload berbahaya dalam aplikasi, sehingga menyebabkan perilaku yang tidak terduga yang dapat mengakibatkan download file berbahaya, injeksi perintah, atau DoS.
Mitigasi
Sebelum mengirim pesan NDEF yang diterima ke komponen aplikasi lainnya, data di dalamnya harus divalidasi agar berada dalam format yang diharapkan dan berisi informasi yang diharapkan. Hal ini menghindari data berbahaya yang diteruskan ke komponen aplikasi lain tanpa difilter, sehingga mengurangi risiko perilaku atau serangan yang tidak terduga menggunakan data NFC yang dirusak.
Cuplikan berikut menunjukkan contoh logika validasi data yang diterapkan sebagai metode dengan pesan NDEF sebagai argumen dan indeksnya dalam array pesan. Hal ini diterapkan melalui contoh developer Android example untuk mendapatkan data dari tag NDEF NFC yang dipindai:
Kotlin
//The method takes as input an element from the received NDEF messages array
fun isValidNDEFMessage(messages: Array<NdefMessage>, index: Int): Boolean {
// Checks if the index is out of bounds
if (index < 0 || index >= messages.size) {
return false
}
val ndefMessage = messages[index]
// Retrieves the record from the NDEF message
for (record in ndefMessage.records) {
// Checks if the TNF is TNF_ABSOLUTE_URI (0x03), if the Length Type is 1
if (record.tnf == NdefRecord.TNF_ABSOLUTE_URI && record.type.size == 1) {
// Loads payload in a byte array
val payload = record.payload
// Declares the Magic Number that should be matched inside the payload
val gifMagicNumber = byteArrayOf(0x47, 0x49, 0x46, 0x38, 0x39, 0x61) // GIF89a
// Checks the Payload for the Magic Number
for (i in gifMagicNumber.indices) {
if (payload[i] != gifMagicNumber[i]) {
return false
}
}
// Checks that the Payload length is, at least, the length of the Magic Number + The Descriptor
if (payload.size == 13) {
return true
}
}
}
return false
}
Java
//The method takes as input an element from the received NDEF messages array
public boolean isValidNDEFMessage(NdefMessage[] messages, int index) {
//Checks if the index is out of bounds
if (index < 0 || index >= messages.length) {
return false;
}
NdefMessage ndefMessage = messages[index];
//Retrieve the record from the NDEF message
for (NdefRecord record : ndefMessage.getRecords()) {
//Check if the TNF is TNF_ABSOLUTE_URI (0x03), if the Length Type is 1
if ((record.getTnf() == NdefRecord.TNF_ABSOLUTE_URI) && (record.getType().length == 1)) {
//Loads payload in a byte array
byte[] payload = record.getPayload();
//Declares the Magic Number that should be matched inside the payload
byte[] gifMagicNumber = {0x47, 0x49, 0x46, 0x38, 0x39, 0x61}; // GIF89a
//Checks the Payload for the Magic Number
for (int i = 0; i < gifMagicNumber.length; i++) {
if (payload[i] != gifMagicNumber[i]) {
return false;
}
}
//Checks that the Payload length is, at least, the length of the Magic Number + The Descriptor
if (payload.length == 13) {
return true;
}
}
}
return false;
}
Resource
- Izin Runtime
- Panduan konektivitas
- Contoh
- bulkTransfer
- Kriptografi
- Menyiapkan Bluetooth
- Dasar-Dasar NFC
- Catatan aplikasi Android
- Spesifikasi Bluetooth klasik