Güvenli olmayan makineden makineye iletişim kurulumu

OWASP kategorisi: MASVS-CODE: Kod Kalitesi

Genel Bakış

Kullanıcıların şunu yapmasına olanak tanıyan işlevler uygulayan uygulamalar nadirdir; Radyo frekansı (RF) kullanarak veri aktarmak veya diğer cihazlarla etkileşimde bulunmak kablolu bağlantılardan yararlanmamalıdır. Android'de bu amaçla kullanılan en yaygın teknolojiler klasik Bluetooth (Bluetooth BR/EDR), Bluetooth Düşük Enerji (BDE), kablosuz P2P, NFC ve USB'dir.

Bu teknolojiler genellikle akıllı ev aksesuarları, sağlık izleme cihazları, toplu taşıma kioskları, ödeme terminalleri ve Android destekli diğer cihazlarla iletişim kurması beklenen uygulamalarda uygulanır.

Diğer kanallarda olduğu gibi, makineden makineye iletişim, iki veya daha fazla yayıncı arasında kurulan güven sınırını tehlikeye atmayı amaçlayan saldırılar daha fazla cihaz. Cihaz kimliğine bürünme gibi teknikler, kötü amaçlı kullanıcılar tarafından iletişim kanalına karşı çok sayıda saldırı gerçekleştirmek için kullanılabilir.

Android, makineler arasında yapılandırmaya yönelik belirli API'ler geliştirir. geliştiricilerin kullanımına sunulan iletişim yöntemleridir.

İletişim uygulanırken bu API'ler hata olarak dikkatle kullanılmalıdır protokolleri, kullanıcı veya cihaz verilerinin yetkisiz olarak açığa çıkmasına üçüncü taraflardan sorumlu olacaktır. En kötü senaryoda, saldırganlar güvenlik açığını bir veya daha fazla cihazı ele geçirerek cihazdaki içeriğe tam erişim imkanı elde etti cihaz üzerinde.

Etki

Sorunun etkisi, takip edebilirsiniz.

Makine ile makine arasında iletişim kanallarının yanlış kullanımı veya yapılandırılması, kullanıcı cihazını güvenilmeyen iletişim girişimlerine açık hale getirebilir. Bu durum, cihazın güvenlik açığına ortadaki adam (MiTM), komut yerleştirme, DoS (DoS) veya Kimliğe Bürünme Saldırısı.

Risk: Hassas verilerin kablosuz kanallar üzerinden dinlenmesi

Makineler arası iletişim mekanizmalarını uygularken hem kullanılan teknoloji hem de veri türü göz önünde bulundurulmalıdır iletilebilir. Kablolu bağlantılar, ilgili cihazlar arasında fiziksel bir bağlantı gerektirdiği için bu tür görevler için pratikte daha güvenli olsa da klasik Bluetooth, BLE, NFC ve Wifi P2P gibi radyo frekanslarını kullanan iletişim protokollerinin akışı kesilebilir. Bir saldırgan, veri alışverişinde bulunan terminallerden veya erişim noktalarından birinin kimliğine bürünerek kablosuz iletişimi kesebilir ve sonuç olarak hassas kullanıcı verilerine erişebilir. Ayrıca, izin verilirse cihazda yüklü kötü amaçlı uygulamalar iletişime özel çalışma zamanı izinlerini sistem mesaj arabelleklerini okuyarak cihazlar arasında veri alışverişi sağlar.

Çözümler

Uygulama, hassas verilerin makineler arasında değişimini gerektiriyorsa kablosuz kanallar üzerinden, ardından uygulama katmanında güvenlik çözümleri uygulamanın koduna uygulanması gerekir. Bu, saldırganların iletişim kanalını taramasını ve değiştirilen verileri açık metin olarak almasını engeller. Ek kaynaklar için Kriptografi dokümanlarına bakın.


Risk: Kötü amaçlı kablosuz veri ekleme

Makineler arası kablosuz iletişim kanalları (klasik Bluetooth, BDE, NFC, kablosuz eşler arası ağ), kötü amaçlı veriler kullanılarak bozulabilir. Yeterli beceriye sahip kullanılan iletişim protokolünü tanımlayıp uç noktalardan birinin kimliğine bürünerek, uç noktanın kimliğine bürünerek özel olarak işlenmiş yükler. Bu tür kötü amaçlı trafik, uygulamanın işlevini bozabilir ve en kötü durumda uygulama ile cihazda beklenmedik davranışlara neden olabilir ya da DoS, komut ekleme veya cihaz ele geçirme gibi saldırılara yol açabilir.

Çözümler

Android, klasik Bluetooth, BLE, NFC ve Wifi P2P gibi makineden makineye iletişimleri yönetmek için geliştiricilere güçlü API'ler sağlar. Bu önlemler, iki cihaz arasında paylaşılan verilerin temizlenmesi için dikkatli bir şekilde uygulanmış bir veri doğrulama mantığıyla birleştirilmelidir.

Bu çözüm uygulama düzeyinde uygulanmalı ve verilerin beklenen uzunlukta, biçimde olup olmadığını ve uygulama tarafından yorumlanabilecek geçerli bir yükü içerip içermediğini doğrulayan kontroller içermelidir.

Aşağıdaki snippet'te örnek veri doğrulama mantığı gösterilmektedir. Uygulandı Android geliştiricileri için Bluetooth verilerini uygulama örneğine bakın. aktarma:

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;
           }
    }

Risk: USB'ye kötü amaçlı veri yerleştirme

İki cihaz arasındaki USB bağlantıları, iletişimi kesmek isteyen kötü amaçlı kullanıcılar tarafından hedeflenebilir. Bu durumda, ek bir güvenlik katmanı oluşturur, çünkü saldırganın hiçbir cihazı gizlice dinleyebilmek için terminalleri bağlayan kabloya mesajını alırsınız. İster kasıtlı ister kasıtsız olarak cihaza takılan güvenilmeyen USB cihazlar da başka bir saldırı vektörüdür.

Uygulama, belirli tetiklemeler için USB cihazları PID/VID kullanarak filtreliyorsa olduğu gibi, saldırganlar size gönderilen verilerde değişiklik yapabilirler. meşru cihazın kimliğine bürünerek USB kanalını kapatır. Bu tür saldırılar, kötü amaçlı kullanıcıların cihaza tuş vuruşları göndermesine veya en kötü durumda uzaktan kod yürütmeye ya da istenmeyen yazılım indirmeye yol açabilecek uygulama etkinlikleri gerçekleştirmesine olanak tanıyabilir.

Çözümler

Uygulama düzeyinde bir doğrulama mantığı uygulanmalıdır. Bu mantık, USB üzerinden gönderilen verileri filtreleyerek uzunluğun, biçimin ve içeriğin uygulama kullanım alanına uyup uymadığını kontrol eder. Örneğin, kalp atış hızı monitörü tuş vuruşu komutları gönderememelidir.

Ayrıca, mümkün olduğunda uygulamanın USB cihazdan alabileceği USB paketi sayısının kısıtlanmasına dikkat edilmelidir. Bu, kötü amaçlı cihazların ördek gibi saldırılar gerçekleştirmesini engeller.

Bu doğrulama, arabelleğe alma (örneğin, bir bulkTransfer üzerine):

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();
        }
    }

Belirli Riskler

Bu bölümde, standart olmayan azaltma stratejileri gerektiren veya belirli bir SDK düzeyinde azaltılan riskler toplanmıştır. Bu riskler, eksiksiz bir liste sunmak için burada yer almaktadır.

Risk: Bluetooth – yanlış bulunabilirlik süresi

Android geliştiricilerinin Bluetooth dokümanlarında belirtildiği gibi, uygulama içinde Bluetooth arayüzünü yapılandırırken cihazın bulunabilirliğini etkinleştirmek için startActivityForResult(Intent, int) yöntemini kullanmak ve EXTRA_DISCOVERABLE_DURATION değerini sıfıra ayarlamak, uygulama arka planda veya ön planda çalışırken cihazın bulunabilir olmasını sağlar. Klasik Bluetooth spesifikasyonunda, bulunabilir cihazlar sürekli olarak belirli keşifler yayınlıyor. diğer cihazların cihaz verilerini almasına veya bu verilere bağlanmasına izin veren mesajlar İçinde Böyle bir senaryoda kötü amaçlı bir üçüncü taraf, bu tür mesajlara müdahale edip Android destekli cihaza veri gönderebilirsiniz. Bağlantı kurulduktan sonra saldırgan, veri hırsızlığı, DoS veya komut ekleme gibi başka saldırılar gerçekleştirebilir.

Çözümler

EXTRA_DISCOVERABLE_DURATION hiçbir zaman sıfır olarak ayarlanmamalıdır. EXTRA_DISCOVERABLE_DURATION parametresi ayarlanmazsa Android, cihazları varsayılan olarak 2 dakika boyunca bulunabilir hale getirir. EXTRA_DISCOVERABLE_DURATION parametresi için ayarlanabilecek maksimum değer 2 saattir (7.200 saniye). Evet bulunabilir sürenin en kısa zamanda tutulması önerilir mümkün olan en iyi sonucu verir.


Risk: NFC – klonlanmış intent filtreleri

Kötü amaçlı bir uygulama, belirli NFC etiketlerini veya NFC özellikli cihazları okumak için intent filtreleri kaydedebilir. Bu filtreler, meşru bir uygulama tarafından tanımlananları kopyalayabilir. Bu da saldırganın, paylaşılan NFC verilerinin içeriğini okumasını sağlar. İki aktivite bir araya geldiğinde belirli bir NFC etiketi için aynı intent filtrelerine sahipse Etkinlik Seçici bu nedenle kullanıcının yine de kötü amaçlı başarılı olması için atayarak açar. Bununla birlikte, intent-filter'leri gizlemeyle birleştirerek bu senaryoyu gerçekleştirmek mümkündür. Bu saldırı yalnızca NFC üzerinden paylaşılan verilerin son derece hassas olarak kabul edilebileceği durumlarda önemlidir.

Çözümler

Bir uygulamada NFC okuma özellikleri uygulanırken amaç filtreleri Android uygulama kayıtları (AAR'lar) ile birlikte kullanılabilir. AAR kaydını bir NDEF mesajına yerleştirmek, yalnızca meşru uygulamanın ve ilişkili NDEF işleme etkinliğinin başlatıldığına dair güçlü bir güvence sağlar. Bu sayede, istenmeyen uygulamaların veya etkinliklerin NFC üzerinden paylaşılan son derece hassas etiket veya cihaz verilerini okuması engellenir.


Risk: NFC - NDEF mesajı doğrulaması eksik

Android destekli bir cihaz, NFC etiketinden veya NFC özellikli bir cihazdan veri aldığında sistem, uygulamayı veya içindeki NDEF mesajını işlemek üzere yapılandırılmış belirli etkinliği otomatik olarak tetikler. Uygulamada uygulanan mantığa göre, etikette bulunan veya cihazdan alınan veriler, web sayfalarının açılması gibi başka işlemleri tetiklemek için diğer etkinliklere sunulabilir.

NDEF mesaj içeriği doğrulaması olmayan uygulamalar, saldırganların NFC özellikli cihazlar veya NFC etiketleri kullanarak kötü amaçlı dosyaya neden olabilecek beklenmedik davranışa neden olan komut yerleştirme ya da DoS komutlarından oluşur.

Çözümler

Alınan NDEF mesajını herhangi bir uygulama bileşenine göndermeden önce, içindeki verilerin beklenen biçimde olduğu ve düşünülebilir. Böylece, kötü amaçlı verilerin diğer uygulamaların beklenmedik davranış riskini azaltır, NFC verileri kullanarak yapılan saldırılar.

Aşağıdaki snippet'te yöntemini kullanabilirsiniz. Bu, taranan NFC NDEF etiketinden veri almak için Android geliştiricilerinin örneği üzerine uygulandı:

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;
    }

Kaynaklar