I have a bunch of machines being monitored by adaptive application security controls that are giving warnings because the training process was not ran long enough to recognize benign executables. What's an easy way to add exceptions for the executables in active alerts to the adaptive security groups?
This script grabs the active alerts from defender, and updates the groups. The alerts must still be dismissed manually.
function Get-ExistingRules {
Param(
$subscriptionId,
$groupName
)
$url = "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.Security/locations/centralus/applicationWhitelistings/${groupName}?api-version=2015-06-01-preview";
return az rest `
--method get `
--url $url `
| ConvertFrom-Json;
}
function Add-NewRules {
Param(
$subscriptionId,
$groupName,
$files
)
$url = "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.Security/locations/centralus/applicationWhitelistings/${groupName}?api-version=2015-06-01-preview";
$existing = Get-ExistingRules $subscriptionId $groupName;
$existing | ConvertTo-Json -Depth 100 > asd.json;
$myList = $existing.properties.pathRecommendations;
foreach ($file in $files) {
$myList += [pscustomobject]@{
path = $file.path
type = "File"
common = $true
action = "Add"
usernames = @(
[pscustomobject]@{
username = "Everyone"
recommendationAction = "Recommended"
}
)
userSids = @(
"S-1-1-0"
)
fileType = $file.type
configurationStatus = "NotConfigured"
};
}
$existing.properties.pathRecommendations = $myList;
$existing.properties = [pscustomobject]@{
protectionMode = $existing.properties.protectionMode
vmRecommendations = $existing.properties.vmRecommendations
pathRecommendations = $existing.properties.pathRecommendations
}
$existing.PSObject.properties.remove("location");
# return $existing;
$body = $existing | ConvertTo-Json -Depth 20 -Compress;
$body > temp.json;
# $body = $body -replace "`"", "\`"";
# return az rest `
# --method PUT `
# --url $url `
# --body $body `
# | ConvertFrom-Json;
# avoid max command length limit by storing body in a file
try {
return az rest `
--method PUT `
--url $url `
--body `@temp.json `
| ConvertFrom-Json;
}
catch {
Write-Warning "Encountered error adding rule";
Write-Warning "$_";
}
return $null;
}
function Format-Body {
param(
$obj
)
$body = $obj | ConvertTo-Json -Depth 100 -Compress;
$body = $body -replace "`"", "\`"";
$body = $body -replace "`r", "";
return $body;
}
Write-Host "Listing subscriptions";
# you can filter to just one subscription if you want
# $subscriptions = az account list --query "[?name=='NPRD'].id" --output tsv;
$subscriptions = az account list --query "[].id" --output tsv;
$allAlerts = New-Object System.Collections.ArrayList;
$i = 0;
foreach ($sub in $subscriptions) {
Write-Progress -Id 0 -Activity "Fetching alerts" -Status $sub -PercentComplete ($i / $subscriptions.Count * 100);
$i = $i++;
$alerts = az security alert list `
--subscription $sub `
| ConvertFrom-Json `
| Where-Object { @("VM_AdaptiveApplicationControlLinuxViolationAudited", "VM_AdaptiveApplicationControlWindowsViolationAudited") -contains $_.alertType } `
| Where-Object { $_.status -eq "Active" };
foreach ($x in $alerts) {
$allAlerts.Add($x) > $null;
}
}
Write-Progress -Id 0 "Done" -Completed;
function Get-Files {
Param(
$alert
)
if ($alert.alertType -eq "VM_AdaptiveApplicationControlLinuxViolationAudited") {
$fileType = "executable";
}
else {
$fileType = "exe";
}
$pattern = "Path: (.*?);";
$str = $alert.extendedProperties.file;
return $str `
| Select-String -Pattern $pattern -AllMatches `
| ForEach-Object { $_.Matches } `
| ForEach-Object { $_.Value } `
| ForEach-Object { [pscustomobject]@{
path = $_
type = $fileType
}};
}
$alertGroups = $allAlerts | Select-Object *, @{Name = "groupName"; Expression = { $_.extendedProperties.groupName } } | Group-Object groupName;
foreach ($group in $alertGroups) {
$groupName = $group.Name;
$group.Group[0].id -match "/subscriptions/([^/]+)/" > $null;
$subscriptionId = $matches[1];
$files = $group.Group | ForEach-Object { Get-Files $_ };
Write-Host "Adding file path rule sub=$subscriptionId group=$groupName count=$($files.Count)";
Add-NewRules $subscriptionId $groupName $files;
}