Message ID | 20240619134451.222-1-lev@openvpn.net |
---|---|
State | Accepted |
Headers | show |
Series | [Openvpn-devel] interactive.c: Improve access control for gui<->service pipe | expand |
On Wed, Jun 19, 2024 at 9:47 AM Lev Stipakov <lstipakov@gmail.com> wrote: > At the moment everyone but anonymous are permitted > to create a pipe with the same name as interactive service creates, > which makes it possible for malicious process with SeImpersonatePrivilege > impersonate as local user. > > This hardens the security of the pipe, making it possible only for > processes running as SYSTEM (such as interactive service) create the > pipe with the same name. > > While on it, replace EXPLICIT_ACCESS structures with SDDL string. > > CVE: 2024-4877 > > Change-Id: I35e783b79a332d247606e05a39e41b4d35d39b5d > Reported by: Zeze with TeamT5 <zeze7w@gmail.com> > Signed-off-by: Lev Stipakov <lev@openvpn.net> > --- > v2: > - ensure that sd is freed even if pipe creation failed > - added Reported-By > Acked-by: Selva Nair <selva.nair@gmail.com>
Forgot to add: This applies only to 2.6 -- for master we'll need a rebased version. On Wed, Jun 19, 2024 at 9:51 AM Selva Nair <selva.nair@gmail.com> wrote: > > > On Wed, Jun 19, 2024 at 9:47 AM Lev Stipakov <lstipakov@gmail.com> wrote: > >> At the moment everyone but anonymous are permitted >> to create a pipe with the same name as interactive service creates, >> which makes it possible for malicious process with SeImpersonatePrivilege >> impersonate as local user. >> >> This hardens the security of the pipe, making it possible only for >> processes running as SYSTEM (such as interactive service) create the >> pipe with the same name. >> >> While on it, replace EXPLICIT_ACCESS structures with SDDL string. >> >> CVE: 2024-4877 >> >> Change-Id: I35e783b79a332d247606e05a39e41b4d35d39b5d >> Reported by: Zeze with TeamT5 <zeze7w@gmail.com> >> Signed-off-by: Lev Stipakov <lev@openvpn.net> >> --- >> v2: >> - ensure that sd is freed even if pipe creation failed >> - added Reported-By >> > > Acked-by: Selva Nair <selva.nair@gmail.com> >
This is another "developed in secrecy on the security@ mailing list" patch, because it has security implications. It affects windows builds, where it is possible to have two different processes provide a pipe with the same name (ewwww!), and a connecting client will might not end up at the interactive service but at "some random process". This is not a major issue in itself, but the GUI sends a "user credentials token" (so openvpn.exe can be run as "normal user" later on) and this can be abused by a malicious process to get access to the user running openvpn-gui.exe - now, it's a somewhat theoretical attack (malicious software having sufficient privileges to do use a user token, but not having either "that user access" or "system privs" to start with) - but it's worth fixing. So, just stay calm, don't panic, and upgrade to 2.6.11 ;-) I have not tested this beyond "does it compile?" on a local ubuntu/mingw build and on GHA. Lev, Selva and Heiko did all the grunt work on coming up with a solution and testing the patch. Your patch has been applied to the release/2.6 branch. A rebase to master is in the works (this conflicted with the snprintf() cleanup patch, which is "only in master" and was merged right after *this* was developed and tested). Backport to release/2.5 is not fully straightforward either - there have been a number of fixes to interactive.c, and not all of them have been backported. OTOH, we do not intend to provide 2.5.x windows binaries ever again (and said so at 2.5.10 release), so now is the time to upgrade your windows clients to 2.6.x commit 51301eb6c233c284270e3f4ed0c7f5781f2b5c62 (release/2.6) Author: Lev Stipakov Date: Wed Jun 19 16:44:23 2024 +0300 interactive.c: Improve access control for gui<->service pipe Signed-off-by: Lev Stipakov <lev@openvpn.net> Acked-by: Selva Nair <selva.nair@gmail.com> Message-Id: <20240619134451.222-1-lev@openvpn.net> URL: https://www.mail-archive.com/search?l=mid&q=20240619134451.222-1-lev@openvpn.net Signed-off-by: Gert Doering <gert@greenie.muc.de> -- kind regards, Gert Doering
diff --git a/src/openvpnserv/interactive.c b/src/openvpnserv/interactive.c index d32223ce..6da8ee5d 100644 --- a/src/openvpnserv/interactive.c +++ b/src/openvpnserv/interactive.c @@ -2137,73 +2137,50 @@ ServiceCtrlInteractive(DWORD ctrl_code, DWORD event, LPVOID data, LPVOID ctx) static HANDLE CreateClientPipeInstance(VOID) { - TCHAR pipe_name[256]; /* The entire pipe name string can be up to 256 characters long according to MSDN. */ - HANDLE pipe = NULL; - PACL old_dacl, new_dacl; - PSECURITY_DESCRIPTOR sd; - static EXPLICIT_ACCESS ea[2]; - static BOOL initialized = FALSE; - DWORD flags = PIPE_ACCESS_DUPLEX | WRITE_DAC | FILE_FLAG_OVERLAPPED; + /* + * allow all access for local system + * deny FILE_CREATE_PIPE_INSTANCE for everyone + * allow read/write for authenticated users + * deny all access to anonymous + */ + const TCHAR *sddlString = TEXT("D:(A;OICI;GA;;;S-1-5-18)(D;OICI;0x4;;;S-1-1-0)(A;OICI;GRGW;;;S-1-5-11)(D;;GA;;;S-1-5-7)"); - if (!initialized) + PSECURITY_DESCRIPTOR sd = NULL; + if (!ConvertStringSecurityDescriptorToSecurityDescriptor(sddlString, SDDL_REVISION_1, &sd, NULL)) { - PSID everyone, anonymous; - - ConvertStringSidToSid(TEXT("S-1-1-0"), &everyone); - ConvertStringSidToSid(TEXT("S-1-5-7"), &anonymous); + MsgToEventLog(M_SYSERR, TEXT("ConvertStringSecurityDescriptorToSecurityDescriptor failed.")); + return INVALID_HANDLE_VALUE; + } - ea[0].grfAccessPermissions = FILE_GENERIC_WRITE; - ea[0].grfAccessMode = GRANT_ACCESS; - ea[0].grfInheritance = NO_INHERITANCE; - ea[0].Trustee.pMultipleTrustee = NULL; - ea[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; - ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea[0].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; - ea[0].Trustee.ptstrName = (LPTSTR) everyone; + /* Set up SECURITY_ATTRIBUTES */ + SECURITY_ATTRIBUTES sa = {0}; + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = sd; + sa.bInheritHandle = FALSE; - ea[1].grfAccessPermissions = 0; - ea[1].grfAccessMode = REVOKE_ACCESS; - ea[1].grfInheritance = NO_INHERITANCE; - ea[1].Trustee.pMultipleTrustee = NULL; - ea[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; - ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea[1].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; - ea[1].Trustee.ptstrName = (LPTSTR) anonymous; + DWORD flags = PIPE_ACCESS_DUPLEX | WRITE_DAC | FILE_FLAG_OVERLAPPED; + static BOOL first = TRUE; + if (first) + { flags |= FILE_FLAG_FIRST_PIPE_INSTANCE; - initialized = TRUE; + first = FALSE; } + TCHAR pipe_name[256]; /* The entire pipe name string can be up to 256 characters long according to MSDN. */ openvpn_swprintf(pipe_name, _countof(pipe_name), TEXT("\\\\.\\pipe\\" PACKAGE "%ls\\service"), service_instance); - pipe = CreateNamedPipe(pipe_name, flags, - PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_REJECT_REMOTE_CLIENTS, - PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, NULL); + HANDLE pipe = CreateNamedPipe(pipe_name, flags, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_REJECT_REMOTE_CLIENTS, + PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, &sa); + + LocalFree(sd); + if (pipe == INVALID_HANDLE_VALUE) { MsgToEventLog(M_SYSERR, TEXT("Could not create named pipe")); return INVALID_HANDLE_VALUE; } - if (GetSecurityInfo(pipe, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, - NULL, NULL, &old_dacl, NULL, &sd) != ERROR_SUCCESS) - { - MsgToEventLog(M_SYSERR, TEXT("Could not get pipe security info")); - return CloseHandleEx(&pipe); - } - - if (SetEntriesInAcl(2, ea, old_dacl, &new_dacl) != ERROR_SUCCESS) - { - MsgToEventLog(M_SYSERR, TEXT("Could not set entries in new acl")); - return CloseHandleEx(&pipe); - } - - if (SetSecurityInfo(pipe, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, - NULL, NULL, new_dacl, NULL) != ERROR_SUCCESS) - { - MsgToEventLog(M_SYSERR, TEXT("Could not set pipe security info")); - return CloseHandleEx(&pipe); - } - return pipe; }
At the moment everyone but anonymous are permitted to create a pipe with the same name as interactive service creates, which makes it possible for malicious process with SeImpersonatePrivilege impersonate as local user. This hardens the security of the pipe, making it possible only for processes running as SYSTEM (such as interactive service) create the pipe with the same name. While on it, replace EXPLICIT_ACCESS structures with SDDL string. CVE: 2024-4877 Change-Id: I35e783b79a332d247606e05a39e41b4d35d39b5d Reported by: Zeze with TeamT5 <zeze7w@gmail.com> Signed-off-by: Lev Stipakov <lev@openvpn.net> --- v2: - ensure that sd is freed even if pipe creation failed - added Reported-By src/openvpnserv/interactive.c | 81 +++++++++++++---------------------- 1 file changed, 29 insertions(+), 52 deletions(-)