Skip to content

Commit

Permalink
Merge pull request l0ss#4 from l0ss/dev
Browse files Browse the repository at this point in the history
Dev to Master
  • Loading branch information
l0ss authored Feb 8, 2018
2 parents 419f484 + 16f1066 commit 67a665f
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 43 deletions.
4 changes: 3 additions & 1 deletion TODO
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
Get-GPORegSettings - implement filtering - very noisy
Get-GPORegSettings - fix output of .value, add output for *.extension.policy.dropdownlist.value.name.innertext
Get-GPORegSettings - fix output of .value
Get-GPOFilePerms - parse SDDL
Get-GPOAccountSettings - implement filtering
Get-GPOFolderRedirection - get permissions on target path

207 changes: 165 additions & 42 deletions grouper.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ $Global:intRights += "SeCreateGlobalPrivilege"
$Global:intRights += "SeLoadDriverPrivilege"
$Global:intRights += "SeRemoteInteractiveLogonRight"

$Global:boringTrustees = @()
$Global:boringTrustees += "BUILTIN\Administrators"
$Global:boringTrustees += "NT AUTHORITY\SYSTEM"

#____________________ GPO Check functions _______________

# There's a whole pile of these functions. Each one consumes a single <GPO> object from a Get-GPOReport XML report,
Expand Down Expand Up @@ -369,21 +373,40 @@ Function Get-GPOMSIInstallation {
######
# Description: Checks for MSI installers being used to install software.
# Vulnerable: TODO Only show instances where the file is writable by the current user or 'Everyone' or 'Domain Users' or 'Authenticated Users'.
# Interesting: TODO Also show instances where any user/group other than the usual default Domain/Enterprise Admins has 'Full Control'.
# Interesting: All MSI installations.
# Boring: All MSI installations.
######

$computerMSIInstallation = ($polXml.Computer.ExtensionData.Extension.MsiApplication | Sort-Object GPOSettingOrder)
$MSIInstallation = ($polXml.ExtensionData.Extension.MsiApplication | Sort-Object GPOSettingOrder)

if ($MSIInstallation) {
foreach ($setting in $MSIInstallation) {
$output = @{}
$MSIPath = $setting.Path
$output.Add("Name", $setting.Name)
$output.Add("Path", $MSIPath)

if ($Global:onlineChecks -eq 1) {
if ($MSIPath.StartsWith("\\")) {
$ACLData = Find-IntACL -Path $MSIPath
$output.Add("Owner",$ACLData["Owner"])
if ($ACLData["Vulnerable"] -eq "True") {
$settingisvulnerable = 1
$output.Add("[!]", "Source file writable by current user!")
}
$MSIPathAccess = $ACLData["Trustees"]
}
}

if ($computerMSIInstallation) {
foreach ($setting in $computerMSIInstallation) {
if ($level -eq 1) {
$output = @{}
$output.Add("Name", $setting.Name)
$output.Add("Path", $setting.Path)
if (($level -le 2) -Or (($level -le 3) -And ($settingisVulnerable -eq 1))) {
Write-NoEmpties -output $output
"`r`n"
if ($MSIPathAccess) {
""
Write-Title -Text "Permissions on source file:" -DividerChar "-"
Write-Output $MSIPathAccess
}
}
"`r`n"
}
}
}
Expand All @@ -398,22 +421,43 @@ Function Get-GPOScripts {
######
# Description: Checks for startup/shutdown/logon/logoff scripts.
# Vulnerable: TODO Only show instances where the file is writable by the current user or 'Everyone' or 'Domain Users' or 'Authenticated Users'.
# Interesting: TODO Also show instances where any user/group other than the usual default Domain/Enterprise Admins has 'Full Control' or where 'Parameters' is set.
# Interesting: All scripts.
# Boring: All scripts.
######

$settingsScripts = ($polXml.ExtensionData.Extension.Script | Sort-Object GPOSettingOrder)

if ($settingsScripts) {
foreach ($setting in $settingsScripts) {
if ($level -eq 1) {
$output = @{}
$output.Add("Command", $setting.Command)
$output.Add("Type", $setting.Type)
$output.Add("Parameters", $setting.Parameters)
Write-NoEmpties -output $output
"`r`n"
$commandPath = $setting.Command
$output = @{}
$output.Add("Command", $commandPath)
$output.Add("Type", $setting.Type)
$output.Add("Parameters", $setting.Parameters)
$settingIsVulnerable = 0

if ($Global:onlineChecks -eq 1) {
if ($commandPath.StartsWith("\\")) {
$ACLData = Find-IntACL -Path $commandPath
$output.Add("Owner",$ACLData["Owner"])
if ($ACLData["Vulnerable"] -eq "True") {
$settingisvulnerable = 1
$output.Add("[!]", "Source file writable by current user!")
}
$commandPathAccess = $ACLData["Trustees"]
}
}

if (($level -le 2) -Or (($level -le 3) -And ($settingisVulnerable -eq 1))) {
Write-NoEmpties -output $output
if ($commandPathAccess) {
""
Write-Title -Text "Permissions on source file:" -DividerChar "-"
Write-Output $commandPathAccess
}
}
"`r`n"

}
}
}
Expand All @@ -426,25 +470,46 @@ Function Get-GPOFileUpdate {
)

######
# Description: Checks for MSI installers being used to install software.
# Description: Checks for files being copied/updated/whatever.
# Vulnerable: TODO Only show instances where the 'fromPath' file is writable by the current user or 'Everyone' or 'Domain Users' or 'Authenticated Users'.
# Interesting: TODO Also show instances where any user/group other than the usual default Domain/Enterprise Admins has 'Full Control' of the 'fromPath' file.
# Interesting: All File Updates where FromPath is a network share
# Boring: All File Updates.
######

$settingsFiles = ($polXml.ExtensionData.Extension.FilesSettings | Sort-Object GPOSettingOrder)

if ($settingsFiles) {
foreach ($setting in $settingsFiles.File) {
if ($level -eq 1) {
$output = @{}
$output.Add("Name", $setting.name)
$output.Add("Action", $setting.Properties.action)
$output.Add("fromPath", $setting.Properties.fromPath)
$output.Add("targetPath", $setting.Properties.targetPath)
$fromPath = $setting.Properties.fromPath
$targetPath = $setting.Properties.targetPath
$output = @{}
$output.Add("Name", $setting.name)
$output.Add("Action", $setting.Properties.action)
$output.Add("fromPath", $fromPath)
$output.Add("targetPath", $targetPath)
$settingIsVulnerable = 0

if ($Global:onlineChecks -eq 1) {
if ($fromPath.StartsWith("\\")) {
$ACLData = Find-IntACL -Path $fromPath
$output.Add("Owner",$ACLData["Owner"])
if ($ACLData["Vulnerable"] -eq "True") {
$settingisvulnerable = 1
$output.Add("[!]", "Source file writable by current user!")
}
$fromPathAccess = $ACLData["Trustees"]
}
}

if (($level -le 2) -Or (($level -le 3) -And ($settingisVulnerable -eq 1))) {
Write-NoEmpties -output $output
"`r`n"
if ($fromPathAccess) {
""
Write-Title -Text "Permissions on source file:" -DividerChar "-"
Write-Output $fromPathAccess
}
}
"`r`n"
}
}
}
Expand Down Expand Up @@ -1017,21 +1082,39 @@ Function Get-GPOShortcuts {
if ($settingsShortcuts) {
# Iterate over array of settings, writing out only those we care about.
foreach ($setting in $settingsShortcuts) {
if ($level -eq 1) {
$output = @{}
$output.Add("Name", $setting.name)
$output.Add("Status", $setting.status)
$output.Add("targetType", $setting.properties.targetType)
$output.Add("Action", $setting.properties.Action)
$output.Add("comment", $setting.properties.comment)
$output.Add("startIn", $setting.properties.startIn)
$output.Add("arguments", $setting.properties.arguments)
$output.Add("targetPath", $setting.properties.targetPath)
$output.Add("iconPath", $setting.properties.iconPath)
$output.Add("shortcutPath", $setting.properties.shortcutPath)
$targetPath = $setting.properties.targetPath
$output = @{}
$output.Add("Name", $setting.name)
$output.Add("Status", $setting.status)
$output.Add("targetType", $setting.properties.targetType)
$output.Add("Action", $setting.properties.Action)
$output.Add("comment", $setting.properties.comment)
$output.Add("startIn", $setting.properties.startIn)
$output.Add("arguments", $setting.properties.arguments)
$output.Add("targetPath", $setting.properties.targetPath)
$output.Add("iconPath", $setting.properties.iconPath)
$output.Add("shortcutPath", $setting.properties.shortcutPath)
if ($Global:onlineChecks -eq 1) {
if ($targetPath.StartsWith("\\")) {
$ACLData = Find-IntACL -Path $targetPath
$output.Add("Owner",$ACLData["Owner"])
if ($ACLData["Vulnerable"] -eq "True") {
$settingisvulnerable = 1
$output.Add("[!]", "Source file writable by current user!")
}
$targetPathAccess = $ACLData["Trustees"]
}
}

if (($level -le 2) -Or (($level -le 3) -And ($settingisVulnerable -eq 1))) {
Write-NoEmpties -output $output
"`r`n"
if ($targetPathAccess) {
""
Write-Title -Text "Permissions on source file:" -DividerChar "-"
Write-Output $targetPathAccess
}
}
"`r`n"
}
}
}
Expand Down Expand Up @@ -1134,6 +1217,30 @@ Function Write-Banner {
}
}

Function Find-IntACL {
Param (
[Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$Path
)
$ACLData = @{}
try {
$targetPathACL = Get-ACL $Path -ErrorAction Stop
$targetPathOwner = $targetPathACL.Owner
$targetPathAccess = $targetPathACL.Access | Where-Object {-Not ($Global:boringTrustees -Contains $_.IdentityReference)} | select FileSystemRights,AccessControlType,IdentityReference
$ACLData.Add("Owner", $targetPathOwner)
$ACLData.Add("Trustees", $targetPathAccess)
Try {
[io.file]::OpenWrite($targetPath).close()
$ACLData.Add("Vulnerable","True")
}
Catch {
$ACLData.Add("Vulnerable","False")
}
}
catch [System.Exception] {
$ACLData.Add("Vulnerable","Error")
}
return $ACLData
}

#_____________________________________________________________________
Function Invoke-AuditGPO {
Expand Down Expand Up @@ -1176,7 +1283,8 @@ Function Invoke-AuditGPO {
$polchecks += {Get-GPOScripts -Level $level -polXML $computerSettings}
$polchecks += {Get-GPOFileUpdate -Level $level -polXML $userSettings}
$polchecks += {Get-GPOFileUpdate -Level $level -polXML $computerSettings}
$polchecks += {Get-GPOMSIInstallation -Level $level -polXML $xmlgpo}
$polchecks += {Get-GPOMSIInstallation -Level $level -polXML $userSettings}
$polchecks += {Get-GPOMSIInstallation -Level $level -polXML $computerSettings}
$polchecks += {Get-GPOUserRights -Level $level -polXML $xmlgpo}
$polchecks += {Get-GPOSchedTasks -Level $level -polXML $xmlgpo}
$polchecks += {Get-GPOFolderRedirection -Level $level -polXML $xmlgpo}
Expand Down Expand Up @@ -1332,7 +1440,9 @@ Function Invoke-AuditGPOReport {
ParameterSetName='WithoutFile', Mandatory=$false
)]
[ValidateSet(1,2,3)]
[int]$level = 2
[int]$level = 2,

[switch]$online
)

Write-Banner
Expand All @@ -1353,6 +1463,20 @@ Function Invoke-AuditGPOReport {
$Global:showDisabled = 1
}

# quick and dirty check to make sure that if the user said to do 'online' checks that we can actually reach the domain.
$Global:onlineChecks = 0
if ($online) {
try {
net accounts /domain 1> $null
$Global:onlineChecks = 1
}
catch {
Write-Output "Couldn't talk to the domain, falling back to offline mode."
$Global:onlineChecks =0
}

}

if ($lazyMode) {
$requiredModules = @('GroupPolicy')
$requiredModules | Import-Module -Verbose:$false -ErrorAction SilentlyContinue
Expand Down Expand Up @@ -1394,4 +1518,3 @@ Function Invoke-AuditGPOReport {
$stats += ('Total GPOs: {0}' -f $gpocount)
Write-Output $stats
}

0 comments on commit 67a665f

Please sign in to comment.