Within https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/net/ip/net_shell.c a command “net pkt”, is defined. The handler for this command, cmd_net_pkt, takes a string parameter to the function get_net_pkt. This string is converted to a number, and is cast to a pointer. Provided the input is a valid set of hex bytes of suitable length, the pointer will be returned without error. No attempt is made to verify the data pointed to is of the net_pkt type. This pointer is then passed to the net_pkt_buffer_info function. A while loop begins printing various values at offsets defined by the net_pkt’s buffer struct for each buffer thought to be a fragment of the input packet pointer. The while loop concludes when the list of fragments encounters a null value and the function returns. The cmd_net_pkt calls one more function, net_pkt_buffer_hexdump. This function dereferences the input pointer to identify the buffer pointer. For each fragment within the buffer, the data pointer and length are read and passed the shell_hexdump function where each byte within the buffer’s data is printed to the shell.
The net pkt command seems to be available even when the kernel, device and devmem shell modules are disabled, and the shell configuration to reduce flash/memory usage is applied.
Attack model
At the most basic level, an invalid pointer can be input that crashes the device, but with more knowledge of the device’s memory layout, further exploitation is possible.
In the case where a malicious actor can load some small amount of data into a known location in memory, the data interpreted as a header for the net_pkt and net_buf structs can be configured to not cause any unmapped memory to be accessed, the net_buf data and len parameters could be configured to cover any content from the firmware or memory. Calling the vulnerable command with the known memory location as the input string would result in the shell_hexdump command printing the firmware/memory content to the shell, without triggering a fault.
As a proof of concept (shown in the image below), we attempted to exploit a test firmware. Using a chosen parameter (0x3ffcbc30, pointing to inside of the text buffer for the current command) from our knowledge of the memory map, the net pkt command interprets $”@? as a member of a net_pkt struct, pointing to a net_buf struct. For the simplicity of the proof of concept, we manually placed a buffer in flash to act as our falsified net_buf struct, but the required data could be loaded into other user manipulatable memory. A location and length are interpreted from this buffer, and the bytes at the entered location are printed to the console.
Reporter
Guy Dalton Farrelly [email protected]
Patches
For more information
If you have any questions or comments about this advisory:
embargo: 2023-04-22
Within https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/net/ip/net_shell.c a command “net pkt”, is defined. The handler for this command, cmd_net_pkt, takes a string parameter to the function get_net_pkt. This string is converted to a number, and is cast to a pointer. Provided the input is a valid set of hex bytes of suitable length, the pointer will be returned without error. No attempt is made to verify the data pointed to is of the net_pkt type. This pointer is then passed to the net_pkt_buffer_info function. A while loop begins printing various values at offsets defined by the net_pkt’s buffer struct for each buffer thought to be a fragment of the input packet pointer. The while loop concludes when the list of fragments encounters a null value and the function returns. The cmd_net_pkt calls one more function, net_pkt_buffer_hexdump. This function dereferences the input pointer to identify the buffer pointer. For each fragment within the buffer, the data pointer and length are read and passed the shell_hexdump function where each byte within the buffer’s data is printed to the shell.
The net pkt command seems to be available even when the kernel, device and devmem shell modules are disabled, and the shell configuration to reduce flash/memory usage is applied.
Attack model
At the most basic level, an invalid pointer can be input that crashes the device, but with more knowledge of the device’s memory layout, further exploitation is possible.
In the case where a malicious actor can load some small amount of data into a known location in memory, the data interpreted as a header for the net_pkt and net_buf structs can be configured to not cause any unmapped memory to be accessed, the net_buf data and len parameters could be configured to cover any content from the firmware or memory. Calling the vulnerable command with the known memory location as the input string would result in the shell_hexdump command printing the firmware/memory content to the shell, without triggering a fault.
As a proof of concept (shown in the image below), we attempted to exploit a test firmware. Using a chosen parameter (0x3ffcbc30, pointing to inside of the text buffer for the current command) from our knowledge of the memory map, the net pkt command interprets $”@? as a member of a net_pkt struct, pointing to a net_buf struct. For the simplicity of the proof of concept, we manually placed a buffer in flash to act as our falsified net_buf struct, but the required data could be loaded into other user manipulatable memory. A location and length are interpreted from this buffer, and the bytes at the entered location are printed to the console.
Reporter
Guy Dalton Farrelly [email protected]
Patches
For more information
If you have any questions or comments about this advisory:
embargo: 2023-04-22