https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2092dc06bb3069155adf4…
commit 2092dc06bb3069155adf40bd7a3616fee8ec68bb
Author: George Bișoc <george.bisoc(a)reactos.org>
AuthorDate: Sat Apr 9 21:17:58 2022 +0200
Commit: George Bișoc <george.bisoc(a)reactos.org>
CommitDate: Fri May 6 10:09:49 2022 +0200
[WINLOGON][HACK] Allow network services access to default window station
HHHHHHHHHHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCCCCCCCCCCCCCCCCCCCCCCKKKKKKKKKKKKKKKKKK!!!
There are two problems concerning with network services. First, a window station
should be created for every network service process that gets started although this
doesn't happen. Instead, network services like RPCSS and DNS service host process
(svchost.exe) attempt to access the default window station (Winsta0).
This is because the access token of these two network service processes have an
authentication ID that is uniquely generated. This is incorrect, because NetworkService is
a special account with its own designed authentication ID for it. As a matter of fact, no
window station is created for a network service and as such
both RPCSS and DNS svchost.exe attempt to access Winsta0 which they cannot.
The second problem, albeit not quite relevant to the first one but still worth
mentioning nevertheless, is that network services have an access token that is primary
which it should be an impersonation token. These problems all come from LSASS as LSA
infrastructure is responsible for creating access tokens with security
context for objects.
For the moment being, add a hack on Winlogon that gives allow access to the default
window station to network services. When LSASS and involved components are fixed, this
hack must be removed.
---
base/system/winlogon/security.c | 191 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 183 insertions(+), 8 deletions(-)
diff --git a/base/system/winlogon/security.c b/base/system/winlogon/security.c
index 26d3935fe2e..4045496abb2 100644
--- a/base/system/winlogon/security.c
+++ b/base/system/winlogon/security.c
@@ -115,7 +115,7 @@ CreateWinstaSecurity(
BOOL Success = FALSE;
SECURITY_DESCRIPTOR AbsoluteSd;
PSECURITY_DESCRIPTOR RelativeSd = NULL;
- PSID WinlogonSid = NULL, AdminsSid = NULL;
+ PSID WinlogonSid = NULL, AdminsSid = NULL, NetworkServiceSid = NULL; /*
NetworkServiceSid is a HACK, see the comment below for information */
DWORD DaclSize;
PACL Dacl;
@@ -142,18 +142,62 @@ CreateWinstaSecurity(
goto Quit;
}
+ /* HACK: Create the network service SID */
+ if (!AllocateAndInitializeSid(&NtAuthority,
+ 1,
+ SECURITY_NETWORK_SERVICE_RID,
+ 0, 0, 0, 0, 0, 0, 0,
+ &NetworkServiceSid))
+ {
+ ERR("CreateWinstaSecurity(): Failed to create the network service SID (error
code %lu)\n", GetLastError());
+ goto Quit;
+ }
+
/*
* Build up the DACL size. This includes a number
* of four ACEs of two different SIDs. The first two
* ACEs give both window station and generic access
* to Winlogon, the last two give limited window station
* and desktop access to admins.
+ *
+ * ===================== !!!MUST READ!!! =====================
+ *
+ * HACK -- Include in the DACL two more ACEs for network
+ * service SID. Network services will be granted full
+ * access to the default window station. Whilst technically
+ * services that are either network or local ones are part
+ * and act on behalf of the system, what we are doing here
+ * is a hack because of two reasons:
+ *
+ * 1) Winlogon does not allow default window station (Winsta0)
+ * access to network services on Windows. As a matter of fact,
+ * network services must access their own service window station
+ * (aka Service-0x0-3e4$) which never gets created. Why it never
+ * gets created is explained on the second point.
+ *
+ * 2) Our LSASS terribly lacks in code that handles special logon
+ * service types, NetworkService and LocalService. For this reason
+ * whenever an access token is created for a network service process
+ * for example, its authentication ID (aka LogonId represented as a LUID)
+ * is a uniquely generated ID by LSASS for this process. This is wrong
+ * on so many levels, partly because a network service is not a regular
+ * service and network services have their own special authentication logon
+ * ID (with its respective LUID as {0x3e4, 0x0}). On top of that, a network
+ * service process must have an impersonation token but for whatever reason
+ * we are creating a primary access token instead.
+ *
+ * FOR ANYONE WHO'S INTERESTED ON FIXING THIS, DO NOT FORGET TO REMOVE THIS
+ * HACK!!!
+ *
+ * =========================== !!!END!!! ================================
*/
DaclSize = sizeof(ACL) +
sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) +
sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) +
sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) +
- sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid);
+ sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) +
+ sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
GetLengthSid(NetworkServiceSid) +
+ sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
GetLengthSid(NetworkServiceSid);
/* Allocate the DACL now */
Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
@@ -216,6 +260,28 @@ CreateWinstaSecurity(
goto Quit;
}
+ /* HACK: Fifth ACE -- give full access to network services */
+ if (!AddAccessAllowedAceEx(Dacl,
+ ACL_REVISION,
+ NO_PROPAGATE_INHERIT_ACE,
+ WINSTA_ALL,
+ NetworkServiceSid))
+ {
+ ERR("CreateWinstaSecurity(): Failed to set ACE for network service (error
code %lu)\n", GetLastError());
+ goto Quit;
+ }
+
+ /* HACK: Sixth ACE -- give full generic access to network services */
+ if (!AddAccessAllowedAceEx(Dacl,
+ ACL_REVISION,
+ INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE |
CONTAINER_INHERIT_ACE,
+ GENERIC_ACCESS,
+ NetworkServiceSid))
+ {
+ ERR("CreateWinstaSecurity(): Failed to set ACE for network service (error
code %lu)\n", GetLastError());
+ goto Quit;
+ }
+
/* Initialize the security descriptor */
if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION))
{
@@ -253,6 +319,13 @@ Quit:
FreeSid(AdminsSid);
}
+ /* HACK */
+ if (NetworkServiceSid != NULL)
+ {
+ FreeSid(NetworkServiceSid);
+ }
+ /* END HACK */
+
if (Dacl != NULL)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
@@ -289,7 +362,7 @@ CreateApplicationDesktopSecurity(
BOOL Success = FALSE;
SECURITY_DESCRIPTOR AbsoluteSd;
PSECURITY_DESCRIPTOR RelativeSd = NULL;
- PSID WinlogonSid = NULL, AdminsSid = NULL;
+ PSID WinlogonSid = NULL, AdminsSid = NULL, NetworkServiceSid = NULL; /*
NetworkServiceSid is a HACK, see the comment in CreateWinstaSecurity for information */
DWORD DaclSize;
PACL Dacl;
@@ -316,6 +389,17 @@ CreateApplicationDesktopSecurity(
goto Quit;
}
+ /* HACK: Create the network service SID */
+ if (!AllocateAndInitializeSid(&NtAuthority,
+ 1,
+ SECURITY_NETWORK_SERVICE_RID,
+ 0, 0, 0, 0, 0, 0, 0,
+ &NetworkServiceSid))
+ {
+ ERR("CreateApplicationDesktopSecurity(): Failed to create the network
service SID (error code %lu)\n", GetLastError());
+ goto Quit;
+ }
+
/*
* Build up the DACL size. This includes a number
* of two ACEs of two different SIDs. The first ACE
@@ -324,7 +408,8 @@ CreateApplicationDesktopSecurity(
*/
DaclSize = sizeof(ACL) +
sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) +
- sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid);
+ sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) +
+ sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
GetLengthSid(NetworkServiceSid); /* HACK */
/* Allocate the DACL now */
Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
@@ -365,6 +450,17 @@ CreateApplicationDesktopSecurity(
goto Quit;
}
+ /* HACK: Third ACE -- Give full desktop power to network services */
+ if (!AddAccessAllowedAceEx(Dacl,
+ ACL_REVISION,
+ 0,
+ DESKTOP_ALL,
+ NetworkServiceSid))
+ {
+ ERR("CreateApplicationDesktopSecurity(): Failed to set ACE for network
services (error code %lu)\n", GetLastError());
+ goto Quit;
+ }
+
/* Initialize the security descriptor */
if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION))
{
@@ -402,6 +498,13 @@ Quit:
FreeSid(AdminsSid);
}
+ /* HACK */
+ if (NetworkServiceSid != NULL)
+ {
+ FreeSid(NetworkServiceSid);
+ }
+ /* END HACK */
+
if (Dacl != NULL)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
@@ -775,7 +878,7 @@ AllowWinstaAccessToUser(
BOOL Success = FALSE;
SECURITY_DESCRIPTOR AbsoluteSd;
PSECURITY_DESCRIPTOR RelativeSd = NULL;
- PSID WinlogonSid = NULL, AdminsSid = NULL, InteractiveSid = NULL;
+ PSID WinlogonSid = NULL, AdminsSid = NULL, InteractiveSid = NULL, NetworkServiceSid =
NULL; /* NetworkServiceSid is a HACK, see the comment in CreateWinstaSecurity for
information */
SECURITY_INFORMATION SecurityInformation;
DWORD DaclSize;
PACL Dacl;
@@ -814,6 +917,17 @@ AllowWinstaAccessToUser(
goto Quit;
}
+ /* HACK: Create the network service SID */
+ if (!AllocateAndInitializeSid(&NtAuthority,
+ 1,
+ SECURITY_NETWORK_SERVICE_RID,
+ 0, 0, 0, 0, 0, 0, 0,
+ &NetworkServiceSid))
+ {
+ ERR("AllowWinstaAccessToUser(): Failed to create the network service SID
(error code %lu)\n", GetLastError());
+ goto Quit;
+ }
+
/*
* Build up the DACL size. This includes a number
* of eight ACEs of four different SIDs. The first ACE
@@ -830,7 +944,9 @@ AllowWinstaAccessToUser(
sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(InteractiveSid)
+
sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(InteractiveSid)
+
sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(LogonSid) +
- sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(LogonSid);
+ sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(LogonSid) +
+ sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
GetLengthSid(NetworkServiceSid) + /* HACK */
+ sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
GetLengthSid(NetworkServiceSid);
/* Allocate the DACL now */
Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
@@ -937,6 +1053,28 @@ AllowWinstaAccessToUser(
goto Quit;
}
+ /* HACK : Ninenth ACE -- Give full winsta access to network services */
+ if (!AddAccessAllowedAceEx(Dacl,
+ ACL_REVISION,
+ NO_PROPAGATE_INHERIT_ACE,
+ WINSTA_ALL,
+ NetworkServiceSid))
+ {
+ ERR("AllowWinstaAccessToUser(): Failed to set ACE for logon network service
SID (error code %lu)\n", GetLastError());
+ goto Quit;
+ }
+
+ /* HACK: Tenth ACE -- Give generic access to network services */
+ if (!AddAccessAllowedAceEx(Dacl,
+ ACL_REVISION,
+ INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE |
CONTAINER_INHERIT_ACE,
+ GENERIC_ACCESS,
+ NetworkServiceSid))
+ {
+ ERR("AllowWinstaAccessToUser(): Failed to set ACE for network service SID
(error code %lu)\n", GetLastError());
+ goto Quit;
+ }
+
/* Initialize the security descriptor */
if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION))
{
@@ -985,6 +1123,13 @@ Quit:
FreeSid(InteractiveSid);
}
+ /* HACK */
+ if (NetworkServiceSid != NULL)
+ {
+ FreeSid(NetworkServiceSid);
+ }
+ /* END HACK */
+
if (Dacl != NULL)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
@@ -1024,7 +1169,7 @@ AllowDesktopAccessToUser(
BOOL Success = FALSE;
SECURITY_DESCRIPTOR AbsoluteSd;
PSECURITY_DESCRIPTOR RelativeSd = NULL;
- PSID WinlogonSid = NULL, AdminsSid = NULL, InteractiveSid = NULL;
+ PSID WinlogonSid = NULL, AdminsSid = NULL, InteractiveSid = NULL, NetworkServiceSid =
NULL; /* NetworkServiceSid is a HACK, see the comment in CreateWinstaSecurity for
information */
SECURITY_INFORMATION SecurityInformation;
DWORD DaclSize;
PACL Dacl;
@@ -1063,6 +1208,17 @@ AllowDesktopAccessToUser(
goto Quit;
}
+ /* HACK: Create the network service SID */
+ if (!AllocateAndInitializeSid(&NtAuthority,
+ 1,
+ SECURITY_NETWORK_SERVICE_RID,
+ 0, 0, 0, 0, 0, 0, 0,
+ &NetworkServiceSid))
+ {
+ ERR("AllowDesktopAccessToUser(): Failed to create the network service SID
(error code %lu)\n", GetLastError());
+ goto Quit;
+ }
+
/*
* Build up the DACL size. This includes a number
* of four ACEs of four different SIDs. The first ACE
@@ -1075,7 +1231,8 @@ AllowDesktopAccessToUser(
sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) +
sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) +
sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(InteractiveSid)
+
- sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(LogonSid);
+ sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(LogonSid) +
+ sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
GetLengthSid(NetworkServiceSid); /* HACK */
/* Allocate the DACL now */
Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
@@ -1138,6 +1295,17 @@ AllowDesktopAccessToUser(
goto Quit;
}
+ /* HACK: Fifth ACE -- Give full desktop to network services */
+ if (!AddAccessAllowedAceEx(Dacl,
+ ACL_REVISION,
+ 0,
+ DESKTOP_ALL,
+ NetworkServiceSid))
+ {
+ ERR("AllowDesktopAccessToUser(): Failed to set ACE for network service SID
(error code %lu)\n", GetLastError());
+ goto Quit;
+ }
+
/* Initialize the security descriptor */
if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION))
{
@@ -1186,6 +1354,13 @@ Quit:
FreeSid(InteractiveSid);
}
+ /* HACK */
+ if (NetworkServiceSid != NULL)
+ {
+ FreeSid(NetworkServiceSid);
+ }
+ /* END HACK */
+
if (Dacl != NULL)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);