Advice on how to input a variable...

I have the below code…

In short it takes a copy of the existing audits in windows and then compares them to the required values that are stored in a hash table.

I had an after though that I would want to add the security section in the ‘add-content…’ section. I’m not sure how to do this though.

So say “Logon” = “Success and Failure”; section number would be like “Section 1.8.5”

Can anyone suggest how I might best complete this?

I added the $section variable to show where I would like the output to show up.

#array to section numbers for the hash
	$dvHash = @{
			"Credential Validation" = "Success and Failure"; 
			"Kerberos Service Ticket Operations" = "Success and Failure"; 
			"Other Account Logon Events" = "Success and Failure"; 
			"Kerberos Authentication Service" = "Success and Failure"; 
			"Account Lockout" = "Success and Failure"; 
			"Logon" = "Success and Failure"; 
			"Logoff" = "Success and Failure"; 
			"IPsec Main Mode" = "Success and Failure"; 
			"IPsec Quick Mode" = "Success and Failure"; 
			"IPsec Extended Mode" = "Success and Failure"; 
			"Special Logon" = "Success and Failure"; 
			"Other Logon/Logoff Events" = "Success and Failure"; 
			"Network Policy Server" = "Success and Failure"; 
			"User Account Management" = "Success and Failure"; 
			"Computer Account Management" = "Success and Failure"; 
			"Security Group Management" = "Success and Failure"; 
			"Distribution Group Management" = "Success and Failure"; 
			"Application Group Management" = "Success and Failure"; 
			"Other Account Management Events" = "Success and Failure"; 
			"Directory Service Access" = "Failure"; 
			"Directory Service Changes" = "Failure"; 
			"Directory Service Replication" = "Failure"; 
			"Detailed Directory Service Replication" = "Failure"; 
			"File System" = "Failure"; "Registry" = "Failure"; 
			"Detailed File Share" = "Failure"; 
			"Audit Policy Change" = "Success and Failure"; 
			"Kernel Object" = "Failure"; 
			"Filtering Platform Policy Change" = "Success and Failure"; 
			"Authentication Policy Change" = "Success and Failure"; 
			"MPSSVC Rule-Level Policy Change" = "Success and Failure"; 
			"SAM" = "Failure"; 
			"Security State Change" = "Failure"; 
			"Security System Extension" = "Failure"; 
			"Other Policy Change Events" = "Success and Failure"; 
			"System Integrity" = "Failure"; 
			"IPsec Driver" = "Failure"; 
			"Other Privilege Use Events" = "Success and Failure"; 
			"Certification Services" = "Failure"; 
			"Sensitive Privilege Use" = "Success and Failure"; 
			"Non Sensitive Privilege Use" = "Success and Failure"; 
			"Application Generated" = "Failure"; 
			"Handle Manipulation" = "Failure"; 
			"File Share" = "Failure"; 
			"Other System Events" = "Failure"; 
			"Filtering Platform Packet Drop" = "Failure"; 
			"Filtering Platform Connection" = "Failure"; 
			"Other Object Access Events" = "Failure";
			"Authorization Policy Change"="Success and failure"
		}
	$audithash = @{}
	
	foreach( $string in ((auditpol /get /category:*) -match '\s\s+' -NotMatch 'Setting'-replace '^\s+([a-zA-Z0-9\s-\\\/(\)?]+\b)\s\s+([a-zA-Z0-9\s]+)', '$1 = $2'))
		{
			 $audithash += ConvertFrom-StringData -StringData $string
		}
}

foreach($dvh in $dvhash.keys)
{
	if($dvhash[$dvh] -like "*" + $audithash[$dvh] + "*" -or $audithash[$dvh] -like "*" + $dvhash[$dvh] + "*")
	{
		$dv = $dvh + ": " + $dvhash[$dvh]
		$mv = "$dvh is set to " + $audithash[$dvh]
		$state = "Passed"
		add-content ScanResults.csv "$section!WinMulti!$svr!$os!$ls!Log Access Attempts!Audit Subcategory $dvh WIN-MULTI!$state!$mv!$dv !$notes
	}	
	else
	{
		$dv = $dvh + ": " + $dvhash[$dvh]
		$mv = "$dvh is set to " + $audithash[$dvh]
		$state = "Failed"
		add-content ScanResults.csv "$section!WinMulti!$svr!$os!$ls!Log Access Attempts!Audit Subcategory $dvh WIN-MULTI!$state!$mv!$dv !$notes
	}

}

What is the Section number? Is it an arbitrary value you have assigned or is it an existing list you are trying to utilize?

It’s a number that will just be hard coded into the script. I am basically just turning manual health checks into automated ones, and thought the section number would be relevant.

A coworker suggested adding the section number in the hash, and using regex to filter it out later…i’m not fantastic at regex at all (linux friend built the one in the original code) like

$dvHash = @{
			"1.8!Credential Validation" = "Success and Failure"; 
			"1.20!Kerberos Service Ticket Operations" = "Success and Failure"; 
			"1.23!Other Account Logon Events" = "Success and Failure"; 
                        .....
                   }

But i’m not really in love with that idea

You can create another hash for the section number association and then use it in your output

$section = @{
     "Credential Validation" = "1.8"; 
     "Kerberos Service Ticket Operations" = "1.20" 
}

...

add-content ScanResults.csv "$($section.Item('$dvh'))!WinMulti!$svr!$os!$ls!Log Access Attempts!Audit Subcategory $dvh WIN-MULTI!$state!$mv!$dv !$notes

Or you could make your existing hash use an array value rather than a string value like this.

#array to section numbers for the hash
	$dvHash = @{
			"Credential Validation" = @("Success and Failure", "1.8"); 
			"Kerberos Service Ticket Operations" = @("Success and Failure", "1.20"); 
			"Other Account Logon Events" = @("Success and Failure", "1.23"); 
			"Kerberos Authentication Service" = @("Success and Failure", ""); 
			"Account Lockout" = @("Success and Failure", ""); 
			"Logon" = @("Success and Failure", ""); 
			"Logoff" = @("Success and Failure", ""); 
			"IPsec Main Mode" = @("Success and Failure", ""); 
			"IPsec Quick Mode" = @("Success and Failure", ""); 
			"IPsec Extended Mode" = @("Success and Failure", ""); 
			"Special Logon" = @("Success and Failure", ""); 
			"Other Logon/Logoff Events" = @("Success and Failure", ""); 
			"Network Policy Server" = @("Success and Failure", ""); 
			"User Account Management" = @("Success and Failure", ""); 
			"Computer Account Management" = @("Success and Failure", ""); 
			"Security Group Management" = @("Success and Failure", ""); 
			"Distribution Group Management" = @("Success and Failure", ""); 
			"Application Group Management" = @("Success and Failure", ""); 
			"Other Account Management Events" = @("Success and Failure", ""); 
			"Directory Service Access" = @("Failure", ""); 
			"Directory Service Changes" = @("Failure", ""); 
			"Directory Service Replication" = @("Failure", ""); 
			"Detailed Directory Service Replication" = @("Failure", ""); 
			"File System" = @("Failure", ""); "Registry" = @("Failure", ""); 
			"Detailed File Share" = @("Failure", ""); 
			"Audit Policy Change" = @("Success and Failure", ""); 
			"Kernel Object" = @("Failure", ""); 
			"Filtering Platform Policy Change" = @("Success and Failure", ""); 
			"Authentication Policy Change" = @("Success and Failure", ""); 
			"MPSSVC Rule-Level Policy Change" = @("Success and Failure", ""); 
			"SAM" = @("Failure", ""); 
			"Security State Change" = @("Failure", ""); 
			"Security System Extension" = @("Failure", ""); 
			"Other Policy Change Events" = @("Success and Failure", ""); 
			"System Integrity" = @("Failure", ""); 
			"IPsec Driver" = @("Failure", ""); 
			"Other Privilege Use Events" = @("Success and Failure", ""); 
			"Certification Services" = @("Failure", ""); 
			"Sensitive Privilege Use" = @("Success and Failure", ""); 
			"Non Sensitive Privilege Use" = @("Success and Failure", ""); 
			"Application Generated" = @("Failure", ""); 
			"Handle Manipulation" = @("Failure", ""); 
			"File Share" = @("Failure", ""); 
			"Other System Events" = @("Failure", ""); 
			"Filtering Platform Packet Drop" = @("Failure", ""); 
			"Filtering Platform Connection" = @("Failure", ""); 
			"Other Object Access Events" = @("Failure", "");
			"Authorization Policy Change" = @("Success and failure", "")
		}
	$audithash = @{}
	
	foreach( $string in ((auditpol /get /category:*) -match '\s\s+' -NotMatch 'Setting'-replace '^\s+([a-zA-Z0-9\s-\\\/(\)?]+\b)\s\s+([a-zA-Z0-9\s]+)', '$1 = $2'))
		{
			 $audithash += ConvertFrom-StringData -StringData $string
		}

foreach($dvh in $dvhash.keys)
{
	if($dvhash[$dvh][0] -like "*" + $audithash[$dvh] + "*" -or $audithash[$dvh] -like "*" + $dvhash[$dvh][0] + "*")
	{
		$dv = $dvh + ": " + $dvhash[$dvh][0]
		$mv = "$dvh is set to " + $audithash[$dvh]
		$state = "Passed"
		add-content ScanResults.csv "$($dvhash[$dvh][1])!WinMulti!$svr!$os!$ls!Log Access Attempts!Audit Subcategory $dvh WIN-MULTI!$state!$mv!$dv !$notes"
	}	
	else
	{
		$dv = $dvh + ": " + $dvhash[$dvh][0]
		$mv = "$dvh is set to " + $audithash[$dvh]
		$state = "Failed"
		add-content ScanResults.csv "$($dvhash[$dvh][1])!WinMulti!$svr!$os!$ls!Log Access Attempts!Audit Subcategory $dvh WIN-MULTI!$state!$mv!$dv !$notes"
	}

}

Works great, I ran into an issue I just noticed, that I thought I had fixed though…

in this section:

foreach($dvh in $dvhash.keys)
{
	if($dvhash[$dvh] -like "*" + $audithash[$dvh] + "*" -or $audithash[$dvh] -like "*" + $dvhash[$dvh] + "*")
	{
		$dv = $dvh + ": " + $dvhash[$dvh]
		$mv = "$dvh is set to " + $audithash[$dvh]
		$state = "Passed"
		add-content ScanResults.csv "$($sectionhash.item($dvh))!C020-S-Gv1.0-WIN-MULTI!$svr!$os!$ls!Log Access Attempts!Audit Subcategory $dvh WIN-MULTI!$state!$mv!$dv !This fixlet checks if $dvh is set to Success. (0=No Logging, 1=Log Success, 2=Log Failure, 3=Log Success and Failure)"
	}	
	else
	{
		$dv = $dvh + ": " + $dvhash[$dvh]
		$mv = "$dvh is set to " + $audithash[$dvh]
		$state = "Failed"
		add-content ScanResults.csv "$($sectionhash.item($dvh))!C020-S-Gv1.0-WIN-MULTI!$svr!$os!$ls!Log Access Attempts!Audit Subcategory $dvh WIN-MULTI!$state!$mv!$dv !This fixlet checks if $dvh is set to Success. (0=No Logging, 1=Log Success, 2=Log Failure, 3=Log Success and Failure)"
	}

}

$audithash contains the actual values on the server
$dvhash contains the desired values the server must attain (or greater)

if the measured value of “SAM” = Failure but the desired value is success and failure it will fail

Alternatively if it’s SAM = ‘success and failure’ and the desired value is success it would pass.

I noticed my if statement is passing if the actual value contains success and the desired value is ‘success and failure’ it is still passing it…my brain is a little fried this afternoon but any helpful hints or nudges would really help me out here.

Thanks again for your help earlier with the hash

Plug your values into your IF statement and you can see why it is passing. Because you are using -or if either one of the conditions is TRUE, it passes. In all three scenarios you gave, your IF statement is TRUE on one of the conditions.

if("success and failure" -like "*Failure*" -or "failure" -like "*success and failure*")
                      TRUE                                 FALSE

if("success" -like "*success and failure*" -or "success and failure" -like "*success*")
                      FALSE                                 TRUE

if("success and failure" -like "*success*" -or "success" -like "*success and failure*")
                      TRUE                                 FALSE

You really just need a much simpler If statement

if($audithash[$dvh] -like "*" + $dvhash[$dvh] + "*")
{
    "Do this"
}	
else
{
    "Do this"
}

For Example

function Test {
    Param(
        [string]$actual,
        [string]$desired
    )

    if($actual -like "*$desired*") {
        $True
    }
    else
    {
        $False
    }
}

Results:

PS C:> Test -actual “Success” -desired “Success and Failure”
False

PS C:> Test -actual “Failure” -desired “Success and Failure”
False

PS C:> Test -actual “Success and Failure” -desired “Success and Failure”
True

PS C:> Test -actual “Success” -desired “Success”
True

PS C:> Test -actual “Failure” -desired “Success”
False

PS C:> Test -actual “Success and Failure” -desired “Success”
True

PS C:> Test -actual “Success” -desired “Failure”
False

PS C:> Test -actual “Failure” -desired “Failure”
True

PS C:> Test -actual “Success and Failure” -desired “Failure”
True

Curtis thanks a lot, I was thinking about this last night with a clear head and came up with that conclusion as well…you’ve really been a help thanks so much!