When reading message from the pipe, we first peek the pipe to get the size
of the message waiting to be read and then read the message. A compromised
OpenVPN process could send an excessively large message, which would result
in a stack-allocated message buffer overflow.
To address this, we terminate the misbehaving process if the peeked message
size exceeds the maximum allowable size.
CVE: 2024-27459
Microsoft case number: 85932
Reported-by: Vladimir Tokarev <vtokarev@microsoft.com>
Change-Id: Ib5743cba0741ea11f9ee62c4978b2c6789b81ada
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Acked-by: Heiko Hund <heiko@openvpn.net>
Message-Id: <20240319152803.1801-2-lev@openvpn.net>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg28420.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
| ... | ... |
@@ -106,6 +106,18 @@ typedef struct {
|
| 106 | 106 |
struct tun_ring *receive_ring; |
| 107 | 107 |
} ring_buffer_maps_t; |
| 108 | 108 |
|
| 109 |
+typedef union {
|
|
| 110 |
+ message_header_t header; |
|
| 111 |
+ address_message_t address; |
|
| 112 |
+ route_message_t route; |
|
| 113 |
+ flush_neighbors_message_t flush_neighbors; |
|
| 114 |
+ block_dns_message_t block_dns; |
|
| 115 |
+ dns_cfg_message_t dns; |
|
| 116 |
+ enable_dhcp_message_t dhcp; |
|
| 117 |
+ register_ring_buffers_message_t rrb; |
|
| 118 |
+ set_mtu_message_t mtu; |
|
| 119 |
+ wins_cfg_message_t wins; |
|
| 120 |
+} pipe_message_t; |
|
| 109 | 121 |
|
| 110 | 122 |
static DWORD |
| 111 | 123 |
AddListItem(list_item_t **pfirst, LPVOID data) |
| ... | ... |
@@ -1610,19 +1622,7 @@ static VOID |
| 1610 | 1610 |
HandleMessage(HANDLE pipe, HANDLE ovpn_proc, |
| 1611 | 1611 |
DWORD bytes, DWORD count, LPHANDLE events, undo_lists_t *lists) |
| 1612 | 1612 |
{
|
| 1613 |
- DWORD read; |
|
| 1614 |
- union {
|
|
| 1615 |
- message_header_t header; |
|
| 1616 |
- address_message_t address; |
|
| 1617 |
- route_message_t route; |
|
| 1618 |
- flush_neighbors_message_t flush_neighbors; |
|
| 1619 |
- block_dns_message_t block_dns; |
|
| 1620 |
- dns_cfg_message_t dns; |
|
| 1621 |
- enable_dhcp_message_t dhcp; |
|
| 1622 |
- register_ring_buffers_message_t rrb; |
|
| 1623 |
- set_mtu_message_t mtu; |
|
| 1624 |
- wins_cfg_message_t wins; |
|
| 1625 |
- } msg; |
|
| 1613 |
+ pipe_message_t msg; |
|
| 1626 | 1614 |
ack_message_t ack = {
|
| 1627 | 1615 |
.header = {
|
| 1628 | 1616 |
.type = msg_acknowledgement, |
| ... | ... |
@@ -1632,7 +1632,7 @@ HandleMessage(HANDLE pipe, HANDLE ovpn_proc, |
| 1632 | 1632 |
.error_number = ERROR_MESSAGE_DATA |
| 1633 | 1633 |
}; |
| 1634 | 1634 |
|
| 1635 |
- read = ReadPipeAsync(pipe, &msg, bytes, count, events); |
|
| 1635 |
+ DWORD read = ReadPipeAsync(pipe, &msg, bytes, count, events); |
|
| 1636 | 1636 |
if (read != bytes || read < sizeof(msg.header) || read != msg.header.size) |
| 1637 | 1637 |
{
|
| 1638 | 1638 |
goto out; |
| ... | ... |
@@ -2059,6 +2059,13 @@ RunOpenvpn(LPVOID p) |
| 2059 | 2059 |
break; |
| 2060 | 2060 |
} |
| 2061 | 2061 |
|
| 2062 |
+ if (bytes > sizeof(pipe_message_t)) |
|
| 2063 |
+ {
|
|
| 2064 |
+ /* process at the other side of the pipe is misbehaving, shut it down */ |
|
| 2065 |
+ MsgToEventLog(MSG_FLAGS_ERROR, TEXT("OpenVPN process sent too large payload length to the pipe (%lu bytes), it will be terminated"), bytes);
|
|
| 2066 |
+ break; |
|
| 2067 |
+ } |
|
| 2068 |
+ |
|
| 2062 | 2069 |
HandleMessage(ovpn_pipe, proc_info.hProcess, bytes, 1, &exit_event, &undo_lists); |
| 2063 | 2070 |
} |
| 2064 | 2071 |
|