Browse code

interactive.c: Fix potential stack overflow issue

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>

Lev Stipakov authored on 2024/03/20 00:27:11
Showing 1 changed files
... ...
@@ -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