Kategori OWASP: MASVS-CODE: Kualitas Kode
Ringkasan
Tidak jarang aplikasi 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 dalam Android untuk tujuan ini adalah Bluetooth klasik (Bluetooth BR/EDR), Bluetooth Rendah Energi (BLE), Wi-Fi P2P, NFC, dan USB.
Teknologi ini biasanya diterapkan dalam aplikasi yang diharapkan berkomunikasi dengan aksesori smart home, perangkat pemantauan kesehatan, kios transportasi umum, terminal pembayaran, dan perangkat Android lainnya.
Seperti saluran lainnya, komunikasi mesin ke mesin rentan terhadap serangan yang bertujuan untuk membahayakan batas kepercayaan yang ditetapkan antara dua atau beberapa perangkat. Teknik seperti peniruan identitas perangkat dapat dimanfaatkan oleh pengguna berbahaya untuk melakukan serangan yang luas terhadap komunikasi saluran TV Anda.
Android menyediakan API tertentu untuk mengonfigurasi komunikasi mesin ke mesin bagi developer.
API ini harus digunakan dengan hati-hati sebagai error saat menerapkan dapat menyebabkan data pengguna atau perangkat terekspos ke data yang pihak ketiga. Dalam skenario terburuk, penyerang mungkin dapat mengambil alih satu atau beberapa perangkat dari jarak jauh, sehingga mendapatkan akses penuh ke konten di perangkat.
Dampak
Dampaknya dapat bervariasi sesuai dengan teknologi perangkat ke perangkat yang diterapkan di aplikasi.
Penggunaan atau konfigurasi saluran komunikasi mesin ke mesin yang salah dapat membuat perangkat pengguna terekspos ke upaya komunikasi yang tidak tepercaya. Hal ini dapat menyebabkan perangkat menjadi rentan terhadap serangan tambahan seperti {i>man-in-the-middle (MiTM), injeksi perintah, DoS, <i} serangan peniruan identitas.
Risiko: Penyadap data sensitif melalui saluran nirkabel
Saat menerapkan mekanisme komunikasi mesin ke mesin, pertimbangan yang cermat harus diberikan pada teknologi yang digunakan dan jenis data yang harus dikirim. Sementara koneksi kabel dalam praktiknya lebih aman untuk tugas seperti itu, karena mereka memerlukan tautan fisik antara perangkat yang terlibat, protokol komunikasi yang menggunakan frekuensi radio seperti Bluetooth klasik, BLE, NFC, dan Wi-Fi P2P dapat dicegat. Penyerang mungkin dapat meniru 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 antarperangkat dengan membaca buffering pesan sistem.
Mitigasi
Jika aplikasi memang memerlukan pertukaran data sensitif dari mesin ke mesin melalui saluran nirkabel, solusi keamanan lapisan aplikasi, seperti enkripsi, harus diterapkan dalam kode aplikasi. Hal ini akan mencegah penyerang untuk mengendus saluran komunikasi dan mengambil dipertukarkan data dalam teks yang jelas. Untuk referensi tambahan, lihat dokumentasi Kriptografi.
Risiko: Injeksi data berbahaya nirkabel
Saluran komunikasi mesin ke mesin nirkabel (Bluetooth klasik, BLE, NFC, Wifi P2P) dapat dimodifikasi menggunakan data berbahaya. Penyerang yang cukup terampil dapat mengidentifikasi protokol komunikasi yang digunakan dan merusak alur pertukaran data, misalnya dengan meniru salah satu endpoint, mengirim payload yang dibuat secara khusus. Lalu lintas berbahaya semacam ini dapat menurunkan fungsi aplikasi dan, dalam skenario terburuk, menyebabkan kejadian yang tak terduga perilaku aplikasi dan perangkat pengguna, atau mengakibatkan serangan seperti DoS, perintah injeksi, atau pengambilalihan perangkat.
Mitigasi
Android menyediakan API yang canggih bagi developer untuk mengelola komunikasi antar-mesin seperti Bluetooth klasik, BLE, NFC, dan Wi-Fi P2P. Hal ini harus dikombinasikan dengan logika validasi data yang diterapkan dengan hati-hati untuk membersihkan data apa pun yang dipertukarkan antara dua perangkat.
Solusi ini harus diterapkan di tingkat aplikasi dan harus mencakup pemeriksaan yang memverifikasi apakah data tersebut memiliki panjang, format, dan berisi payload valid yang dapat diinterpretasikan oleh aplikasi.
Cuplikan berikut menunjukkan contoh logika validasi data. Hal ini diimplementasikan melalui contoh developer Android untuk mengimplementasikan 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 disasar oleh pengguna yang berbahaya yang tertarik untuk mencegat komunikasi. Dalam hal ini, link fisik yang diperlukan merupakan lapisan keamanan tambahan karena penyerang perlu mendapatkan akses ke kabel yang menghubungkan terminal agar dapat menguping pesan apa pun. Vektor serangan lainnya diwakili oleh perangkat USB yang tidak tepercaya yang, baik disengaja maupun tidak disengaja, dicolokkan ke perangkat.
Jika aplikasi memfilter perangkat USB menggunakan PID/VID untuk memicu fungsi dalam aplikasi, penyerang mungkin dapat mengutak-atik data yang dikirim saluran USB dengan cara meniru identitas perangkat yang sah. Serangan semacam ini bisa memungkinkan pengguna berbahaya mengirim penekanan ke perangkat atau menjalankan aplikasi aktivitas yang, dalam kasus terburuk, dapat menyebabkan eksekusi kode jarak jauh atau unduhan perangkat lunak yang tidak diinginkan.
Mitigasi
Logika validasi tingkat aplikasi harus diterapkan. Logika ini harus menyaring data yang dikirim melalui USB untuk memeriksa bahwa panjang, format, dan isi cocok dengan kasus penggunaan aplikasinya. Misalnya, monitor detak jantung tidak boleh dapat mengirim perintah tombol.
Selain itu, jika memungkinkan, pertimbangan harus diberikan untuk membatasi jumlah paket USB yang dapat diterima aplikasi dari perangkat USB. Tindakan ini mencegah perangkat berbahaya melakukan serangan seperti rubber ducky.
Validasi ini dapat dilakukan dengan membuat thread baru untuk memeriksa
melakukan buffer konten, misalnya, pada 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 visibilitas yang salah
Seperti yang disoroti dalam dokumentasi Bluetooth developer Android, saat
mengonfigurasi antarmuka Bluetooth dalam aplikasi, menggunakan
metode startActivityForResult(Intent, int)
untuk mengaktifkan visibilitas
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 menyiarkan penemuan tertentu
pesan yang memungkinkan perangkat lain mengambil data perangkat atau terhubung ke perangkat tersebut. Dalam
skenario tersebut, pihak ketiga yang berbahaya dapat mencegat pesan tersebut dan terhubung
ke perangkat yang didukung Android. Setelah terhubung, penyerang
dapat melakukan serangan
serangan 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 (7200 detik). Penting
disarankan untuk menjaga durasi waktu yang dapat ditemukan menjadi waktu tersingkat
memungkinkan, sesuai dengan kasus penggunaan aplikasi.
Risiko: NFC – filter intent yang di-clone
Aplikasi berbahaya dapat mendaftarkan filter intent untuk membaca tag NFC tertentu atau Perangkat yang mendukung NFC. Filter ini dapat mereplikasi filter yang ditentukan oleh yang sah, sehingga memungkinkan penyerang untuk membaca konten data NFC yang dipertukarkan. Perlu dicatat bahwa, ketika dua aktivitas menentukan filter intent yang sama untuk tag NFC tertentu, Pemilih Aktivitas ditampilkan, oleh karena itu pengguna masih harus memilih aplikasi agar serangan itu berhasil. Meskipun demikian, menggabungkan filter intent dengan penyelubungan, 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 data aplikasi Android (AAR). Menyematkan Data AAR di dalam pesan NDEF akan memberikan jaminan kuat bahwa hanya aplikasi yang sah, dan aktivitas penanganan NDEF yang terkait, 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 Android menerima data dari tag NFC atau perangkat yang kompatibel dengan NFC, sistem akan otomatis memicu aplikasi atau aktivitas tertentu yang dikonfigurasi untuk menangani pesan NDEF yang ada di dalamnya. Menurut logika yang diimplementasikan 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 berkemampuan NFC atau tag NFC untuk memasukkan payload berbahaya dalam aplikasi, sehingga menyebabkan perilaku 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 dalam format yang diharapkan dan berisi informasi yang diharapkan. Hal ini untuk menghindari pengiriman data berbahaya ke tanpa filter, mengurangi risiko perilaku yang tak terduga atau serangan yang menggunakan data NFC yang dimodifikasi.
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 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;
}
Referensi
- Izin Runtime
- Panduan konektivitas
- Contoh
- massalTransfer
- Kriptografi
- Menyiapkan Bluetooth
- NFC Basis
- Data aplikasi Android
- Spesifikasi Bluetooth klasik