Building a Purple Teaming Test Environment with Ludus

Building a Purple Teaming Test Environment with Ludus

Introduction

In my previous post, I demonstrated how to install Ludus on Debian 12.

Automate your Cyber Security Lab with Ludus
Ludus is a free and open source project saving you all the hours you usually needed to setup your lab!

In this blog post, I want to go beyond the initial setup and show you how I automated my Home Lab using Ludus.

How Ludus builds Environments

Before we can start building, we need to understand some concepts first, which will not only help us in this project, but also in upcoming ones.

Ludus - Ranges

Ranges are environments configured in a single YAML file and then deployed. After the deployment has started, you can watch Ludus create Virtual Machines in Proxmox.

You can find everything you need to know in the Ludus Documentation:

🗒️ Configuration | Ludus
The Ludus range configuration file is a yaml document that describes the virtual machines and optionally the network rules, router settings, and defaults a user would like to deploy.
  1. Create a configuration file and save it
  2. Load the file using:
ludus range config set -f </path/to/file.yml>
  1. Deploy the loaded Range using:
ludus range deploy
  1. Check the progress by tailing the logs:
ludus range logs -f
  1. Check if the deployment was successful using:
ludus range status
  1. If you're done and wish to setup another range, delete your current range using:
ludus range destroy

After the deletion, you can create a new config.yml file (or use an already existing one) and deploy the next range.

This makes all of my testing environments copy-pastable text!

Ludus - Roles

While deploying a virtual environment with the press of a button sounds amazing enough, you can even assign roles to the hosts.

Roles are Ansible roles that are applied to VMs in Ludus after they are deployed and configured. While you can create your own, there are already some to choose from.

🎭 Roles | Ludus
How to use Roles

You can literally tell a host to play the role of a MSSQL Server, Elastic Server, Wazuh Server and much more!

💡
Note: At the time of this writing, assigning the Elastic Agent role to a Windows Server did not work for me. But I will show you a workaround later in this post!

Building the Dream Lab

What we need to do:

  1. Create a Configuration File for our desired Environment
  2. Deploy the Range
  3. Verify that the Deployment completed successfully
  4. Access Kibana and onboard the Windows Server
  5. Setup our VPN to access the hosts/Kibana

The Lab I'm setting up today looks as follows:

  • Router (automatically configured)
  • Windows Server 2022 as Domain Controller
  • Windows 11 Workstation
  • Debian 12 server as Elastic Server

You can also go ahead and add a Kali Linux host to the mix, but since my server runs on 32 GB RAM (non-upgradable), I will use a separate VM running on my laptop.

1 - Adding the necessary Roles

Before we start building our Yaml-File, we need to add the desired Ansible roles. Enter the two commands to prepare the elastic server and agent roles [1]:

ludus ansible roles add badsectorlabs.ludus_elastic_container
ludus ansible roles add badsectorlabs.ludus_elastic_agent

In Case you also would like to play around with Wazuh in the future, also install these:

ludus ansible roles add aleemladha.wazuh_server_install
ludus ansible roles add aleemladha.ludus_wazuh_agent

Big thanks to Aleemladha who created these amazing roles!

GitHub - aleemladha/wazuh_server_install: Installing wazuh SIEM Unified XDR and SIEM protection
Installing wazuh SIEM Unified XDR and SIEM protection - aleemladha/wazuh_server_install
GitHub - aleemladha/ludus_wazuh_agent: Installing wazuh agents Unified XDR and SIEM protection on Ludus Ranges
Installing wazuh agents Unified XDR and SIEM protection on Ludus Ranges - aleemladha/ludus_wazuh_agent

2 - Creating a Configuration File

Now it is time to construct the building plan of our lab. Refer to the Ludus documentation if you wish to create your own. In this blog post, I will showcase the one I created.

Having read enough about the documentation, I was ready to build my own configuration file:


  - vm_name: "{{ range_id }}-elastic"
    hostname: "{{ range_id }}-elastic"
    template: debian-12-x64-server-template
    vlan: 10
    ip_last_octet: 2
    ram_gb: 8
    cpus: 4
    linux: true
    testing:
      snapshot: false
      block_internet: false
    roles:
      - badsectorlabs.ludus_elastic_container
    role_vars:
      ludus_elastic_password: "elastic123"

  - vm_name: "{{ range_id }}-dc01"
    hostname: "{{ range_id }}-dc01"
    template: win2022-server-x64-template
    vlan: 10
    ip_last_octet: 12
    ram_gb: 8
    cpus: 4
    windows:
      sysprep: false
    domain:
      fqdn: minder-security.local
      role: primary-dc

  - vm_name: "{{ range_id }}-ws01"
    hostname: "{{ range_id }}-ws01"
    template: win11-22h2-x64-enterprise-template
    vlan: 10
    ip_last_octet: 22
    ram_gb: 8
    cpus: 8
    windows:
      sysprep: true
      install_additional_tools: true
      visual_studio_version: 2019
    domain:
      fqdn: minder-security.local
      role: member
    roles:
      - badsectorlabs.ludus_elastic_agent


defaults:
  router_vm_name: "{{ range_id }}-router-debian11-x64"
  snapshot_with_RAM: false
  stale_hours: 0
  ad_domain_functional_level: Win2012R2
  ad_forest_functional_level: Win2012R2
  ad_domain_admin: domainadmin
  ad_domain_admin_password: password123
  ad_domain_user: domainuser
  ad_domain_user_password: password
  ad_domain_safe_mode_password: safepassword
  timezone: Europe/Zurich

3 - Deploying the Range

The steps are explained in How Ludus builds Environments. You can just follow along:

  1. Set the configuration
ludus range config set -f config.yml
  1. Deploy the Range:
ludus range deploy
  1. Track the Progress:
ludus range logs -f

This process will take a while. In the meantime, you can relax, grab a coffee, and spend some time with your loved ones.

After it's done, you should be able to see something like this:

4 - Verifying the Deployment

The default credentials are documented by Ludus [2]. We will need the following:

  • Windows
    • localuser:password (local Administrator)
    • LUDUS\domainuser:password
    • LUDUS\domainadmin:password (Domain Admin)
  • Others
    • localuser:password

The Windows 11 Workstation was properly set up and runs bginfo which shows, that the domain join was successful. I authenticated using domainuser, but you can also just use localuser if you wish:

As you can see, due to install_additional_tools: true, we now have a Windows 11 Host fully equipped with Firefox, Chrome, VSCode, Burp Suite, 7Zip, Process Hacker, Ilspy and other useful utilities.

The Windows Server 2022 (Domain Controller) also seemed to have been set up correctly:

I quickly checked if the domain was configured as intended, and it seems to have worked perfectly!

💡
The Background Color of the machines change color depending on testing mode being enabled or not.

As you might want to analyze malware in such an environment, a red background tells you that testing mode is disabled.

As soon as testing mode is enabled, the background will turn green.
Testing mode | Ludus
Ludus is more than a simple infrastructure deployment tool - it allows users to test tools and techniques safely without allowing potentially unwanted outbound network communications.

5 - Installing Elastic Agent on the Domain Controller

Since the automated installation of the Elastic Agent was not possible in my case, I installed it manually:

  1. Open Edge on the Domain Controller/Windows Server
  2. Access Kibana using the web: https://<IP_OF_ELASTIC_SERVER>:5601/, click on "Advanced" and "Continue to <IP>"
  1. Authenticate with the credentials you configured in config.yml, or whatever you named your configuration file
  2. On the left menu, scroll down and go to Management > Fleet
  1. Confirm that the Windows 11 Host is onboarded:
  1. Then click on Add agent
  2. Select Endpoint Policy
  3. Check Enroll in Fleet
  4. Then copy the PowerShell code provided
  1. Paste the contents line by line into PowerShell
  2. Add --insecure at the end of the line executing the installation binary to avoid running into an error caused by the certificate being untrusted:
  1. Now, you should see that our DC has successfully been onboarded!

6 - Setting up the VPN Connection

If you wish to connect to the environment from outside, you need to install and configure WireGuard. I chose the GUI version:

  1. Download and install the WireGuard GUI on your local machine from which you wish to interact with the testing environment:
Installation - WireGuard
  1. Display your configuration by using the command line below on your Ludus server (Replace <ID> with your user-id. In my case it was XA):
ludus user wireguard --user <ID> --url https://127.0.0.1:8081
  1. Create a file on your local machine and post the output from above:
  1. Import the file to WireGuard:
  1. Activate the Connection

Now you can connect to Kibana from your local Host!

Now that everything has been set up and you're connected to the VPN, you can connect to your VMs. Kibana is available through the Port 5601, so let's connect:

https://10.2.10.2:5601

The default credentials configured in the config file should be elastic and you can get the password from your configuration file.

8 - Next Steps

Now that Elastic is configured (and dark mode is turned on), I can start testing and investigating.

Since I am currently taking a course on Maldev Academy and preparing for the HTB CPTS, I plan to write my own malware on the Windows 11 workstation, run it, perform malicious Active Directory actions (AS-REP-Roasting, Kerberoasting, etc.) using an external host, and then analyze the logs. For this, I need to first deploy Sysmon, then find a suitable HIDS solution (thinking about Wazuh) and deploy Velociraptor. If I'm not getting fascinated by another topic in the meantime, I might do a blog post about it!

Thank you so much for reading my post and I hope I could showcase some of Ludus' capabilities!

Sources

[1] https://docs.ludus.cloud/docs/environment-guides/elastic

[2] https://docs.ludus.cloud/docs/quick-start/deploy-range