[NTOSKRNL]

- Implement SeCheckAuditPrivilege and use it instead of SeSinglePrivilegeCheck, because the latter uses the effective token and we want the primary token
- Implement SePrivilegedServiceAuditAlarm
- Add and initialize missing SeLocalServiceSid and SeNetworkServiceSid

svn path=/trunk/; revision=62245
This commit is contained in:
Timo Kreuzer 2014-02-18 17:51:45 +00:00
parent ea1508451e
commit 5ebaa3c3dd
5 changed files with 157 additions and 29 deletions

View file

@ -143,6 +143,8 @@ extern PSID SeAliasBackupOpsSid;
extern PSID SeAuthenticatedUsersSid;
extern PSID SeRestrictedSid;
extern PSID SeAnonymousLogonSid;
extern PSID SeLocalServiceSid;
extern PSID SeNetworkServiceSid;
/* Privileges */
extern const LUID SeCreateTokenPrivilege;
@ -531,6 +533,20 @@ SeFastTraverseCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN ACCESS_MASK DesiredAccess,
IN KPROCESSOR_MODE AccessMode);
BOOLEAN
NTAPI
SeCheckAuditPrivilege(
_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
_In_ KPROCESSOR_MODE PreviousMode);
VOID
NTAPI
SePrivilegedServiceAuditAlarm(
_In_opt_ PUNICODE_STRING ServiceName,
_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
_In_ PPRIVILEGE_SET PrivilegeSet,
_In_ BOOLEAN AccessGranted);
#endif
/* EOF */

View file

@ -16,6 +16,8 @@
#define SEP_PRIVILEGE_SET_MAX_COUNT 60
UNICODE_STRING SeSubsystemName = RTL_CONSTANT_STRING(L"Security");
/* PRIVATE FUNCTIONS***********************************************************/
BOOLEAN
@ -202,11 +204,59 @@ SepAdtPrivilegedServiceAuditAlarm(
_In_ PTOKEN Token,
_In_ PTOKEN PrimaryToken,
_In_ PPRIVILEGE_SET Privileges,
_In_ BOOLEAN AccessGranted )
_In_ BOOLEAN AccessGranted)
{
UNIMPLEMENTED;
}
VOID
NTAPI
SePrivilegedServiceAuditAlarm(
_In_opt_ PUNICODE_STRING ServiceName,
_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
_In_ PPRIVILEGE_SET PrivilegeSet,
_In_ BOOLEAN AccessGranted)
{
PTOKEN EffectiveToken;
PSID UserSid;
PAGED_CODE();
/* Get the effective token */
if (SubjectContext->ClientToken != NULL)
EffectiveToken = SubjectContext->ClientToken;
else
EffectiveToken = SubjectContext->PrimaryToken;
/* Get the user SID */
UserSid = EffectiveToken->UserAndGroups->Sid;
/* Check if this is the local system SID */
if (RtlEqualSid(UserSid, SeLocalSystemSid))
{
/* Nothing to do */
return;
}
/* Check if this is the network service or local service SID */
if (RtlEqualSid(UserSid, SeExports->SeNetworkServiceSid) ||
RtlEqualSid(UserSid, SeExports->SeLocalServiceSid))
{
// FIXME: should continue for a certain set of privileges
return;
}
/* Call the worker function */
SepAdtPrivilegedServiceAuditAlarm(SubjectContext,
&SeSubsystemName,
ServiceName,
SubjectContext->ClientToken,
SubjectContext->PrimaryToken,
PrivilegeSet,
AccessGranted);
}
static
NTSTATUS
SeCaptureObjectTypeList(
@ -477,7 +527,7 @@ SepAccessCheckAndAuditAlarm(
}
/* Check for audit privilege */
HaveAuditPrivilege = SeSinglePrivilegeCheck(SeAuditPrivilege, UserMode);
HaveAuditPrivilege = SeCheckAuditPrivilege(&SubjectContext, UserMode);
if (!HaveAuditPrivilege && !(Flags & AUDIT_ALLOW_NO_PRIVILEGE))
{
DPRINT1("Caller does not have SeAuditPrivilege\n");
@ -811,6 +861,7 @@ NtCloseObjectAuditAlarm(
PVOID HandleId,
BOOLEAN GenerateOnClose)
{
SECURITY_SUBJECT_CONTEXT SubjectContext;
UNICODE_STRING CapturedSubsystemName;
KPROCESSOR_MODE PreviousMode;
BOOLEAN UseImpersonationToken;
@ -832,11 +883,15 @@ NtCloseObjectAuditAlarm(
return STATUS_SUCCESS;
}
/* Validate privilege */
if (!SeSinglePrivilegeCheck(SeAuditPrivilege, PreviousMode))
/* Capture the security subject context */
SeCaptureSubjectContext(&SubjectContext);
/* Check for audit privilege */
if (!SeCheckAuditPrivilege(&SubjectContext, PreviousMode))
{
DPRINT1("Caller does not have SeAuditPrivilege\n");
return STATUS_PRIVILEGE_NOT_HELD;
Status = STATUS_PRIVILEGE_NOT_HELD;
goto Cleanup;
}
/* Probe and capture the subsystem name */
@ -846,7 +901,7 @@ NtCloseObjectAuditAlarm(
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to capture subsystem name!\n");
return Status;
goto Cleanup;
}
/* Get the current thread and check if it's impersonating */
@ -887,7 +942,14 @@ NtCloseObjectAuditAlarm(
PsDereferencePrimaryToken(Token);
}
return STATUS_SUCCESS;
Status = STATUS_SUCCESS;
Cleanup:
/* Release the security subject context */
SeReleaseSubjectContext(&SubjectContext);
return Status;
}
@ -986,6 +1048,9 @@ NtOpenObjectAuditAlarm(
return Status;
}
/* Capture the security subject context */
SeCaptureSubjectContext(&SubjectContext);
/* Validate the token's impersonation level */
if ((ClientToken->TokenType == TokenImpersonation) &&
(ClientToken->ImpersonationLevel < SecurityIdentification))
@ -996,7 +1061,7 @@ NtOpenObjectAuditAlarm(
}
/* Check for audit privilege */
if (!SeSinglePrivilegeCheck(SeAuditPrivilege, UserMode))
if (!SeCheckAuditPrivilege(&SubjectContext, UserMode))
{
DPRINT1("Caller does not have SeAuditPrivilege\n");
Status = STATUS_PRIVILEGE_NOT_HELD;
@ -1106,9 +1171,6 @@ NtOpenObjectAuditAlarm(
goto Cleanup;
}
/* Capture the security subject context */
SeCaptureSubjectContext(&SubjectContext);
/* Call the internal function */
SepOpenObjectAuditAlarm(&SubjectContext,
&CapturedSubsystemName,
@ -1124,9 +1186,6 @@ NtOpenObjectAuditAlarm(
AccessGranted,
&LocalGenerateOnClose);
/* Release the security subject context */
SeReleaseSubjectContext(&SubjectContext);
Status = STATUS_SUCCESS;
/* Enter SEH to copy the data back to user mode */
@ -1158,6 +1217,9 @@ Cleanup:
if (CapturedPrivilegeSet != NULL)
ExFreePoolWithTag(CapturedPrivilegeSet, 'rPeS');
/* Release the security subject context */
SeReleaseSubjectContext(&SubjectContext);
ObDereferenceObject(ClientToken);
return Status;
@ -1213,12 +1275,15 @@ NtPrivilegedServiceAuditAlarm(
return STATUS_BAD_IMPERSONATION_LEVEL;
}
/* Validate privilege */
if (!SeSinglePrivilegeCheck(SeAuditPrivilege, PreviousMode))
/* Capture the security subject context */
SeCaptureSubjectContext(&SubjectContext);
/* Check for audit privilege */
if (!SeCheckAuditPrivilege(&SubjectContext, PreviousMode))
{
DPRINT1("Caller does not have SeAuditPrivilege\n");
ObDereferenceObject(ClientToken);
return STATUS_PRIVILEGE_NOT_HELD;
Status = STATUS_PRIVILEGE_NOT_HELD;
goto Cleanup;
}
/* Do we have a subsystem name? */
@ -1290,9 +1355,6 @@ NtPrivilegedServiceAuditAlarm(
}
_SEH2_END;
/* Capture the security subject context */
SeCaptureSubjectContext(&SubjectContext);
/* Call the internal function */
SepAdtPrivilegedServiceAuditAlarm(&SubjectContext,
SubsystemName ? &CapturedSubsystemName : NULL,
@ -1302,9 +1364,6 @@ NtPrivilegedServiceAuditAlarm(
CapturedPrivileges,
AccessGranted);
/* Release the security subject context */
SeReleaseSubjectContext(&SubjectContext);
Status = STATUS_SUCCESS;
Cleanup:
@ -1318,6 +1377,9 @@ Cleanup:
if (CapturedPrivileges != NULL)
ExFreePoolWithTag(CapturedPrivileges, 'rPeS');
/* Release the security subject context */
SeReleaseSubjectContext(&SubjectContext);
ObDereferenceObject(ClientToken);
return Status;

View file

@ -252,6 +252,40 @@ SePrivilegePolicyCheck(
return STATUS_SUCCESS;
}
BOOLEAN
NTAPI
SeCheckAuditPrivilege(
_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
_In_ KPROCESSOR_MODE PreviousMode)
{
PRIVILEGE_SET PrivilegeSet;
BOOLEAN Result;
PAGED_CODE();
/* Initialize the privilege set with the single privilege */
PrivilegeSet.PrivilegeCount = 1;
PrivilegeSet.Control = PRIVILEGE_SET_ALL_NECESSARY;
PrivilegeSet.Privilege[0].Luid = SeAuditPrivilege;
PrivilegeSet.Privilege[0].Attributes = 0;
/* Check against the primary token! */
Result = SepPrivilegeCheck(SubjectContext->PrimaryToken,
&PrivilegeSet.Privilege[0],
1,
PRIVILEGE_SET_ALL_NECESSARY,
PreviousMode);
if (PreviousMode != KernelMode)
{
SePrivilegedServiceAuditAlarm(NULL,
SubjectContext,
&PrivilegeSet,
Result);
}
return Result;
}
NTSTATUS
NTAPI
SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src,
@ -506,11 +540,11 @@ SeSinglePrivilegeCheck(IN LUID PrivilegeValue,
if (PreviousMode != KernelMode)
{
#if 0
SePrivilegedServiceAuditAlarm(0,
SePrivilegedServiceAuditAlarm(NULL,
&SubjectContext,
&PrivilegeValue);
#endif
&Priv,
Result);
}
SeReleaseSubjectContext(&SubjectContext);

View file

@ -74,10 +74,15 @@ SepInitExports(VOID)
SepExports.SeAuthenticatedUsersSid = SeAuthenticatedUsersSid;
SepExports.SeRestrictedSid = SeRestrictedSid;
SepExports.SeAnonymousLogonSid = SeAnonymousLogonSid;
SepExports.SeLocalServiceSid = SeLocalServiceSid;
SepExports.SeNetworkServiceSid = SeNetworkServiceSid;
SepExports.SeUndockPrivilege = SeUndockPrivilege;
SepExports.SeSyncAgentPrivilege = SeSyncAgentPrivilege;
SepExports.SeEnableDelegationPrivilege = SeEnableDelegationPrivilege;
SepExports.SeManageVolumePrivilege = SeManageVolumePrivilege;
SepExports.SeImpersonatePrivilege = SeImpersonatePrivilege;
SepExports.SeCreateGlobalPrivilege = SeCreateGlobalPrivilege;
SeExports = &SepExports;
return TRUE;

View file

@ -55,6 +55,8 @@ PSID SeAliasBackupOpsSid = NULL;
PSID SeAuthenticatedUsersSid = NULL;
PSID SeRestrictedSid = NULL;
PSID SeAnonymousLogonSid = NULL;
PSID SeLocalServiceSid = NULL;
PSID SeNetworkServiceSid = NULL;
/* FUNCTIONS ******************************************************************/
@ -135,6 +137,8 @@ SepInitSecurityIDs(VOID)
SeAuthenticatedUsersSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
SeRestrictedSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
SeAnonymousLogonSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
SeLocalServiceSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
SeNetworkServiceSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
if (SeNullSid == NULL || SeWorldSid == NULL ||
SeLocalSid == NULL || SeCreatorOwnerSid == NULL ||
@ -149,7 +153,8 @@ SepInitSecurityIDs(VOID)
SeAliasAccountOpsSid == NULL || SeAliasSystemOpsSid == NULL ||
SeAliasPrintOpsSid == NULL || SeAliasBackupOpsSid == NULL ||
SeAuthenticatedUsersSid == NULL || SeRestrictedSid == NULL ||
SeAnonymousLogonSid == NULL)
SeAnonymousLogonSid == NULL || SeLocalServiceSid == NULL ||
SeNetworkServiceSid == NULL)
{
FreeInitializedSids();
return FALSE;
@ -183,6 +188,8 @@ SepInitSecurityIDs(VOID)
RtlInitializeSid(SeAuthenticatedUsersSid, &SeNtSidAuthority, 1);
RtlInitializeSid(SeRestrictedSid, &SeNtSidAuthority, 1);
RtlInitializeSid(SeAnonymousLogonSid, &SeNtSidAuthority, 1);
RtlInitializeSid(SeLocalServiceSid, &SeNtSidAuthority, 1);
RtlInitializeSid(SeNetworkServiceSid, &SeNtSidAuthority, 1);
SubAuthority = RtlSubAuthoritySid(SeNullSid, 0);
*SubAuthority = SECURITY_NULL_RID;
@ -254,6 +261,10 @@ SepInitSecurityIDs(VOID)
*SubAuthority = SECURITY_RESTRICTED_CODE_RID;
SubAuthority = RtlSubAuthoritySid(SeAnonymousLogonSid, 0);
*SubAuthority = SECURITY_ANONYMOUS_LOGON_RID;
SubAuthority = RtlSubAuthoritySid(SeLocalServiceSid, 0);
*SubAuthority = SECURITY_LOCAL_SERVICE_RID;
SubAuthority = RtlSubAuthoritySid(SeNetworkServiceSid, 0);
*SubAuthority = SECURITY_NETWORK_SERVICE_RID;
return TRUE;
}