使用 powershell 获取 "Audit Policy" 安全设置值

Using powershell to get the "Audit Policy" security setting value

我正在尝试使用 Powershell (auditpol) 来查询审核策略项的安全设置值。到目前为止,对于所有 auditpol 命令,我只能获取子类别值。

auditpol /get /category:*

到目前为止,我只能使用以下方法获得没有 success/failure/no 审计值的 9 个项目的列表:

auditpol /list/category

是否有一个 command/flag 我可能遗漏了 auditpol 或者是否有任何其他命令可以让我检索策略及其相关的安全设置值?

Policy and values that I would like to query.

如您所见,auditpol 仅管理启用“高级审核策略配置”功能时生效的设置。

要查询“经典”审核策略,您需要使用 LSA Policy Win32 API 来:

  1. 使用LsaOpenPolicy()
  2. 打开本地安全策略
  3. 使用LsaQueryPolicyInformation()
  4. 查询审核设置
  5. 将结果翻译成可读的内容。

以下示例使用 Add-Type 编译一个 C# 类型,该类型依次执行上述所有操作:

$AuditPolicyReader = Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Linq;
using System.Collections.Generic;

public class AuditPolicyReader
{
    [Flags()]
    public enum AuditPolicySetting
    {
        Unknown =  -1,
        None    = 0x0,
        Success = 0x1,
        Failure = 0x2
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct LSA_UNICODE_STRING
    {
        public UInt16 Length;
        public UInt16 MaximumLength;
        public IntPtr Buffer;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct LSA_OBJECT_ATTRIBUTES
    {
        public int Length;
        public IntPtr RootDirectory;
        public LSA_UNICODE_STRING ObjectName;
        public UInt32 Attributes;
        public IntPtr SecurityDescriptor;
        public IntPtr SecurityQualityOfService;
    }

    public struct POLICY_AUDIT_EVENTS_INFO
    {
        public bool AuditingMode;
        public IntPtr EventAuditingOptions;
        public Int32 MaximumAuditEventCount;
    }

    [DllImport("advapi32.dll")]
    static extern uint LsaQueryInformationPolicy(IntPtr PolicyHandle, uint InformationClass, out IntPtr Buffer);

    [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
    static extern uint LsaOpenPolicy(ref LSA_UNICODE_STRING SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, uint DesiredAccess, out IntPtr PolicyHandle);

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern uint LsaClose(IntPtr ObjectHandle);

    public static Dictionary<string, AuditPolicySetting> GetClassicAuditPolicy()
    {
        // Create dictionary to hold the audit policy settings (the key order here is important!!!)
        var settings = new Dictionary<string, AuditPolicySetting>
        {
            {"System", AuditPolicySetting.Unknown},
            {"Logon", AuditPolicySetting.Unknown},
            {"Object Access", AuditPolicySetting.Unknown},
            {"Privilige Use", AuditPolicySetting.Unknown},
            {"Detailed Tracking", AuditPolicySetting.Unknown},
            {"Policy Change", AuditPolicySetting.Unknown},
            {"Account Management", AuditPolicySetting.Unknown},
            {"Directory Service Access", AuditPolicySetting.Unknown},
            {"Account Logon", AuditPolicySetting.Unknown},
        };

        // Open local machine security policy
        IntPtr polHandle;
        LSA_OBJECT_ATTRIBUTES aObjectAttributes = new LSA_OBJECT_ATTRIBUTES();
        aObjectAttributes.Length = 0;
        aObjectAttributes.RootDirectory = IntPtr.Zero;
        aObjectAttributes.Attributes = 0;
        aObjectAttributes.SecurityDescriptor = IntPtr.Zero;
        aObjectAttributes.SecurityQualityOfService = IntPtr.Zero;

        var systemName = new LSA_UNICODE_STRING();
        uint desiredAccess = 2; // we only need the audit policy, no need to request anything else
        var res = LsaOpenPolicy(ref systemName, ref aObjectAttributes, desiredAccess, out polHandle);
        if (res != 0)
        {
            if(res == 0xC0000022)
            {
                // Access denied, needs to run as admin
                throw new UnauthorizedAccessException("Failed to open LSA policy because of insufficient access rights");
            }
            throw new Exception(string.Format("Failed to open LSA policy with return code '0x{0:X8}'", res));
        }
        try
        {
            // now that we have a valid policy handle, we can query the settings of the audit policy
            IntPtr outBuffer;
            uint policyType = 2; // this will return information about the audit settings
            res = LsaQueryInformationPolicy(polHandle, policyType, out outBuffer);
            if (res != 0)
            {
                throw new Exception(string.Format("Failed to query LSA policy information with '0x{0:X8}'", res));
            }

            // copy the raw values returned by LsaQueryPolicyInformation() to a local array;
            var auditEventsInfo = Marshal.PtrToStructure<POLICY_AUDIT_EVENTS_INFO>(outBuffer);
            var values = new int[auditEventsInfo.MaximumAuditEventCount];                
            Marshal.Copy(auditEventsInfo.EventAuditingOptions, values, 0, auditEventsInfo.MaximumAuditEventCount);

            // now we just need to translate the provided values into our settings dictionary
            var categoryIndex = settings.Keys.ToArray();
            for (int i = 0; i < values.Length; i++)
            {
                settings[categoryIndex[i]] = (AuditPolicySetting)values[i];
            }

            return settings;
        }
        finally
        {
            // remember to release policy handle
            LsaClose(polHandle);
        }
    }
}
'@ -PassThru |Where-Object Name -eq AuditPolicyReader

现在我们可以调用 GetClassicAuditPolicy()(记得从提升的提示中调用 运行):

PS ~> $AuditPolicyReader::GetClassicAuditPolicy()
Key                                 Value
---                                 -----
System                               None
Logon                    Success, Failure
Object Access                        None
Privilige Use                        None
Detailed Tracking                    None
Policy Change                     Success
Account Management       Success, Failure
Directory Service Access             None
Account Logon                        None

auditpol只returnsAdvanced audit policy configuration。这些设置可以在 Security Settings > Advanced Audit Policy Configuration > System Audit Policies

下的 UI 中找到

在 Windows Server 2003/Windows Vista 之后,您的屏幕截图显示的遗留审计策略大部分被取消了。请注意策略属性或 MS 上的警告 compatibility page:

对于高级策略,您可以使用 /r 获取 csv 格式的 table:

auditpol /get /category:'Account Logon' /r | ConvertFrom-Csv | 
Format-Table 'Policy Target',Subcategory,'Inclusion Setting'
Policy Target Subcategory                        Inclusion Setting
------------- -----------                        -----------------
System        Kerberos Service Ticket Operations No Auditing      
System        Other Account Logon Events         No Auditing      
System        Kerberos Authentication Service    No Auditing      
System        Credential Validation              No Auditing      

对于遗留审计策略:

secedit.exe /export /areas SECURITYPOLICY /cfg filename.txt
[Event Audit]
AuditSystemEvents = 0
AuditLogonEvents = 0
AuditObjectAccess = 0
AuditPrivilegeUse = 0
AuditPolicyChange = 0
AuditAccountManage = 0
AuditProcessTracking = 0
AuditDSAccess = 0
AuditAccountLogon = 0

要求它没有被禁用。签入注册表:

Get-ItemProperty HKLM:\System\CurrentControlSet\Control\Lsa -Name SCENoApplyLegacyAuditPolicy 

这是一个代码,可以为您提供所有类别和子类别及其当前 audit-status 的列表。我使它比添加每个对象的本地名称实际需要的时间长了一点。另请参阅代码末尾的一些usage-samples。

# getting the audit policy settings for each subcategory
# works for any OS language

cls
Remove-Variable * -ea 0
$ErrorActionPreference = 'stop'
#requires -runasadmin

$dll = [string]::Join("`r`n", '[DllImport("advapi32.dll")]', 'public static extern bool') 
$auditpol = Add-Type -Name 'AuditPol' -Namespace 'Win32' -PassThru -MemberDefinition "
$dll AuditEnumerateCategories(out IntPtr catList, out uint count);
$dll AuditLookupCategoryName(Guid catGuid, out string catName);
$dll AuditEnumerateSubCategories(Guid catGuid, bool all, out IntPtr subList, out uint count);
$dll AuditLookupSubCategoryName(Guid subGuid, out String subName);
$dll AuditQuerySystemPolicy(Guid subGuid, uint count, out IntPtr policy);
$dll AuditFree(IntPtr buffer);"

Add-Type -TypeDefinition "
using System;
public struct AUDIT_POLICY_INFORMATION {
    public Guid AuditSubCategoryGuid;
    public UInt32 AuditingInformation;
    public Guid AuditCategoryGuid;
}"

function getPolicyInfo($sub) {
    # get policy info for one subcategory:
    $pol = new-object AUDIT_POLICY_INFORMATION
    $size = $ms::SizeOf($pol)
    $ptr  = $ms::AllocHGlobal($size)
    $null = $ms::StructureToPtr($pol, $ptr, $false)
    $null = $auditpol::AuditQuerySystemPolicy($sub, 1, [ref]$ptr)
    $pol  = $ms::PtrToStructure($ptr, [type][AUDIT_POLICY_INFORMATION])
    $null = $ms::FreeHGlobal($ptr)
    [PsCustomObject]@{
        category = $pol.AuditCategoryGuid
        success  = [bool]($pol.AuditingInformation -band 1)
        failure  = [bool]($pol.AuditingInformation -band 2)
    }
}

# (optional) get GUID and local name of all categories:
$ms = [System.Runtime.InteropServices.Marshal]
$count = [uint32]0
$buffer = [IntPtr]::Zero
$size = $ms::SizeOf([type][guid])
$null = $auditpol::AuditEnumerateCategories([ref]$buffer,[ref]$count)
$ptr = [int64]$buffer
$name = [System.Text.StringBuilder]::new()
$catList = @{}
foreach($id in 1..$count) {
    $guid = $ms::PtrToStructure([IntPtr]$ptr,[type][guid])
    $null = $auditpol::AuditLookupCategoryName($guid,[ref]$name)
    $catList[$guid] = $name
    $ptr += $size
}
$null = $auditpol::AuditFree($buffer)

# get all subcategories (with optional name):
$guid = [guid]::Empty
$null = $auditpol::AuditEnumerateSubCategories($guid, $true, [ref]$buffer, [ref]$count)
$ptr = [int64]$buffer
$subList = @{}
foreach($id in 1..$count) {
    $guid = $ms::PtrToStructure([IntPtr]$ptr,[type][guid])
    $null = $auditpol::AuditLookupSubCategoryName($guid,[ref]$name)
    $pol  = getPolicyInfo $guid
    $data = [psCustomObject]@{
        category = $catList[$pol.category]
        subcategory = $name
        success = $pol.success
        failure = $pol.failure
    }
    $subList[$guid.guid] = $data
    $ptr += $size
}
$null = $auditpol::AuditFree($buffer)

# listing all subCategories and their audit settings:
$subList.Values | sort category, subcategory | ft -AutoSize

# gettings the audit-settings for a given subcategory-GUID (without '{}'):
$process_creation_guid = '0CCE922B-69AE-11D9-BED3-505054503030'
$subList[$process_creation_guid]