First version of subdomain takeover runbook

This commit is contained in:
Jurjen Ladenius
2021-09-01 16:25:01 +02:00
parent ec9d1d34ae
commit 3a348fc8b0
11 changed files with 810 additions and 187 deletions

View File

@@ -0,0 +1,39 @@
function Get-BlobEffectoryDomainResources {
<#
.SYNOPSIS
Retrieves the stored domain resources list
.DESCRIPTION
Retrieves the newest domain resources list from the CSV in Azure storage.
.PARAMETER connectionString
Connection string of the storage account to retrieve from.
#>
param(
[Parameter(Mandatory)]
[string] $connectionString
)
[EffectoryDomainNameCheck[]] $loadedResources = @()
$context = New-AzStorageContext -ConnectionString $connectionString
$blob = Get-AzStorageBlob -Container "dangling-dns" -Context $context | Sort-Object -Property Name | Select-Object -Last 1
if ($null -ne $blob) {
Get-AzStorageBlobContent -Context $context -CloudBlob $blob.ICloudBlob -Destination "$Env:temp/$($blob.Name).history.csv" -Force >$null
$loadedResources = Import-CSV "$Env:temp/$($blob.Name).history.csv"
Remove-Item -Path "$Env:temp/$($blob.Name).history.csv"
}
$loadedResources
}
# $context = New-AzStorageContext -ConnectionString "DefaultEndpointsProtocol=https;AccountName=runbookseffectory;AccountKey=PIyewEcppMcm8imMhpUUOgrOUbWyFPK0o8PfdwPnEiNvEQqUvTDzjuV4W18z2sBuRzspGs5pV/Fz96umfePviw==;EndpointSuffix=core.windows.net"
# Get-AzTrafficManagerProfile | Export-Csv "$Env:temp/test4.csv"
# Set-AzStorageBlobContent -Context $context -Container "dangling-dns" -File "$Env:temp/test4.csv" -Blob "test2.csv" -Force >$null
# Get-AzStorageBlobContent -Context $context -Container "dangling-dns" -Blob "test2.csv" -Destination "$Env:temp/test3.csv" -Force
# $foo = Import-CSV "$Env:temp/test3.csv"
# $foo

View File

@@ -1,134 +0,0 @@
#Requires -Modules Az.Accounts,Az.Websites,Az.FrontDoor,Az.Storage,Az.Cdn,Az.Network,Az.TrafficManager,Az.ContainerInstance
function Get-EffectoryDomainResources {
<#
.SYNOPSIS
Find resources in Azure that have DNS records
.DESCRIPTION
Gets all resources that have hostnames.
.PARAMETER subscriptionId
Optional Subscription Id to set the context to. Otherwise uses the current context.
#>
param(
[Parameter()]
[string] $subscriptionId
)
# Initialize
[EffectoryDomainNameCheck[]]$result = @()
[string]$effectoryDomainPattern = "*.effectory.com"
# Get subscription info
[Microsoft.Azure.Commands.Profile.Models.Core.PSAzureContext]$currentContext = $null
if (![string]::IsNullOrWhitespace($subscriptionId)) {
$currentContext = Set-AzContext -SubscriptionId $subscriptionId
}
else {
$currentContext = Get-AzContext
$subscriptionId = $currentContext.Subscription
}
Write-Host "Processing subscription $($currentContext.Name)"
# # ------------------------------------------------------------------------------------------------------------------
# Write-Host "Checking WebApps and WebApp Slots for subscription $($currentContext.Name)"
# $webApps = Get-AzWebApp
# [int]$webAppCounter = 0
# [int]$webAppSlotCounter = 0
# if ($null -ne $webApps) {
# # check webapps
# $itemsWebApps = CheckWebApps -subscription $currentContext -webApps $webApps -effectoryDomainPattern $effectoryDomainPattern
# $webAppCounter += $itemsWebApps.Count
# $result += $itemsWebApps
# # check webapp slots
# foreach ($webApp in $webApps) {
# $slot = Get-AzWebAppSlot -WebApp $webApp
# if ($null -ne $slot) {
# $itemsWebAppSlots = CheckWebApps -subscription $currentContext -webApps $slot -effectoryDomainPattern $effectoryDomainPattern
# $webAppSlotCounter += $itemsWebAppSlots.Count
# $result += $itemsWebAppSlots
# }
# }
# }
# Write-Host "Found $($webAppCounter) WebApps and $($webAppSlotsCounter) WebApp Slots for subscription $($currentContext.Name)"
# ------------------------------------------------------------------------------------------------------------------
Write-Host "Checking FrontDoor Endpoints for subscription $($currentContext.Name)"
$frontDoors = Get-AzFrontDoor
[int]$frontDoorEndPointCounter = 0
if ($null -ne $frontDoors) {
$itemsFrontDoors = CheckFrontDoorEndPoints -subscription $currentContext -frontDoors $frontDoors -effectoryDomainPattern $effectoryDomainPattern
$frontDoorEndPointCounter += $itemsFrontDoors.Count
$result += $itemsFrontDoors
}
Write-Host "Found $($frontDoorEndPointCounter) FrontDoor Endpoints for subscription $($currentContext.Name)"
# ------------------------------------------------------------------------------------------------------------------
Write-Host "Checking Storage Accounts for subscription $($currentContext.Name)"
$storageAccounts = Get-AzStorageAccount | Where-Object { $_.CustomDomain.Name -like $effectoryDomainPattern } # storage accounts
[int]$storageCounter = 0
if ($null -ne $storageAccounts) {
$itemsStorage = CheckStorageAccounts -subscription $currentContext -storageAccounts $storageAccounts -effectoryDomainPattern $effectoryDomainPattern
$storageCounter += $itemsStorage.Count
$result += $itemsStorage
}
Write-Host "Found $($storageCounter) Storage Accounts for subscription $($currentContext.Name)"
# # ------------------------------------------------------------------------------------------------------------------
# Write-Host "Checking Cdn Endpoints for subscription $($currentContext.Name)"
# $cdnProfiles = Get-AzCdnProfile
# [int]$cdnCounter = 0
# if ($null -ne $cdnProfiles) {
# $itemsCdn = CheckCdnEndpoints -subscription $currentContext -cdnProfiles $cdnProfiles -effectoryDomainPattern $effectoryDomainPattern
# $cdnCounter += $itemsCdn.Count
# $result += $itemsCdn
# }
# Write-Host "Found $($cdnCounter) Cdn Endpoints for subscription $($currentContext.Name)"
# # ------------------------------------------------------------------------------------------------------------------
# Write-Host "Checking public IP addresses for subscription $($currentContext.Name)"
# $ipAddresses = Get-AzPublicIpAddress | Where-Object DnsSettings -ne $null | Where-Object { $_.DnsSettings.DomainNameLabel -ne "" }
# [int]$ipCounter = 0
# if ($null -ne $ipAddresses) {
# $itemsIpAddresses = CheckIpAddresses -subscription $currentContext -ipAddresses $ipAddresses -effectoryDomainPattern $effectoryDomainPattern
# $ipCounter += $itemsIpAddresses.Count
# $result += $itemsIpAddresses
# }
# Write-Host "Found $($ipCounter) public IP addresses for subscription $($currentContext.Name)"
# # ------------------------------------------------------------------------------------------------------------------
# Write-Host "Checking Traffic Managers for subscription $($currentContext.Name)"
# $trafficManagers = Get-AzTrafficManagerProfile
# [int]$trafficManagerCounter = 0
# if ($null -ne $trafficManagers) {
# $itemsTrafficManagers = CheckTrafficManagers -subscription $currentContext -trafficManagers $trafficManagers -effectoryDomainPattern $effectoryDomainPattern
# $trafficManagerCounter += $itemsTrafficManagers.Count
# $result += $itemsTrafficManagers
# }
# Write-Host "Found $($trafficManagerCounter) Traffic Managers for subscription $($currentContext.Name)"
# # ------------------------------------------------------------------------------------------------------------------
# Write-Host "Checking Container groups for subscription $($currentContext.Name)"
# $containerInstances = Get-AzContainerGroup
# if ($null -ne $containerInstances) {
# throw "Container groups are not implemented yet."
# }
# # ------------------------------------------------------------------------------------------------------------------
# Write-Host "Checking API Management for subscription $($currentContext.Name)"
# $apiManagementServices = Get-AzApiManagement
# if ($null -ne $apiManagementServices) {
# throw "API Management services are not implemented yet."
# }
# ------------------------------------------------------------------------------------------------------------------
$result
}

View File

@@ -17,47 +17,22 @@ function Set-BlobEffectoryDomainResources {
[string] $connectionString
)
[string] $fileName = "$((Get-Date).ToString("yyyy-MM-dd hh-mm")) - resources.csv"
[string] $fileName = "$((Get-Date).ToString("yyyy-MM-dd HH-mm-ss")) - resources.csv"
Write-Host "Storing resources to $($fileName)"
$context = New-AzStorageContext -ConnectionString $connectionString
# move to history
$blobs = Get-AzStorageBlob -Container "dangling-dns" -Context $context
$blobs = Get-AzStorageBlob -Container "dangling-dns" -Context $context
if ($null -ne $blobs) {
foreach ($blob in $blobs) {
Start-AzStorageBlobCopy -CloudBlob $blob.ICloudBlob -DestContainer "dangling-dns-history" -DestBlob $blob.Name -Context $context
Remove-AzStorageBlob -Container "dangling-dns" -Blob $blob.Name -Context $context
Start-AzStorageBlobCopy -CloudBlob $blob.ICloudBlob -DestContainer "dangling-dns-history" -DestBlob $blob.Name -Context $context -Force >$null
Remove-AzStorageBlob -Container "dangling-dns" -Blob $blob.Name -Context $context -Force >$null
}
}
# store as current
$effectoryResources | Export-Csv "$Env:temp/$($fileName)"
Set-AzStorageBlobContent -Context $context -Container "dangling-dns" -File "$Env:temp/$($fileName)" -Blob $fileName -Force
}
# function Get-BlobEffectoryDomainResources {
# <#
# .SYNOPSIS
# -
# .DESCRIPTION
# -
# .PARAMETER subscriptionId
# -
# #>
# [EffectoryDomainNameCheck[]] $effectoryResources
# }
# $context = New-AzStorageContext -ConnectionString "DefaultEndpointsProtocol=https;AccountName=runbookseffectory;AccountKey=PIyewEcppMcm8imMhpUUOgrOUbWyFPK0o8PfdwPnEiNvEQqUvTDzjuV4W18z2sBuRzspGs5pV/Fz96umfePviw==;EndpointSuffix=core.windows.net"
# Get-AzTrafficManagerProfile | Export-Csv "$Env:temp/test4.csv"
# Set-AzStorageBlobContent -Context $context -Container "dangling-dns" -File "$Env:temp/test4.csv" -Blob "test2.csv" -Force >$null
# Get-AzStorageBlobContent -Context $context -Container "dangling-dns" -Blob "test2.csv" -Destination "$Env:temp/test3.csv" -Force
# $foo = Import-CSV "$Env:temp/test3.csv"
# $foo
Set-AzStorageBlobContent -Context $context -Container "dangling-dns" -File "$Env:temp/$($fileName)" -Blob $fileName -Force >$null
Remove-Item -Path "$Env:temp/$($fileName)"
}

View File

@@ -0,0 +1,50 @@
function VerifyEffectoryDomainResources {
<#
.SYNOPSIS
Find resources in Azure that no longer exist, but have DNS records.
.DESCRIPTION
Gets all resources that have hostnames.
.PARAMETER effectoryDomainPattern
The domain pattern to look for when enumerating hosts, e.g. '*.effectory.com'
.PARAMETER effectoryResources
The resources that currently exist.
.PARAMETER effectoryResourcesPrevious
The resources that existed previously.
#>
param(
[Parameter(Mandatory)]
[string] $effectoryDomainPattern,
[Parameter(Mandatory)]
[AllowNull()]
[EffectoryDomainNameCheck[]] $effectoryResources,
[Parameter(Mandatory)]
[AllowNull()]
[EffectoryDomainNameCheck[]] $effectoryResourcesPrevious
)
[bool] $hasErrors = $false
# ----------------------------------------------------------------------------------------------------------
Write-Information "Comparing found resources with previously stored resources to find records that should've been deleted."
foreach ($oldResource in $effectoryResourcesPrevious) {
$currentItem = $effectoryResources.Where({$_.DomainName -eq $oldResource.DomainName}, 'First')
if (($null -eq $currentItem) -or ($currentItem.Count -eq 0)) {
# Host name no longer exists, so there should be no DNS record
# check
Write-Warning "Host name '$($oldResource.DomainName)' no longer exists. Checking DNS record for '$($oldResource.ResourceName)' ($($oldResource.ResourceType))."
$CName = DnsResolveHost -domainName $oldResource.DomainName -effectoryDomainPattern $effectoryDomainPattern -externalDNSServer "8.8.8.8"
if (($null -ne $CName) -and ($CName -ne "")) {
Write-Error "Host name '$($oldResource.DomainName)' no longer exists, but found DNS record '$($CName)' for '$($oldResource.ResourceName)' ($($oldResource.ResourceType))."
$hasErrors = $true
}
}
elseif (($oldResource.ResourceName -ne $currentItem.ResourceName) -or ($oldResource.ResourceId -ne $currentItem.ResourceId)) {
# found, but does not point to the same resource
# verify the DNS record to make sure it points to this resource
Write-Warning "Host name '$($oldResource.DomainName)' was found, but points to another resource. Assuming this was intentional."
}
}
$hasErrors
}