RTPS parsing buffer overflow
AHA! has discovered an issue with Wireshark, and is issuing this disclosure in accordance with AHA!'s standard disclosure policy on 2023-05-16. CVE-2023-0666 has been assigned to this issue.
Any questions about this disclosure should be directed to cve@takeonme.org.
Executive Summary
Due to failure in validating the length provided by an attacker-crafted RTPS packet, Wireshark version 4.0.5 and prior, by default, is susceptible to a heap-based buffer overflow, and possibly code execution in the context of the process running Wireshark. CVE-2023-0666 appears to be an instance of CWE-122.
Technical Details
The rtps_util_add_type_library_type
function contains a call to g_strlcpy
that, without validation, uses a length supplied by the packet data that can result in a heap-based buffer overflow.
Snippet of the vulnerable code:
static gint rtps_util_add_type_library_type(proto_tree *tree,
tvbuff_t * tvb, gint offset, const guint encoding, dissection_info *info) {
proto_tree * annotation_tree;
guint32 member_id = 0, member_length = 0, long_number, i;
gint offset_tmp;
guint16 short_number;
gchar * name = NULL;
rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length);
offset_tmp = offset;
/* ... */
long_number = tvb_get_guint32(tvb, offset_tmp, encoding);
name = tvb_get_string_enc(wmem_packet_scope(), tvb, offset_tmp+4, long_number, ENC_ASCII);
if (info)
(void) g_strlcpy(info->member_name, name, long_number);
The dissection_info
struct is defined as:
typedef struct _dissection_info {
guint64 type_id;
gint member_kind;
guint64 base_type_id;
guint32 member_length;
gchar member_name[MAX_MEMBER_NAME];
RTICdrTypeObjectExtensibility extensibility;
gint32 bound;
guint32 num_elements;
dissection_element* elements;
} dissection_info;
and MAX_MEMBER_NAME
is defined as:
#define MAX_MEMBER_NAME (256)
The overflow occurs when long_number
is greater than 256 bytes however it should be noted that this does require that many bytes to have been sent.
g_strlcpy
expects the size of the destination buffer as the last argument so this can be remediated by using sizeof(info->member_name)
instead of long_number
in the g_strlcpy
call. Additionally, the return value should be checked because if it is greater than sizeof(info->member_name)
, then truncation occurred.
Reproduction: Run tshark -r rtps_trigger.pcap
or open rtps_trigger.pcap
in Wireshark. Note that an ASAN build is not required due to the way the PCAP was crafted.
Full output from running under GDB:
(gdb) run -r ~/rtps_trigger.pcap
Starting program: /usr/bin/tshark -r ~/rtps_trigger.pcap
This GDB supports auto-downloading debuginfo from the following URLs:
https://debuginfod.ubuntu.com
Enable debuginfod for this session? (y or [n]) n
Debuginfod has been disabled.
To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7fffebcdd6c0 (LWP 125835)]
[Thread 0x7fffebcdd6c0 (LWP 125835) exited]
[New Thread 0x7fffebcdd6c0 (LWP 125836)]
[Thread 0x7fffebcdd6c0 (LWP 125836) exited]
1 0.000000 192.168.0.231 → 192.168.0.214 TCP 54 2603 → 9187 [SYN] Seq=0 Win=8192 Len=0
2 0.000363 192.168.0.214 → 192.168.0.231 TCP 54 9187 → 2603 [SYN, ACK] Seq=0 Ack=0 Win=8192 Len=0
3 0.000611 192.168.0.231 → 192.168.0.214 TCP 54 2603 → 9187 [ACK] Seq=1 Ack=0 Win=8192 Len=0
4 0.000853 192.168.0.231 → 192.168.0.214 RTPS 1454 DATA_deprecated[Malformed Packet]
Thread 1 "tshark" received signal SIGSEGV, Segmentation fault.
wmem_block_split_free_chunk (allocator=0x5555555bf660, chunk=0x7fffe9f44fb0, size=<optimized out>) at ./wsutil/wmem/wmem_allocator_block.c:614
614 ./wsutil/wmem/wmem_allocator_block.c: No such file or directory.
(gdb) x/5i $pc
=> 0x7ffff088db1b <wmem_block_split_free_chunk+267>: mov QWORD PTR [rsi+0x10],rax
0x7ffff088db1f <wmem_block_split_free_chunk+271>: mov QWORD PTR [r8+0x8],rax
0x7ffff088db23 <wmem_block_split_free_chunk+275>: jmp 0x7ffff088da9b <wmem_block_split_free_chunk+139>
0x7ffff088db28 <wmem_block_split_free_chunk+280>: nop DWORD PTR [rax+rax*1+0x0]
0x7ffff088db30 <wmem_block_split_free_chunk+288>: mov rax,QWORD PTR [rcx+0x10]
(gdb) p (char[]) $rsi
$1 = "AHA!AHA!"
Reproducer: cve-2023-0666.pcap
Attacker Value
By providing this poisoned RTPS packet, an attacker could hijack the user account of an analyst running Wireshark. Many security appliances capture packets as a matter of course for later analysis, and Wireshark is a common tool used by incident responders. So, it would be trivial for an attacker to intentionally "get caught" in order to provide their malicious packet to an incident response analyst. Once compromised, this can provide an attacker a unique, privileged position in the targeted network.
Credit
This issue is being disclosed through the AHA! CNA and is credited to: Austin Hackers Anonymous!
Timeline
- 2023-04-27 (Wed): Initial findings presented at the regularly scheduled AHA! meeting.
- 2023-05-17 (Wed): PoC validated and anaylsis completed for disclosure.
- 2023-05-18 (Thu): Disclosed to the vendor via email at security@wireshark.org.
- ... time marches on ....
- 2023-07-17 (Mon): (Planned) Public disclosure at https://takeonme.org/cve/CVE-2023-0666.html