Sitemap

Wazuh setup, DNS Forwarders, and adding SNs to AD

9 min read2 days ago

--

Press enter or click to view image in full size

Background

This is one of those housekeeping lab projects that isn’t so much about a new big thing like PowerShell Transcript Logging as it is about a bunch of little things:

  • Installing an actual SIEM in the lab and not just a WEC or forwarding everything to Sentinel.
  • Setting DNS Forwarding up properly on the DCs so I don’t have to add 8.8.8.8 to VM’s DNS servers.
  • Adding a feature to AD that Microsoft should have; putting Make, Model, and SN into computer accounts

Wazuh

I already had Ubuntu Server 24.04 downloaded for another project so I just ran with it for hosting Wazuh. I’m running it in the ESXi I used for these projects for now. Eventually I’ll get a third refurbished server to run something like Proxmox and figure out how to migrate VMs from VMware to it.

Installing Ubuntu was straightforward and really quick. Once it’s up and running you’ll want to set a static IP.

#Find the current IP and NIC name
ip a

#Edit the config file to specify IP, subnet, GW, subnet, & DNS servers
sudo nano /etc/netplan/00-installer-config.yaml
- - file contents - -
network:
version: 2
renderer: networkd
ethernets:
ens160:
dhcp4: false
dhcp6: false
match:
macaddress: 00:0c:29:fb:47:35
set-name: ens160
addresses:
- 192.168.0.116/24
routes:
- to: default
via: 192.168.0.1
nameservers:
addresses:
- 192.168.0.101
- 192.168.0.102
- 192.168.0.103
- 192.168.0.104
- - /contents - -

Please note that the tabbing is this file is apparently crucial. Medium doesn’t do a great job of showing tab indents in code blocks so I’ll just show a screenshot of how mine looked.

#Apply the config
sudo netplan try
sudo netplan apply

I then simply SSHed into the VM, downloaded, and installed Wazuh.

sudo apt update && sudo apt upgrade -y

#I had to use -i even though the VM has 2 CPUs and 4 GB RAM
curl -sO https://packages.wazuh.com/4.11/wazuh-install.sh && sudo bash ./wazuh-install.sh -a -i

Make sure you note the admin password that Wazuh shows at the end of the installation.

Agent Installation

Obviously if I was doing this on multiple systems I’d write a startup PS1 and push it via a GPO. However since for now I’m just pulling the events that are already on the home lab’s WEC server I simply did:

Enter-PsSession TestWECII
Invoke-WebRequest -Uri https://packages.wazuh.com/4.x/windows/wazuh-agent-4.11.0-1.msi -OutFile "$env:TEMP\wazuh-agent.msi"
msiexec.exe /i "$env:TEMP\wazuh-agent.msi" /q WAZUH_MANAGER='192.168.0.116' WAZUH_REGISTRATION_SERVER='192.168.0.116'
Start-Service -Name "Wazuh"

I then simply used the Run command to open and edit the Wazuh Agent’s config file.

\\TestWECII\C$\Program Files (x86)\ossec-agent

#Edit ossec.conf to add
<localfile>
<location>ForwardedEvents</location>
<log_format>eventchannel</log_format>
</localfile>

I included a screenshot showing where I added that snippet to the config file. This update to the config is because the agent doesn’t pull the Forwarded Events by default.

Press enter or click to view image in full size

Once all that’s done we see the system in Wazuh, stats, and events from it.

Press enter or click to view image in full size

DNS Forwarders

This is admittedly something I should have done a long, long time ago.

$ADRoot = (Get-ADDomain).DistinguishedName
$DCs = (Get-ADComputer -Filter * -SearchBase "ou=domain controllers,$ADRoot").Name
ForEach($DC in $DCs)
{
Invoke-Command $DC {Set-DnsServerForwarder -IPAddress "8.8.8.8", "8.8.4.4" -PassThru}
}

#Verify
ForEach($DC in $DCs)
{
$DC
Invoke-Command $DC {(Get-DnsServerForwarder).IPAddress.IPAddressToString}
}

This sets the lab’s DCs to forward requests they don’t have a record for, aka anything on the Internet, to Google’s DNS servers.

Adding Computer Make, Model, & SN to AD

IMHO this is something Microsoft really should have included in AD ‘out of the box’ back in 2000. A prior OIC who’s really smart and more creative than I am came up with the idea of adding 3 custom attributes to the Schema to store the Make, Model, and Service Tag of computer accounts. I merely borrowed his idea and worked out two different ways to implement it in the home lab. I also used the Description attribute rather than modifying the Schema.

The first method, which is similar to what he did, is to run a ForEach loop as a Domain Admin to query the systems, pull the info, and update their AD account Description.

Get Rich’s stories in your inbox

Join Medium for free to get updates from this writer.

I ran it against the Hypervisor OU as this OU contains the only physical systems with real SNs in my home lab. Additionally my ESXi system is in that OU so I used it as a learning oppotunity to work on some error handling since Get-CimInstance obviously can’t query a Linux based system.

$ADRoot = (Get-ADDomain).DistinguishedName
$Hypervisors = Get-ADComputer -Filter * -SearchBase "ou=hypervisors,$ADRoot" -Properties *

ForEach($Hypervisor in $Hypervisors)
{
#Make sure you're not carrying info from the prior system
$Computer = $null
$UEFI = $null
$Make = "N/A"
$Model = "N/A"
$Serial = "N/A"

if($Hypervisor.Name -eq $env:COMPUTERNAME)
{
$Computer = Get-CimInstance -ClassName Win32_ComputerSystem
$UEFI = Get-CimInstance -ClassName Win32_BIOS
}

else
{
$Session = New-CimSession -ComputerName $Hypervisor.DNSHostName -ErrorAction SilentlyContinue
if($Session)
{
$Computer = Get-CimInstance -ClassName Win32_ComputerSystem -CimSession $session
$UEFI = Get-CimInstance -ClassName Win32_BIOS -CimSession $session
Remove-CimSession -CimSession $session
}
}

$Make = $Computer.Manufacturer
$Model = $Computer.Model
$Serial = $UEFI.SerialNumber

if($Make -eq $null)
{Write-Host "System is running Linux or is off"}
Else{Write-Host "$($Hypervisor.Name) is a $Make $Model with SN $Serial"}
if($Hypervisor.Description -like "*$Serial*")
{Write-Host "Description already set, skipping"}
else{
$HW = "$Make $Model SN: $Serial"
$NewDescription = "$($Hypervisor.Description) - $HW"
Set-ADComputer -Identity $Hypervisor.DistinguishedName -Replace @{description = "$NewDescription"}
}
}
Press enter or click to view image in full size

This works, but it has a bit of an issue; the system has to be on and reachable at the time the function is run.

Alternate TTP, Startup PS1

I tested out an alternate method on the Clients OU, which in my lab contains the very few Windows 10/11 VMs I run. Since this version is only run against the local system it’s a lot simpler. The idea here is that as users turn on and boot up their computers the computer will update it’s own Description with the info.

#This is meant to be run as a startup PS1 on laptops in the Client OU
#The downside of this TTP is that it only works if each laptop has the PowerShell AD Module
Import-Module ActiveDirectory
$ADRoot = (Get-ADDomain).DistinguishedName

$Hypervisor = Get-ADComputer $env:COMPUTERNAME
#Make sure you're not carrying info from the prior system
$Computer = $null
$UEFI = $null
$Make = "N/A"
$Model = "N/A"
$Serial = "N/A"

$Computer = Get-CimInstance -ClassName Win32_ComputerSystem
$UEFI = Get-CimInstance -ClassName Win32_BIOS
$Make = $Computer.Manufacturer
$Model = $Computer.Model
$Serial = $UEFI.SerialNumber

if($Make -eq $null)
{Write-Host "System is running Linux or is off"}
Else{Write-Host "$($Hypervisor.Name) is a $Make $Model with SN $Serial"}
if($Hypervisor.Description -like "*$Serial*")
{Write-Host "Description already set, skipping"}
else{
$HW = "$Make $Model SN: $Serial"
$NewDescription = "$($Hypervisor.Description) - $HW"
Set-ADComputer -Identity $Hypervisor.DistinguishedName -Replace @{description = "$NewDescription"}
}
Press enter or click to view image in full size

However for this TTP to work bear two things in mind:

  • The system has to have the PowerShell AD Module installed.
  • You have to have delegated rights in AD for the computer accounts to update their own Description attribute.

If you want to use this method and don’t want to load any modules then there’s ways to call .NET methods and get it done. Google and Gemini will let you know. Just make sure you read anything Gemini gives you and Google if you’re unsure. Gemini gave me bad info regarding some GUIDs.

Delegating computers rights

The easy way to give computer accounts in an OU the right to update their own Description is this:

Import-Module ActiveDirectory
Set-Location AD:
$ADRoot = (Get-ADDomain).DistinguishedName

#Give Computers the right to update their own description
$victim = (Get-ADOrganizationalUnit "ou=Clients,$ADRoot" -Properties *).DistinguishedName
$acl = Get-ACL $victim
$user = New-Object System.Security.Principal.SecurityIdentifier ("S-1–5–10")
#Allow specific WriteProperty on the Description attribute
$acl.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule $user,"WriteProperty","ALLOW",([GUID]("bf967950–0de6–11d0-a285–00aa003049e2")).guid,"Descendents",([GUID]("bf967a86–0de6–11d0-a285–00aa003049e2")).guid))
#Apply above ACL rules
Set-ACL $victim $acl

I got this template from my Dangerous Rights Cheatsheet. If you’re new to how DACLs look in PowerShell, querying them, tweaking them, etc then see our DACL Primer.

On a sidenote, Gemini gave me the wrong GUID for the Description attribute:

bf967a0e-0de6–11d0-a285–00aa003049e2

I Googled it up and found that this GUID was “the Relative Distinguished Name (RDN) of an object. An RDN is the relative portion of a distinguished name (DN), which uniquely identifies an LDAP object.” AKA it was the essentially the Name attribute in modern ADs. The RDN only applied to Windows Server 2000–2012.

Fixing an oopsie if you make one

I’ll admit it, I made quite the booboo while I was writing all this and testing it out in the lab. I copy/pasted the template I used from an example that delegated rights to the Helpdesk group over user accounts in an OU. Naturally I neglected to change the InheritedObjectType when I ran it.

Press enter or click to view image in full size
See the mistake I made here? It took me embarrassingly long to spot it.

I was then wondering why TestClient didn’t update it’s info following a ‘Invoke-GPUpdate ; Restart-Computer’. The answer of course was that I’d given computers in that OU the right to update their own Description on user accounts.

I took it as a learning experience and added the below snippet to my notes. This finds the wrong GUID and removes the ACE from the DACL.

Import-Module ActiveDirectory
Set-Location AD:
$ADRoot = (Get-ADDomain).DistinguishedName

#Find the misconfigured ACE that used the user GUID instead of computer GUID
(Get-Acl "ou=clients,$ADRoot").Access | Where-Object {($_.IdentityReference -like "*Self*") -and ($_.InheritedObjectType -eq "bf967aba-0de6–11d0-a285–00aa003049e2")}

#Remove the wrong ACE
$acl = Get-Acl "ou=clients,$ADRoot"
$OopsieAce = $acl.Access | Where-Object {($_.IdentityReference -like "*Self*") -and ($_.InheritedObjectType -eq "bf967aba-0de6–11d0-a285–00aa003049e2")}
$acl.RemoveAccessRule($OopsieAce)
Set-Acl -Path "ou=clients,$ADRoot" -AclObject $acl

Summary

A future project is to setup some alerts in Wazuh and then test them out by running some common attacker tools from Kali. That’s a future project though and something I might not even get to until after I’m running Wazuh in Proxmox on a third refurbished HP server. Right now it’s just running in ESXi and I don’t particularly like VMware or Broadcom.

This was a fun little lab project and a reminder of how granular and specific the rights you can give out in AD are. This project delegated accounts in a given OU the right to update the Description on their own account if that account is a computer account. They can’t update other computer’s accounts, just their own.

You would not want to give computers in an OU the rights to update or change all the attributes on all the computers in that OU. If you did then an attacker who has local admin on just one system in that OU could get local admin on all the computers in that OU via a rather obscure attack vector.

This is part of why I prefer using PowerShell vs the GUI. It’d be way too easy to click the wrong button in the GUI and give out more rights than you intended.

References

SIDs: https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers

SelfADSI: http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm

Dangerous Rights: https://happycamper84.medium.com/dangerous-rights-cheatsheet-33e002660c1d

DACL Primer: https://happycamper84.medium.com/dacl-primer-7ca758ae0aa8

RDN: https://learn.microsoft.com/en-us/windows/win32/adschema/a-name

--

--

Rich
Rich

Written by Rich

I work various IT jobs & like Windows domain security as a hobby. Most of what’s here is my notes from auditing or the lab.