[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 SeAuthenticatedUsersSid;
extern PSID SeRestrictedSid; extern PSID SeRestrictedSid;
extern PSID SeAnonymousLogonSid; extern PSID SeAnonymousLogonSid;
extern PSID SeLocalServiceSid;
extern PSID SeNetworkServiceSid;
/* Privileges */ /* Privileges */
extern const LUID SeCreateTokenPrivilege; extern const LUID SeCreateTokenPrivilege;
@ -531,6 +533,20 @@ SeFastTraverseCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK DesiredAccess,
IN KPROCESSOR_MODE AccessMode); 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 #endif
/* EOF */ /* EOF */

View file

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

View file

@ -252,6 +252,40 @@ SePrivilegePolicyCheck(
return STATUS_SUCCESS; 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 NTSTATUS
NTAPI NTAPI
SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src, SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src,
@ -506,11 +540,11 @@ SeSinglePrivilegeCheck(IN LUID PrivilegeValue,
if (PreviousMode != KernelMode) if (PreviousMode != KernelMode)
{ {
#if 0 SePrivilegedServiceAuditAlarm(NULL,
SePrivilegedServiceAuditAlarm(0,
&SubjectContext, &SubjectContext,
&PrivilegeValue); &Priv,
#endif Result);
} }
SeReleaseSubjectContext(&SubjectContext); SeReleaseSubjectContext(&SubjectContext);

View file

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

View file

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