मशीन-से-मशीन कम्यूनिकेशन का असुरक्षित सेटअप

OWASP कैटगरी: MASVS-CODE: कोड क्वालिटी

खास जानकारी

बहुत कम संख्या में ऐसे ऐप्लिकेशन देखे जाते हैं जो ऐसी सुविधाएं लागू करते हैं जो उपयोगकर्ताओं को या रेडियो फ़्रीक्वेंसी (आरएफ़) का इस्तेमाल करके डेटा ट्रांसफ़र करें या दूसरे डिवाइसों से इंटरैक्ट करें कम्यूनिकेशन या केबल कनेक्शन. इनमें सबसे आम टेक्नोलॉजी का इस्तेमाल किया जाता है Android इस काम के लिए, क्लासिक ब्लूटूथ (ब्लूटूथ BR/EDR), ब्लूटूथ स्मार्ट है एनर्जी (BLE), वाई-फ़ाई P2P, एनएफ़सी, और यूएसबी.

आम तौर पर, इन टेक्नोलॉजी को उन ऐप्लिकेशन में लागू किया जाता है जिनसे उम्मीद की जाती है स्मार्ट होम ऐक्सेसरी, सेहत की निगरानी करने वाले डिवाइसों, और सार्वजनिक तौर पर जानकारी देने वाले डिवाइसों से संपर्क करें परिवहन कीऑस्क, पेमेंट टर्मिनल, और Android से चलने वाले अन्य डिवाइस.

किसी भी दूसरे चैनल की तरह, मशीन-टू-मशीन कम्यूनिकेशन पर भी हमले किए जा सकते हैं. इन हमलों का मकसद, दो या उससे ज़्यादा डिवाइसों के बीच बनी ट्रस्ट बाउंड्री को कमजोर करना होता है. डिवाइस के नाम पर काम करने जैसी तकनीकों का इस्तेमाल करके, को नुकसान पहुंचाने वाले उपयोगकर्ताओं के ज़रिए, चैनल.

Android, मशीन-से-मशीन को कॉन्फ़िगर करने के लिए खास एपीआई बनाता है डेवलपर के लिए उपलब्ध जानकारी.

कम्यूनिकेशन से जुड़ी गड़बड़ियों को लागू करते समय, इन एपीआई का इस्तेमाल सावधानी से किया जाना चाहिए प्रोटोकॉल से उपयोगकर्ता या डिवाइस का डेटा बिना अनुमति के सार्वजनिक हो सकता है सुरक्षित रखा जा सके. सबसे खराब स्थिति में, हमलावर दुनिया भर में एक या उससे ज़्यादा डिवाइसों को कंट्रोल करते हैं, जिसकी वजह से कॉन्टेंट का पूरा ऐक्सेस मिल जाता है डिवाइस पर.

असर

इसमें लागू की गई डिवाइस-टू-डिवाइस टेक्नोलॉजी के हिसाब से असर अलग-अलग हो सकता है ऐप्लिकेशन खोलें.

मशीन-टू-मशीन कम्यूनिकेशन चैनलों के गलत इस्तेमाल या कॉन्फ़िगरेशन की वजह से, उपयोगकर्ता के डिवाइस पर अविश्वसनीय कम्यूनिकेशन की कोशिशें की जा सकती हैं. इससे डिवाइस पर मैन-इन-द-मिडल (एमआईटीएम), कमांड इंजेक्शन, डीओएस या किसी दूसरे व्यक्ति के नाम पर किए जाने वाले हमलों जैसी अन्य गतिविधियों का खतरा बढ़ जाता है.

जोखिम: वायरलेस चैनलों पर संवेदनशील जानकारी की चोरी

मशीन-टू-मशीन कम्यूनिकेशन के तरीकों को लागू करते समय, इस्तेमाल की गई टेक्नोलॉजी और ट्रांसफ़र किए जाने वाले डेटा टाइप, दोनों पर ध्यान दिया जाना चाहिए. हालांकि, इस तरह के कामों के लिए केबल कनेक्शन ज़्यादा सुरक्षित होते हैं, क्योंकि इनमें शामिल डिवाइसों के बीच फ़िज़िकल लिंक की ज़रूरत होती है. रेडियो फ़्रीक्वेंसी का इस्तेमाल करने वाले कम्यूनिकेशन प्रोटोकॉल, जैसे कि क्लासिक ब्लूटूथ, बीएलई, एनएफ़सी, और वाई-फ़ाई पी2पी को इंटरसेप्ट किया जा सकता है. कोई हमलावर प्रतिरूपित कर सकता है ये इंटरसेप्ट करके, डेटा एक्सचेंज में शामिल टर्मिनल या ऐक्सेस पॉइंट को ऑन द एयर कम्यूनिकेशन की वजह से संवेदनशील उपयोगकर्ताओं तक पहुंच डेटा शामिल है. इसके अलावा, अगर डिवाइस पर इंस्टॉल किए गए नुकसान पहुंचाने वाले ऐप्लिकेशन को, कम्यूनिकेशन से जुड़ी रनटाइम अनुमतियां दी जाती हैं, तो वे सिस्टम मैसेज बफ़र को पढ़कर, डिवाइसों के बीच शेयर किए गए डेटा को वापस पा सकते हैं.

जोखिम कम करने के तरीके

अगर ऐप्लिकेशन को इस्तेमाल करने के लिए, संवेदनशील जानकारी को एक मशीन से दूसरे डिवाइस पर ट्रांसफ़र करने की ज़रूरत हो सुरक्षा समाधान, जैसे कि ऐप्लिकेशन-लेयर सुरक्षा समाधान एन्क्रिप्शन, ऐप्लिकेशन के कोड में लागू किया जाना चाहिए. इससे, हमलावर, कम्यूनिकेशन चैनल को स्निफ़ नहीं कर पाएंगे और न ही, एक-दूसरे के साथ शेयर किए गए डेटा को साफ़ तौर पर ऐक्सेस कर पाएंगे. अतिरिक्त संसाधनों के लिए, इसे देखें: क्रिप्टोग्राफ़ी के दस्तावेज़.


जोखिम: वायरलेस तरीके से नुकसान पहुंचाने वाला डेटा इंजेक्शन

नुकसान पहुंचाने वाले डेटा का इस्तेमाल करके, वायरलेस मशीन-टू-मशीन कम्यूनिकेशन चैनलों (क्लासिक ब्लूटूथ, बीएलई, एनएफ़सी, वाई-फ़ाई पी2पी) में बदलाव किया जा सकता है. काफ़ी कुशल हमलावर इस्तेमाल किए जा रहे कम्यूनिकेशन प्रोटोकॉल की पहचान कर सकते हैं और डेटा एक्सचेंज फ़्लो. उदाहरण के लिए, किसी एंडपॉइंट में से किसी एक के नाम पर काम करके, खास तौर पर तैयार किए गए पेलोड. नुकसान पहुंचाने वाले इस तरह के ट्रैफ़िक से, के काम करने के लिए प्रेरित करते हैं और, सबसे खराब स्थिति में, जिससे ऐप्लिकेशन और डिवाइस के काम करने के तरीके में बदलाव हो सकता है. इसके अलावा, 'DoS', कमांड इंजेक्शन या डिवाइस टेकओवर करना.

खतरों को कम करना

Android, डेवलपर को बेहतर एपीआई उपलब्ध कराता है, ताकि वे मशीन-टू-मशीन कम्यूनिकेशन को मैनेज कर सकें. जैसे, क्लासिक ब्लूटूथ, बीएलई, एनएफ़सी, और वाई-फ़ाई पी2पी. इन्हें सावधानी से लागू किए गए डेटा की पुष्टि करने वाले लॉजिक के साथ जोड़ा जाना चाहिए दो डिवाइसों के बीच लेन-देन किए गए किसी भी डेटा को साफ़ करने के लिए.

इस समाधान को ऐप्लिकेशन लेवल पर लागू किया जाना चाहिए. साथ ही, इसमें ऐसी जांचें शामिल होनी चाहिए जिनसे यह पुष्टि की जा सके कि डेटा की लंबाई और फ़ॉर्मैट सही है या नहीं. साथ ही, इसमें मान्य पेलोड भी शामिल है, जिसे ऐप्लिकेशन समझ सकता है.

नीचे दिया गया स्निपेट, डेटा की पुष्टि करने के लॉजिक का उदाहरण दिखाता है. यह लागू किया गया था ब्लूटूथ डेटा लागू करने के लिए, Android डेवलपर के उदाहरण पर जाएं ट्रांसफ़र करें:

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

जोखिम: यूएसबी से नुकसान पहुंचाने वाला डेटा इंजेक्शन

नुकसान पहुंचाने वाला कोई उपयोगकर्ता दो डिवाइसों के बीच के यूएसबी कनेक्शन को टारगेट कर सकता है बातचीत में रुकावट डालने में दिलचस्पी रखते हैं. इस मामले में, भौतिक लिंक में सुरक्षा की एक अतिरिक्त लेयर होनी चाहिए, क्योंकि हमलावर टर्मिनल को जोड़ने वाली केबल तक पहुंच कर किसी भी डिवाइस को छिपकर सुन सकें दिखाई देगा. अन्य अटैक वेक्टर को ऐसे यूएसबी डिवाइसों से दिखाया जाता है जिन पर भरोसा नहीं किया जा सकता. डिवाइस को जान-बूझकर या अनजाने में प्लग-इन कर दिया गया हो.

अगर ऐप्लिकेशन किसी खास चीज़ को ट्रिगर करने के लिए, पीआईडी/वीआईडी का इस्तेमाल करके यूएसबी डिवाइसों को फ़िल्टर करता है हैकर, ऐप्लिकेशन में भेजे गए डेटा से छेड़खानी कर सकते हैं उस डिवाइस की पहचान चुराकर उस यूएसबी चैनल को शेयर करें. इस तरह के हमलों से, नुकसान पहुंचाने वाले उपयोगकर्ताओं को डिवाइस पर कीस्ट्रोक भेजने या ऐप्लिकेशन की ऐसी गतिविधियां करने की अनुमति मिल सकती है जिनकी वजह से, सबसे खराब स्थिति में रिमोट कोड प्रोग्राम चलाया जा सकता है या अनचाहा सॉफ़्टवेयर डाउनलोड किया जा सकता है.

जोखिम कम करने के तरीके

ऐप्लिकेशन-लेवल पर पुष्टि करने का लॉजिक लागू किया जाना चाहिए. इस लॉजिक को यूएसबी की मदद से भेजे गए डेटा को फ़िल्टर करके देखें कि इमेज की लंबाई, फ़ॉर्मैट, और कॉन्टेंट कितना सही है ऐप्लिकेशन के इस्तेमाल के उदाहरण से मेल खाना चाहिए. उदाहरण के लिए, हार्टबीट मॉनिटर को कीस्ट्रोक आदेश भेजे जा सकते हैं.

इसके अलावा, जहां तक हो सके, यूएसबी डिवाइस से ऐप्लिकेशन को मिलने वाले यूएसबी पैकेट की संख्या. यह नुकसान पहुंचाने वाले डिवाइसों को रबर डकी जैसे हमले करने से रोकता है.

बफ़र किए गए कॉन्टेंट की जांच करने के लिए, एक नई थ्रेड बनाई जा सकती है. उदाहरण के लिए, 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();
        }
    }

खास जोखिम

इस सेक्शन में उन जोखिमों की जानकारी दी गई है जिन्हें कम करने के लिए नॉन-स्टैंडर्ड रणनीतियों की ज़रूरत होती है या इन्हें SDK टूल के किसी खास लेवल पर कम किया गया था. साथ ही, इन्हें पूरा करने के लिए उपलब्ध हैं.

जोखिम: ब्लूटूथ – डिवाइस को खोजने में लगने वाला समय गलत है

Android डेवलपर के लिए ब्लूटूथ दस्तावेज़ में बताया गया है कि ऐप्लिकेशन में ब्लूटूथ इंटरफ़ेस को कॉन्फ़िगर करते समय, डिवाइस को खोजे जा सकने की सुविधा चालू करने के लिए startActivityForResult(Intent, int) का इस्तेमाल करें. साथ ही, EXTRA_DISCOVERABLE_DURATION को शून्य पर सेट करें. ऐसा करने पर, जब तक ऐप्लिकेशन बैकग्राउंड या फ़ोरग्राउंड में चलेगा, तब तक डिवाइस को खोजा जा सकेगा. क्लासिक ब्लूटूथ स्पेसिफ़िकेशन के लिए, डिस्कवर किए जा सकने वाले डिवाइस लगातार डिस्कवरी के लिए खास मैसेज ब्रॉडकास्ट करते रहते हैं. इन मैसेज की मदद से, दूसरे डिवाइस डिवाइस का डेटा हासिल कर सकते हैं या उससे कनेक्ट कर सकते हैं. ऐसे में, कोई नुकसान पहुंचाने वाला तीसरा पक्ष ऐसे मैसेज को इंटरसेप्ट कर सकता है और Android डिवाइस से कनेक्ट कर सकता है. कनेक्ट होने के बाद, हमलावर आगे की कार्रवाई कर सकता है डेटा चोरी, DoS या कमांड इंजेक्शन जैसे हमले.

जोखिम कम करने के तरीके

EXTRA_DISCOVERABLE_DURATION को कभी भी शून्य पर सेट नहीं किया जाना चाहिए. अगर EXTRA_DISCOVERABLE_DURATION पैरामीटर सेट नहीं है, तो डिफ़ॉल्ट रूप से Android, डिवाइसों को दो मिनट के लिए खोजने लायक बनाता है. वह सबसे बड़ी वैल्यू जिसे EXTRA_DISCOVERABLE_DURATION पैरामीटर दो घंटे (7,200 सेकंड) का है. हमारा सुझाव है कि ऐप्लिकेशन के इस्तेमाल के उदाहरण के हिसाब से, डिस्कवर किए जाने की अवधि को कम से कम रखें.


जोखिम: एनएफ़सी – क्लोन किए गए इंटेंट-फ़िल्टर

नुकसान पहुंचाने वाला ऐप्लिकेशन, खास एनएफ़सी टैग या एनएफ़सी की सुविधा वाले डिवाइसों को पढ़ने के लिए, इंटेंट-फ़िल्टर रजिस्टर कर सकता है. ये फ़िल्टर, एक वैध ऐप्लिकेशन, जिससे हमलावर के लिए वह कॉन्टेंट पढ़ना मुमकिन हो जाता है किए गए हैं. ध्यान रखें कि जब दो गतिविधियों के लिए खास तौर पर किसी खास एनएफ़सी टैग के लिए एक जैसे इंटेंट फ़िल्टर का इस्तेमाल करते हैं, तो गतिविधि चुनने वाला टूल है, तो उपयोगकर्ता को अब भी हमले को सफल बनाने के लिए एक ऐप्लिकेशन है. हालांकि, क्लोकिंग के साथ इंटेंट-फ़िल्टर को जोड़ने पर, यह स्थिति अब भी हो सकती है. यह हमला है यह सिर्फ़ उन मामलों में ज़रूरी है जहां एनएफ़सी की मदद से किए गए डेटा के लेन-देन पर विचार किया जा सकता है बेहद संवेदनशील.

खतरों को कम करना

किसी ऐप्लिकेशन में एनएफ़सी की मदद से पढ़ने की सुविधा लागू करते समय, इंटेंट-फ़िल्टर का इस्तेमाल Android ऐप्लिकेशन के रिकॉर्ड (एएआर) के साथ किया जा सकता है. एम्बेड करना एनडीईएफ़ मैसेज में मौजूद एएआर रिकॉर्ड, इस बात का पूरा भरोसा दिलाता है कि सिर्फ़ वैध ऐप्लिकेशन और इससे जुड़ी NDEF हैंडलिंग गतिविधि को शुरू कर दिया गया है. ऐसा करने से, अनचाहे ऐप्लिकेशन या गतिविधियों को बहुत ज़्यादा पढ़ने से रोका जा सकता है एनएफ़सी के ज़रिए किया गया संवेदनशील टैग या डिवाइस का डेटा.


जोखिम: एनएफ़सी – एनडीएफ़ मैसेज की पुष्टि न होना

जब Android पर चलने वाले किसी डिवाइस को एनएफ़सी टैग या एनएफ़सी की सुविधा वाले डिवाइस से डेटा मिलता है तो सिस्टम अपने आप ऐप्लिकेशन या वह गतिविधि जिसे इसमें मौजूद NDEF मैसेज को मैनेज करने के लिए कॉन्फ़िगर किया गया है. ऐप्लिकेशन में लागू किए गए लॉजिक के मुताबिक, ऐप्लिकेशन में मौजूद डेटा या डिवाइस से मिले टैग को दूसरी गतिविधियों में भी शामिल किया जा सकता है, ताकि आगे की कार्रवाइयां, जैसे कि वेब पेज खोलना.

अगर किसी ऐप्लिकेशन में एनडीएफ़ई मैसेज के कॉन्टेंट की पुष्टि करने की सुविधा नहीं है, तो हमलावर एनएफ़सी की सुविधा वाले डिवाइसों या एनएफ़सी टैग का इस्तेमाल करके, ऐप्लिकेशन में नुकसान पहुंचाने वाले पेलोड इंजेक्ट कर सकते हैं. इससे ऐप्लिकेशन का गलत तरीके से इस्तेमाल किया जा सकता है. जैसे, नुकसान पहुंचाने वाली फ़ाइल डाउनलोड करना, कमांड इंजेक्शन या डीओएस (डिनायल ऑफ़ सर्विस) अटैक.

खतरों को कम करना

किसी दूसरे ऐप्लिकेशन कॉम्पोनेंट को मिला NDEF मैसेज भेजने से पहले, उसमें मौजूद डेटा की पुष्टि की जानी चाहिए. इससे यह पक्का किया जा सकता है कि डेटा सही फ़ॉर्मैट में है और उसमें सही जानकारी मौजूद है. इससे, नुकसान पहुंचाने वाले डेटा को अन्य ऐप्लिकेशन के कॉम्पोनेंट को बिना फ़िल्टर किए पास होने से रोका जा सकता है. इससे, अनचाहे व्यवहार या बदले गए एनएफ़सी डेटा का इस्तेमाल करके किए जाने वाले हमलों का जोखिम कम हो जाता है.

नीचे दिया गया स्निपेट, उदाहरण के तौर पर दिखाया गया है कि विधि में एक तर्क के रूप में NDEF मैसेज होता है और मैसेज अरे में इसका इंडेक्स होता है. यह Android डेवलपर के उदाहरण पर लागू किया गया था, ताकि स्कैन किया गया एनएफ़सी NDEF टैग:

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

संसाधन