@@ -9,6 +9,7 @@ Read more about Detection Lab on Medium here: https://medium.com/@clong/introduc
|
||||
NOTE: This lab has not been hardened in any way and runs with default vagrant credentials. Please do not connect or bridge it to any networks you care about. This lab is deliberately designed to be insecure; the primary purpose of it is to provide visibility and introspection into each host.
|
||||
|
||||
## Primary Lab Features:
|
||||
* Microsoft Advanced Threat Analytics (https://www.microsoft.com/en-us/cloud-platform/advanced-threat-analytics) is installed on the WEF machine, with the lightweight ATA gateway installed on the DC
|
||||
* Splunk forwarders are pre-installed and all indexes are pre-created. Technology add-ons for Windows are also preconfigured.
|
||||
* A custom Windows auditing configuration is set via GPO to include command line process auditing and additional OS-level logging
|
||||
* [Palantir's Windows Event Forwarding](http://github.com/palantir/windows-event-forwarding) subscriptions and custom channels are implemented
|
||||
@@ -19,6 +20,7 @@ NOTE: This lab has not been hardened in any way and runs with default vagrant cr
|
||||
* All autostart items are logged to Windows Event Logs via [AutorunsToWinEventLog](https://github.com/palantir/windows-event-forwarding/tree/master/AutorunsToWinEventLog)
|
||||
* SMBv1 Auditing is enabled
|
||||
|
||||
|
||||
## Requirements
|
||||
* 55GB+ of free disk space
|
||||
* 16GB+ of RAM
|
||||
@@ -124,6 +126,7 @@ Vagrant commands must be run from the "Vagrant" folder.
|
||||
* Fleet login: https://192.168.38.5:8412 - admin:admin123#
|
||||
* Splunk login: https://192.168.38.5:8000 - admin:changeme
|
||||
* Caldera login: https://192.168.38.5:8888 - admin:caldera
|
||||
* MS ATA login: https://192.168.38.3 - wef\vagrant:vagrant
|
||||
|
||||
## Lab Hosts
|
||||
* DC - Windows 2016 Domain Controller
|
||||
@@ -134,7 +137,9 @@ Vagrant commands must be run from the "Vagrant" folder.
|
||||
* osquery
|
||||
* Splunk Universal Forwarder (Forwards Sysmon & osquery)
|
||||
* Sysinternals Tools
|
||||
* Microsft Advanced Threat Analytics Lightweight Gateway
|
||||
* WEF - Windows 2016 Server
|
||||
* Microsoft Advanced Threat Analytics
|
||||
* Windows Event Collector
|
||||
* Windows Event Subscription Creation
|
||||
* Powershell transcription logging share
|
||||
@@ -236,6 +241,7 @@ Requests for tools and features will be reviewed on a case by case basis, but I
|
||||
A sizable percentage of this code was borrowed and adapted from [Stefan Scherer](https://twitter.com/stefscherer)'s [packer-windows](https://github.com/StefanScherer/packer-windows) and [adfs2](https://github.com/StefanScherer/adfs2) Github repos. A huge thanks to him for building the foundation that allowed me to design this lab environment.
|
||||
|
||||
# Acknowledgements
|
||||
* [Microsoft Advanced Threat Analytics](https://www.microsoft.com/en-us/cloud-platform/advanced-threat-analytics)
|
||||
* [Splunk](https://www.splunk.com)
|
||||
* [osquery](https://osquery.io)
|
||||
* [Fleet](https://kolide.co/fleet)
|
||||
|
||||
13
Vagrant/Vagrantfile
vendored
13
Vagrant/Vagrantfile
vendored
@@ -57,15 +57,15 @@ Vagrant.configure("2") do |config|
|
||||
|
||||
cfg.vm.provider "vmware_fusion" do |v, override|
|
||||
override.vm.box = "../Boxes/windows_2016_vmware.box"
|
||||
v.memory = 2048
|
||||
v.cpus = 1
|
||||
v.memory = 2560
|
||||
v.cpus = 2
|
||||
v.gui = true
|
||||
end
|
||||
|
||||
cfg.vm.provider "virtualbox" do |vb, override|
|
||||
vb.gui = true
|
||||
vb.customize ["modifyvm", :id, "--memory", 2048]
|
||||
vb.customize ["modifyvm", :id, "--cpus", 1]
|
||||
vb.customize ["modifyvm", :id, "--memory", 2560]
|
||||
vb.customize ["modifyvm", :id, "--cpus", 2]
|
||||
vb.customize ["modifyvm", :id, "--vram", "32"]
|
||||
vb.customize ["modifyvm", :id, "--clipboard", "bidirectional"]
|
||||
vb.customize ["setextradata", "global", "GUI/SuppressMessages", "all" ]
|
||||
@@ -96,18 +96,19 @@ Vagrant.configure("2") do |config|
|
||||
cfg.vm.provision "shell", path: "scripts/configure-pslogstranscriptsshare.ps1", privileged: true
|
||||
cfg.vm.provision "shell", path: "scripts/install-autorunstowineventlog.ps1", privileged: true
|
||||
cfg.vm.provision "shell", inline: "Set-SmbServerConfiguration -AuditSmb1Access $true -Force", privileged: true
|
||||
cfg.vm.provision "shell", path: "scripts/install-microsoft-ata.ps1", privileged: true
|
||||
|
||||
cfg.vm.provider "vmware_fusion" do |v, override|
|
||||
override.vm.box = "../Boxes/windows_2016_vmware.box"
|
||||
v.memory = 2048
|
||||
v.cpus = 1
|
||||
v.cpus = 2
|
||||
v.gui = true
|
||||
end
|
||||
|
||||
cfg.vm.provider "virtualbox" do |vb, override|
|
||||
vb.gui = true
|
||||
vb.customize ["modifyvm", :id, "--memory", 2048]
|
||||
vb.customize ["modifyvm", :id, "--cpus", 1]
|
||||
vb.customize ["modifyvm", :id, "--cpus", 2]
|
||||
vb.customize ["modifyvm", :id, "--vram", "32"]
|
||||
vb.customize ["modifyvm", :id, "--clipboard", "bidirectional"]
|
||||
vb.customize ["setextradata", "global", "GUI/SuppressMessages", "all" ]
|
||||
|
||||
File diff suppressed because one or more lines are too long
123
Vagrant/scripts/install-microsoft-ata.ps1
Normal file
123
Vagrant/scripts/install-microsoft-ata.ps1
Normal file
@@ -0,0 +1,123 @@
|
||||
# Purpose: Downloads, installs and configures Microsft ATA 1.9
|
||||
$title = "Microsoft ATA 1.9"
|
||||
$downloadUrl = "http://download.microsoft.com/download/4/9/1/491394D1-3F28-4261-ABC6-C836A301290E/ATA1.9.iso"
|
||||
$fileHash = "DC1070A9E8F84E75198A920A2E00DDC3CA8D12745AF64F6B161892D9F3975857" # Use Get-FileHash on a correct downloaded file to get the hash
|
||||
|
||||
# Enable web requests to endpoints with invalid SSL certs (like self-signed certs)
|
||||
if (-not("SSLValidator" -as [type])) {
|
||||
add-type -TypeDefinition @"
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
public static class SSLValidator {
|
||||
public static bool ReturnTrue(object sender,
|
||||
X509Certificate certificate,
|
||||
X509Chain chain,
|
||||
SslPolicyErrors sslPolicyErrors) { return true; }
|
||||
|
||||
public static RemoteCertificateValidationCallback GetDelegate() {
|
||||
return new RemoteCertificateValidationCallback(SSLValidator.ReturnTrue);
|
||||
}
|
||||
}
|
||||
"@
|
||||
}
|
||||
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = [SSLValidator]::GetDelegate()
|
||||
|
||||
if (-not (Test-Path "C:\Program Files\Microsoft Advanced Threat Analytics\Center"))
|
||||
{
|
||||
$download = $false
|
||||
if (-not (Test-Path "$env:temp\$title.iso"))
|
||||
{
|
||||
Write-Host "$title.iso doesn't exist yet, downloading..."
|
||||
$download = $true
|
||||
}
|
||||
else
|
||||
{
|
||||
$actualHash = (Get-FileHash -Algorithm SHA256 -Path "$env:temp\$title.iso").Hash
|
||||
If (-not ($actualHash -eq $fileHash))
|
||||
{
|
||||
Write-Host "$title.iso exists, but has wrong hash, downloading..."
|
||||
$download = $true
|
||||
}
|
||||
}
|
||||
if ($download -eq $true)
|
||||
{
|
||||
Write-Host "Downloading $title..."
|
||||
Invoke-WebRequest -Uri $downloadUrl -OutFile "$env:temp\$title.iso"
|
||||
$actualHash = (Get-FileHash -Algorithm SHA256 -Path "$env:temp\$title.iso").Hash
|
||||
If (-not ($actualHash -eq $fileHash))
|
||||
{
|
||||
throw "$title.iso was not downloaded correctly: hash from downloaded file: $actualHash, should've been: $fileHash"
|
||||
}
|
||||
}
|
||||
$Mount = Mount-DiskImage -ImagePath "$env:temp\$title.iso" -StorageType ISO -Access ReadOnly -PassThru
|
||||
$Volume = $Mount | Get-Volume
|
||||
Write-Host "Installing $title"
|
||||
$Install = Start-Process -Wait -FilePath ($Volume.DriveLetter + ":\Microsoft ATA Center Setup.exe") -ArgumentList "/q --LicenseAccepted NetFrameworkCommandLineArguments=`"/q`" --EnableMicrosoftUpdate" -PassThru
|
||||
$Install
|
||||
$Mount | Dismount-DiskImage -Confirm:$false
|
||||
$body = get-content "C:\vagrant\resources\microsoft_ata\microsoft-ata-config.json"
|
||||
|
||||
$req = [System.Net.WebRequest]::CreateHttp("https://wef")
|
||||
try
|
||||
{
|
||||
$req.GetResponse()
|
||||
}
|
||||
catch
|
||||
{
|
||||
# we don't care about errors here, we just want to get the cert ;)
|
||||
}
|
||||
$ThumbPrint = $req.ServicePoint.Certificate.GetCertHashString()
|
||||
$body = $body -replace "{{THUMBPRINT}}", $ThumbPrint
|
||||
|
||||
Invoke-RestMethod -uri https://localhost/api/management/systemProfiles/center -body $body -Method Post -UseBasicParsing -UseDefaultCredentials -ContentType "application/json"
|
||||
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds 60
|
||||
|
||||
Invoke-Command -computername dc -Credential (new-object pscredential("windomain\vagrant",(ConvertTo-SecureString -AsPlainText -Force -String "vagrant"))) -ScriptBlock {
|
||||
|
||||
Write-Host "[$env:computername] Installing ATA Lightweight gateway..."
|
||||
|
||||
# Enable web requests to endpoints with invalid SSL certs (like self-signed certs)
|
||||
if (-not("SSLValidator" -as [type])) {
|
||||
add-type -TypeDefinition @"
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
public static class SSLValidator {
|
||||
public static bool ReturnTrue(object sender,
|
||||
X509Certificate certificate,
|
||||
X509Chain chain,
|
||||
SslPolicyErrors sslPolicyErrors) { return true; }
|
||||
|
||||
public static RemoteCertificateValidationCallback GetDelegate() {
|
||||
return new RemoteCertificateValidationCallback(SSLValidator.ReturnTrue);
|
||||
}
|
||||
}
|
||||
"@
|
||||
}
|
||||
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = [SSLValidator]::GetDelegate()
|
||||
|
||||
Invoke-WebRequest -uri https://wef/api/management/softwareUpdates/gateways/deploymentPackage -UseBasicParsing -OutFile "$env:temp\gatewaysetup.zip" -Credential (new-object pscredential("wef\vagrant",(convertto-securestring -AsPlainText -Force -String "vagrant")))
|
||||
Expand-Archive -Path "$env:temp\gatewaysetup.zip" -DestinationPath "$env:temp\gatewaysetup" -Force
|
||||
|
||||
Set-Location "$env:temp\gatewaysetup"
|
||||
Start-Process -Wait -FilePath ".\Microsoft ATA Gateway Setup.exe" -ArgumentList "/q NetFrameworkCommandLineArguments=`"/q`" ConsoleAccountName=`"wef\vagrant`" ConsoleAccountPassword=`"vagrant`""
|
||||
# Disable invalid web requests to endpoints with invalid SSL certs again
|
||||
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null
|
||||
}
|
||||
|
||||
# set dc as domain synchronizer
|
||||
$config = Invoke-RestMethod -Uri "https://localhost/api/management/systemProfiles/gateways" -UseDefaultCredentials -UseBasicParsing
|
||||
$config[0].Configuration.DirectoryServicesResolverConfiguration.UpdateDirectoryEntityChangesConfiguration.IsEnabled = $true
|
||||
|
||||
Invoke-RestMethod -Uri "https://localhost/api/management/systemProfiles/gateways/$($config[0].Id)" -UseDefaultCredentials -UseBasicParsing -Method Post -ContentType "application/json" -Body ($config[0] | convertto-json -depth 99)
|
||||
|
||||
# Disable invalid web requests to endpoints with invalid SSL certs again
|
||||
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null
|
||||
28
build.ps1
28
build.ps1
@@ -349,13 +349,17 @@ function vagrant_reload_host {
|
||||
function download {
|
||||
param(
|
||||
[string]$URL,
|
||||
[string]$PatternToMatch
|
||||
[string]$PatternToMatch,
|
||||
[switch]$SuccessOn401
|
||||
|
||||
)
|
||||
Write-Verbose "[download] Running for $URL, looking for $PatternToMatch"
|
||||
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
|
||||
[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"
|
||||
|
||||
$wc = New-Object System.Net.WebClient
|
||||
try
|
||||
{
|
||||
$result = $wc.DownloadString($URL)
|
||||
if ($result -like "*$PatternToMatch*") {
|
||||
Write-Verbose "[download] Found $PatternToMatch at $URL"
|
||||
@@ -365,6 +369,20 @@ function download {
|
||||
Write-Verbose "[download] Could not find $PatternToMatch at $URL"
|
||||
return $false
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if ($_.Exception.InnerException.Response.StatusCode -eq 401 -and $SuccessOn401.IsPresent)
|
||||
{
|
||||
return $true
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Verbose "Error occured on webrequest: $_"
|
||||
return $false
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function post_build_checks {
|
||||
@@ -381,6 +399,11 @@ function post_build_checks {
|
||||
$FLEET_CHECK = download -URL 'https://192.168.38.5:8412' -PatternToMatch 'Kolide Fleet'
|
||||
Write-Verbose "[post_build_checks] Fleet Result: $FLEET_CHECK"
|
||||
|
||||
Write-Verbose '[post_build_checks] Running MS ATA Check.'
|
||||
$ATA_CHECK = download -URL 'https://192.168.38.3' -SuccessOn401
|
||||
Write-Verbose "[post_build_checks] ATA Result: $ATA_CHECK"
|
||||
|
||||
|
||||
if ($CALDERA_CHECK -eq $false) {
|
||||
Write-Warning 'Caldera failed post-build tests and may not be functioning correctly.'
|
||||
}
|
||||
@@ -390,6 +413,9 @@ function post_build_checks {
|
||||
if ($FLEET_CHECK -eq $false) {
|
||||
Write-Warning 'Fleet failed post-build tests and may not be functioning correctly.'
|
||||
}
|
||||
if ($ATA_CHECK -eq $false) {
|
||||
Write-Warning 'MS ATA failed post-build tests and may not be functioning correctly.'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
7
build.sh
7
build.sh
@@ -253,12 +253,14 @@ post_build_checks() {
|
||||
CALDERA_CHECK=$(curl -ks -m 2 https://192.168.38.5:8888 | grep -c '302: Found' || echo "")
|
||||
SPLUNK_CHECK=$(curl -ks -m 2 https://192.168.38.5:8000/en-US/account/login?return_to=%2Fen-US%2F | grep -c 'This browser is not supported by Splunk' || echo "")
|
||||
FLEET_CHECK=$(curl -ks -m 2 https://192.168.38.5:8412 | grep -c 'Kolide Fleet' || echo "")
|
||||
ATA_CHECK=$(curl --fail --write-out "%{http_code}" -ks https://192.168.38.3 -m 2)
|
||||
[[ $ATA_CHECK == 401 ]] && ATA_CHECK=1
|
||||
|
||||
BASH_MAJOR_VERSION=$(/bin/bash --version | grep 'GNU bash' | grep -o version\.\.. | cut -d ' ' -f 2 | cut -d '.' -f 1)
|
||||
# Associative arrays are only supported in bash 4 and up
|
||||
if [ "$BASH_MAJOR_VERSION" -ge 4 ]; then
|
||||
declare -A SERVICES
|
||||
SERVICES=(["caldera"]="$CALDERA_CHECK" ["splunk"]="$SPLUNK_CHECK" ["fleet"]="$FLEET_CHECK")
|
||||
SERVICES=(["caldera"]="$CALDERA_CHECK" ["splunk"]="$SPLUNK_CHECK" ["fleet"]="$FLEET_CHECK" ["ms_ata"]="$ATA_CHECK")
|
||||
for SERVICE in "${!SERVICES[@]}"; do
|
||||
if [ "${SERVICES[$SERVICE]}" -lt 1 ]; then
|
||||
(echo >&2 "Warning: $SERVICE failed post-build tests and may not be functioning correctly.")
|
||||
@@ -274,6 +276,9 @@ post_build_checks() {
|
||||
if [ "$FLEET_CHECK" -lt 1 ]; then
|
||||
(echo >&2 "Warning: Fleet failed post-build tests and may not be functioning correctly.")
|
||||
fi
|
||||
if [ "$ATA_CHECK" -lt 1 ]; then
|
||||
(echo >&2 "Warning: MS ATA failed post-build tests and may not be functioning correctly.")
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user