Skip to content

Commit

Permalink
Merge pull request #6 from fkie-cad/dev-add-config-scenarios
Browse files Browse the repository at this point in the history
Move Bounty Hunter config from planner YAML to scenario configs
  • Loading branch information
L015H4CK authored Oct 21, 2024
2 parents 6f5eb54 + 2984517 commit 0254a54
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 79 deletions.
35 changes: 18 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ This example of how to use these parameters is described in more detail in the s
The following sections are structured as follows:
First, a short installation guide is given.
Then, two examples are introduced that show how the Bounty Hunter can be used and what it is capable of.
The first example demonstrates the Bounty Hunter's initial access and privilege escalation capabilities and can be used as a guide on how to use it
The first example demonstrates the Bounty Hunter's initial access and privilege escalation capabilities and can be used as a guide on how to use it.
The second example shows the high level of complexity of cyberattacks the Bounty Hunter can emulate.
Finally, a more detailed description of how the Bounty Hunter works, how it can be configured, and how it could be extended is given.

Expand All @@ -52,8 +52,10 @@ In the second section an example attack based on an APT29 campaign is presented
The following section describes how to emulate a complete, realistic cyberattack chain using the Bounty Hunter and can be used as a guide for getting started with it.
To run an operation, start the Caldera server as usual.
As starting point, the Bounty Hunter uses a local Caldera agent, i.e., an agent that is running on a system initially controlled by the adversary.
Since some initial access abilities, e.g., the Nmap Port Scan (`8fcd3afb-75ca-40da-8bff-432abfb00fbb`), need root privileges, start the local agent with root/sudo.
The `Bounty Hunter Windows Initial Access and Privilege Escalation Tester` adversary and the Bounty Hunter's default configuration (`data/planners/e1bb9388-1845-495d-b67b-ad61a31ff6cd.yml`) were constructed to demonstrate the initial access and privilege escalation capabilities against a Windows or Linux target.
Since some initial access abilities, e.g., the Nmap Port Scan (`8fcd3afb-75ca-40da-8bff-432abfb00fbb`), need root privileges, start the local agent with root/sudo.
To run this scenario, set the scenario in the Bounty Hunter's configuration (`data/planners/e1bb9388-1845-495d-b67b-ad61a31ff6cd.yml`) to `demo_initial_access_and_priv_esc` .
The `Bounty Hunter Windows Initial Access and Privilege Escalation Tester` adversary profile was constructed to demonstrate the initial access and privilege escalation capabilities against a Windows or Linux target.
Alternatively, the `Bounty Hunter - Demo Adversary Profile` can be used as well - which includes all demo abilities for the Bounty Hunter and can be used to demonstrate the various behaviors controlled by the scenario configurations.

Before running the operation, some configurations have to be done:
1. Configure fact `bountyhunter.ip_range`: Using the Caldera UI, configure the IP address range the bounty hunter should scan initially.
Expand Down Expand Up @@ -109,9 +111,9 @@ The following section go into more detail about how the Bounty Hunter works, how
## Bounty Hunter Configuration

The Bounty Hunter can be configured in many ways to further customize the emulated attack behavior.
The configuration can be viewed and edited in `bountyhunter/data/planners/e1bb9388-1845-495d-b67b-ad61a31ff6cd.yml`.
Furthermore, the configuration is displayed in the Bounty Hunter's user interface tab (`plugins -> bountyhunter`).
The configuration can also (partially) be edited using the user interface after pulling [this Caldera branch](https://github.com/L015H4CK/caldera/tree/feature-api-update-planner), which allows updating existing planners using Caldera's API.
Its parameters can be configured using scenario configuration files (`bountyhunter/conf/<scenario_name>/scenario_params.yml`).
The `default` scenario shows all the possible configuration parameters with example values.
Which scenario the Bounty Hunter should use can be configured in its configuration file (`bountyhunter/data/planners/e1bb9388-1845-495d-b67b-ad61a31ff6cd.yml`).

The following table lists the various parameters used by the Bounty Hunter including a short description and the default values.

Expand Down Expand Up @@ -139,8 +141,8 @@ How far, i.e., how many abilities ahead, the Bounty Hunter uses ability rewards
## Locked Abilities and Manual Reward Updates

Locking abilities and performing manual reward updates enables the Bounty Hunter to perform more realistic, more sophisticated and customized attacks.
Consider the example adversary `Bounty Hunter - Locked Abilities Demonstrator` with the following abilities: `Find files`, `Stage sensitive files`, `Create staging directory`, `Compress staged directory`, and `Exfil staged directory`.
Also, the ability `Exfil staged directory` has a high reward value, e.g., `1000`.
Consider the scenario `demo_locked_abilities` and the example adversary `Bounty Hunter - Locked Abilities Demonstrator` with the following abilities: `Find files`, `Stage sensitive files`, `Create staging directory`, `Compress staged directory`, and `Exfil staged directory`.
The ability `Exfil staged directory` has a high reward value, e.g., `1000`.
When using Caldera's Look-Ahead Planner, the agent will execute the following attack chain:
- Create staging directory
- Compress staged directory
Expand All @@ -154,14 +156,13 @@ Now, the Bounty Hunter can be configured to "lock" the `Compress staged director
This means, it will only compress the staged directory after files have been staged. See example configuration below.

```
params:
final_abilities:
- ea713bc4-63f0-491c-9a6f-0b01d560b87e # exfiltrate staged directory
locked_abilities:
- 300157e5-f4ad-4569-b533-9d1fa0e74d74 # compress staged directory
reward_updates:
4e97e699-93d7-4040-b5a3-2e906a58199e: # stage sensitive files
300157e5-f4ad-4569-b533-9d1fa0e74d74: 1 # compress staged directory
final_abilities:
- ea713bc4-63f0-491c-9a6f-0b01d560b87e # exfiltrate staged directory
locked_abilities:
- 300157e5-f4ad-4569-b533-9d1fa0e74d74 # compress staged directory
reward_updates:
4e97e699-93d7-4040-b5a3-2e906a58199e: # stage sensitive files
300157e5-f4ad-4569-b533-9d1fa0e74d74: 1 # compress staged directory
```

Now, when running an operation using the Bounty Hunter and the above configuration, the following attack chain is generated and executed:
Expand Down Expand Up @@ -226,4 +227,4 @@ We welcome any contributions, questions and ideas.
If you have any questions or want to contact us, feel free to open an issue or a pull request.

# License
Released under Apache-2.0 license. For more information see LICENSE.
Released under Apache-2.0 license. For more information see LICENSE.
62 changes: 27 additions & 35 deletions app/planners/bounty_hunter.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from numpy.random import choice, seed
from yaml import safe_load

from plugins.bountyhunter.app.helper.agenda_helper import AgendaHelper

Expand Down Expand Up @@ -27,28 +28,13 @@ class LogicalPlanner:
DISCOUNT = 0.9
SEED = None

def __init__(self, operation, planning_svc, stopping_conditions=(),
depth=DEPTH, discount=DISCOUNT,
default_reward=DEFAULT_REWARD,
default_final_reward=DEFAULT_FINAL_REWARD,
default_reward_update=DEFAULT_REWARD_UPDATE,
final_abilities=None, ability_rewards=None, locked_abilities=None, reward_updates=None,
seed=SEED, weighted_random=False
):
def __init__(self, operation, planning_svc, scenario, stopping_conditions=()):
"""
:param operation:
:param planning_svc:
:param scenario: Name of the scenario in bountyhunter/conf to be used
:param stopping_conditions:
:param depth: recursive depth of future reward function
:param discount: discount factor of future abilities
:param default_reward: default reward value for all abilities
:param default_final_reward: default reward value for all final abilities
:param default_reward_update: default reward update value for all abilities
:param final_abilities: list of final ability IDs
:param ability_rewards: list of ability IDs with corresponding reward value
:param locked_abilities: list of ability IDs of abilities that are locked by default
:param reward_updates: list of custom reward update values per ability
"""

self.operation = operation
Expand All @@ -67,25 +53,13 @@ def __init__(self, operation, planning_svc, stopping_conditions=(),
"execute_elevated"
]

self.depth = depth
self.discount = discount

self.default_reward = default_reward
self.default_final_reward = default_final_reward
self.default_reward_update = default_reward_update

self.final_abilities = final_abilities or {}
self.initial_ability_rewards = ability_rewards or {}
self.ability_rewards = None
self.initial_locked_abilities = locked_abilities or {}
self.locked_abilities = None
self.reward_updates = reward_updates or {}
self.scenario = scenario
self._init_parameters()

self.agent_waiting_for_elevation = None
self.host_waiting_for_elevation = None
self.ability_waiting_for_elevation = None

self.seed = seed
self.start_agent = None

self.agenda_helper = AgendaHelper()
Expand All @@ -94,10 +68,29 @@ def __init__(self, operation, planning_svc, stopping_conditions=(),

self.after_sleep_bucket = None

self.weighted_random = weighted_random

self.planning_svc.log.info("<BountyHunter> Seed: {}".format(self.seed))

def _init_parameters(self):
with open("plugins/bountyhunter/conf/" + self.scenario + "/scenario_params.yml") as f:
scenario_config = safe_load(f)

self.depth = scenario_config.get("depth", self.DEPTH)
self.discount = scenario_config.get("discount", self.DISCOUNT)

self.default_reward = scenario_config.get("default_reward", self.DEFAULT_REWARD)
self.default_final_reward = scenario_config.get("default_final_reward", self.DEFAULT_FINAL_REWARD)
self.default_reward_update = scenario_config.get("default_reward_update", self.DEFAULT_REWARD_UPDATE)

self.final_abilities = scenario_config.get("final_abilities", {})
self.initial_ability_rewards = scenario_config.get("ability_rewards", {})
self.ability_rewards = None
self.initial_locked_abilities = scenario_config.get("locked_abilities", {})
self.locked_abilities = None
self.reward_updates = scenario_config.get("reward_updates", {})

self.weighted_random = scenario_config.get("weighted_random", False)
self.seed = scenario_config.get("seed", self.SEED)

async def execute(self):
self.ability_rewards = self.initial_ability_rewards.copy()
self.locked_abilities = self.initial_locked_abilities.copy()
Expand Down Expand Up @@ -396,7 +389,7 @@ async def _pick_next_ability_link(self, agent, executable_links):
ability_reward_tuples.sort(key=lambda t: t[1], reverse=True)

for art in ability_reward_tuples:
self.planning_svc.log.debug("<BountyHunter> Shuffled/Sorted Ability Rewards: {}".format(art))
self.planning_svc.log.info("<BountyHunter> Shuffled/Sorted Ability Rewards: {}".format(art))

for ability_reward_tuple in ability_reward_tuples:
for link in executable_links:
Expand Down Expand Up @@ -439,7 +432,6 @@ async def _get_ability_rewards(self, agent, abilities):
for ability in abilities:
if ability.ability_id not in self.locked_abilities:
ability_rewards.append((ability.ability_id, await self._future_reward(agent, ability, abilities, 0), ))
# ability_rewards[ability.ability_id] = await self._future_reward(agent, ability, abilities, 0)

return ability_rewards

Expand Down
23 changes: 23 additions & 0 deletions conf/default/scenario_params.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Default scenario
description: Default scenario configuration showing all possible parameters.
seed: 4711
weighted_random: True
depth: 3
discount: 0.9
default_final_reward: 1000
default_reward: 1
default_reward_update: 200
final_abilities:
- ea713bc4-63f0-491c-9a6f-0b01d560b87e # exfiltrate staged directory
ability_rewards:
4e97e699-93d7-4040-b5a3-2e906a58199e: 1000 # stage sensitive files
locked_abilities:
- 300157e5-f4ad-4569-b533-9d1fa0e74d74 # compress staged directory
reward_updates:
6469befa-748a-4b9c-a96d-f191fde47d89: # create staging directory
4e97e699-93d7-4040-b5a3-2e906a58199e: 10000 # stage sensitive files
4e97e699-93d7-4040-b5a3-2e906a58199e: # stage sensitive files
300157e5-f4ad-4569-b533-9d1fa0e74d74: 1 # compress staged directory
300157e5-f4ad-4569-b533-9d1fa0e74d74: # compress staged directory
4e97e699-93d7-4040-b5a3-2e906a58199e: -10000 # stage sensitive files
90c2efaa-8205-480d-8bb6-61d90dbaf81b: -10000 # find files
4 changes: 4 additions & 0 deletions conf/demo_initial_access/scenario_params.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name: Initial Access Demo Scenario
description: Use with adversary profile "Bounty Hunter - Demo Adversary Profile" or "Bounty Hunter - Initial Access Tester" and elevated agent running on host machine.
final_abilities:
- bd527b63-9f9e-46e0-9816-b8434d2b8989 # Current User
5 changes: 5 additions & 0 deletions conf/demo_initial_access_and_priv_esc/scenario_params.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: Initial Access and Privilege Escalation Demo Scenario
description: Use with adversary profile "Bounty Hunter - Demo Adversary Profile" or "Bounty Hunter - Initial Access and Privilege Escalation Tester" and elevated agent running on host machine.
final_abilities:
- 8320facd-6bc9-4850-8ecb-02a18064aa91 # Dump /etc/shadow
- a440211a-d2cc-4f89-a02d-a39061a0e697 # Credential Dumping via wmidump (mimikatz)
14 changes: 14 additions & 0 deletions conf/demo_locked_abilities/scenario_params.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Locked Ability Demo Scenario
description: Use with adversary profile "Bounty Hunter - Demo Adversary Profile" or "Bounty Hunter - Locked Abilities Demonstrator" and an agent running on the target machine in group "target".
final_abilities:
- ea713bc4-63f0-491c-9a6f-0b01d560b87e # exfiltrate staged directory
locked_abilities:
- 300157e5-f4ad-4569-b533-9d1fa0e74d74 # compress staged directory
reward_updates:
6469befa-748a-4b9c-a96d-f191fde47d89: # create staging directory
4e97e699-93d7-4040-b5a3-2e906a58199e: 1000 # stage sensitive files
4e97e699-93d7-4040-b5a3-2e906a58199e: # stage sensitive files
300157e5-f4ad-4569-b533-9d1fa0e74d74: 1 # compress staged directory
300157e5-f4ad-4569-b533-9d1fa0e74d74: # compress staged directory
4e97e699-93d7-4040-b5a3-2e906a58199e: -10000 # stage sensitive files
90c2efaa-8205-480d-8bb6-61d90dbaf81b: -10000 # find files
10 changes: 2 additions & 8 deletions data/adversaries/0b73bf34-fc5b-48f7-9194-dce993b915b1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,8 @@ id: 0b73bf34-fc5b-48f7-9194-dce993b915b1
name: Bounty Hunter - Initial Access Tester
description: |
Adversary Profile for Bounty Hunter initial access testing against Windows and Linux Targets.
Finds and exfiltrates sensitive files after successful initial access.
Find current user name after successful initial access.
atomic_ordering:
- 9c109820-6c4d-4378-9a82-00a75323bfda # Nmap host scan
- 8fcd3afb-75ca-40da-8bff-432abfb00fbb # Nmap port scan
- 720a3356-eee1-4015-9135-0fc08f7eb2d5 # Find git repositories
- 2f90d4de-2612-4468-9251-b220e3727452 # compress git repository
- 6469befa-748a-4b9c-a96d-f191fde47d89 # Create staging directory
- 4e97e699-93d7-4040-b5a3-2e906a58199e # stage sensitive files
- 90c2efaa-8205-480d-8bb6-61d90dbaf81b # find files
- 300157e5-f4ad-4569-b533-9d1fa0e74d74 # compress staged directory
- ea713bc4-63f0-491c-9a6f-0b01d560b87e # exfil staged directory
- bd527b63-9f9e-46e0-9816-b8434d2b8989 # Current User
23 changes: 23 additions & 0 deletions data/adversaries/bc784d7e-6761-4472-9050-ce0ab6c0bf3c.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---

id: bc784d7e-6761-4472-9050-ce0ab6c0bf3c
name: Bounty Hunter - Demo Adversary Profile
description: |
Adversary Profile for Bounty Hunter Demo scenarios.
Depending on the selected scenario in the planner's config, the resulting behavior should be either:
(1) Perform initial access and collect current user name
(2) Perform initial access, privilege escalation and execute ability that needs elevated privileges
(3) Find, stage and exfiltrate sensitive files to demonstrate locked abilities
atomic_ordering:
- 9c109820-6c4d-4378-9a82-00a75323bfda # Nmap host scan (Scenario 1+2)
- 8fcd3afb-75ca-40da-8bff-432abfb00fbb # Nmap port scan (Scenario 1+2)
- bd527b63-9f9e-46e0-9816-b8434d2b8989 # Current User (Scenario 1)
- ce6628bc-c1e2-456b-91e7-da5b8bcd4005 # Abuse bash can be executed with sudo privileges (Scenario 2)
- 0220b3e7-9ba0-4529-abb4-52a70dc49b50 # UAC Bypass via sdctl (Scenario 2)
- a440211a-d2cc-4f89-a02d-a39061a0e697 # Dumping credentials via wmidump (Mimikatz) (Scenario 2)
- 8320facd-6bc9-4850-8ecb-02a18064aa91 # Dump /etc/shadow (Scenario 2)
- 90c2efaa-8205-480d-8bb6-61d90dbaf81b # Find Files (Scenario 3)
- 4e97e699-93d7-4040-b5a3-2e906a58199e # Stage sensitive files (Scenario 3)
- ea713bc4-63f0-491c-9a6f-0b01d560b87e # Exfil staged directory (Scenario 3)
- 6469befa-748a-4b9c-a96d-f191fde47d89 # Create staging directory (Scenario 3)
- 300157e5-f4ad-4569-b533-9d1fa0e74d74 # Compress staged directory (Scenario 3)
20 changes: 1 addition & 19 deletions data/planners/e1bb9388-1845-495d-b67b-ad61a31ff6cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,4 @@ description: |
module: plugins.bountyhunter.app.planners.bounty_hunter
ignore_enforcement_modules: []
params:
#seed: 42123
#weighted_random: False
#depth: 3
#discount: 0.9
#default_final_reward: 1000
#default_reward_update: 500
final_abilities:
- 8320facd-6bc9-4850-8ecb-02a18064aa91 # Dump /etc/shadow
- a440211a-d2cc-4f89-a02d-a39061a0e697 # Credential Dumping via wmidump (mimikatz)
#- ea713bc4-63f0-491c-9a6f-0b01d560b87e # exfiltrate staged directory
#ability_rewards:
# 4e97e699-93d7-4040-b5a3-2e906a58199e: 1000 # stage sensitive files
#locked_abilities:
# - 300157e5-f4ad-4569-b533-9d1fa0e74d74 # compress staged directory
#reward_updates:
#6469befa-748a-4b9c-a96d-f191fde47d89: # create staging directory
#4e97e699-93d7-4040-b5a3-2e906a58199e: 10000 # stage sensitive files
#4e97e699-93d7-4040-b5a3-2e906a58199e: # stage sensitive files
#300157e5-f4ad-4569-b533-9d1fa0e74d74: 1 # compress staged directory
scenario: default

0 comments on commit 0254a54

Please sign in to comment.