One of the features of a minifilter->user mode server system I’m helping build requires us to log user access attempts to certain files. There are a number of ways to get user IDs in both KM and UM but I was just wondering if there’s a “best practices” way of doing so, ensuring the user ID I log belongs to the Windows account that actually tried to open the file, and not a system/admin/etc. account running the minifilter and server?
Advice appreciated, especially for a UM solution as I’d prefer not to monkey with our driver code!
If you’re in Pre/Post IRP_MJ_CREATE you can retrieve the SID of the requestor using the following:
_Use_decl_annotations_
VOID
FsUtilGetRequestorSid(
PFLT_CALLBACK_DATA Data,
PSE_SID SeSid)
{
SID_IDENTIFIER_AUTHORITY nullAuthority = SECURITY_NULL_SID_AUTHORITY;
PACCESS_STATE accessState;
PACCESS_TOKEN requestorToken;
PTOKEN_USER tokenUserInfo = NULL;
NTSTATUS status;
PSECURITY_SUBJECT_CONTEXT requestorSubjectContext;
//
// This routine returns a NULL SID if we fail to query
//
RtlInitializeSid(&SeSid->Sid,
&nullAuthority,
1);
accessState = Data->Iopb->Parameters.Create.SecurityContext->AccessState;
requestorSubjectContext = &accessState->SubjectSecurityContext;
SeLockSubjectContext(requestorSubjectContext);
//
// SeQuerySubjectContextToken does the right thing and returns us either the
// impersonation token or the process token of the requestor
//
requestorToken = SeQuerySubjectContextToken(requestorSubjectContext);
//
// This doesn't fail, there is always one or the other
//
ASSERT(requestorToken);
//
// Query the token to retrieve the user SID
//
status = SeQueryInformationToken(requestorToken,
TokenUser,
(PVOID *)&tokenUserInfo);
if (!NT_SUCCESS(status)) {
goto Exit;
}
RtlCopyMemory(&SeSid->Sid,
tokenUserInfo->User.Sid,
RtlLengthSid(tokenUserInfo->User.Sid));
Exit:
SeUnlockSubjectContext(requestorSubjectContext);
if (tokenUserInfo != NULL) {
ExFreePool(tokenUserInfo);
}
return;
}
User mode can then easily translate the SID to a user name (e.g. LookupAccountSid).
if you are going to log, log the invariant SID - the user name can change, but this can’t. Then in a tool that views the log, perform the conversion based on the then current name etc. for that SID. This often comes up when people change their names after marriage etc.