Adding Caldera parameter handling

pull/3/head
Thorsten Sick 3 years ago
parent 04440bb1ab
commit ebd9854413

@ -134,6 +134,44 @@ class CalderaControl():
agents = self.__contact_server__(payload)
return agents
def list_sources(self):
""" List stored facts
"""
# TODO: Add filters for specific platforms/executors : , platform_filter=None, executor_filter=None as parameters
# curl -H 'KEY: ADMIN123' http://192.168.178.102:8888/api/rest -H 'Content-Type: application/json' -d '{"index":"agents"}'
payload = {"index": "sources"}
facts = self.__contact_server__(payload)
return facts
def list_sources_for_name(self, name):
""" List facts in a source pool with a specific name """
for i in self.list_sources():
if i["name"] == name:
return i
return None
def list_facts_for_name(self, name):
""" Pretty format for facts
@param name: Name of the source ot look into
"""
source = self.list_sources_for_name(name)
if source is None:
return {}
res = {}
for i in source["facts"]:
res[i["trait"]] = {"value": i["value"],
"technique_id": i["technique_id"],
"collected_by": i["collected_by"]
}
return res
def list_paws_of_running_agents(self):
""" Returns a list of all paws of running agents """
return [i["paw"] for i in self.list_agents()]
@ -185,6 +223,12 @@ class CalderaControl():
# ######### Get by id
def get_source(self, source_name):
payload = {"index": "sources",
"name": source_name}
return self.__contact_server__(payload)
def get_ability(self, abid):
"""" Return an ability by id
@ -290,7 +334,26 @@ class CalderaControl():
# ######### Add
def add_operation(self, name, advid, group="red", state="running", obfuscator="plain-text", jitter='4/8'):
def add_sources(self, name, parameters):
""" Adds a data source and seeds it with facts """
payload = {"index": "sources",
"name": name,
# "id": "123456-1234-1234-1234-12345678",
"rules": [],
"relationships": []
}
if parameters is not None:
facts = []
for k, v in parameters.items():
facts.append({"trait": k, "value": v})
payload["facts"] = facts
print(payload)
return self.__contact_server__(payload, method="put")
def add_operation(self, name, advid, group="red", state="running", obfuscator="plain-text", jitter='4/8', parameters=None):
""" Adds a new operation
@param name: Name of the operation
@ -299,10 +362,18 @@ class CalderaControl():
@param state: state to initially set
@param obfuscator: obfuscator to use for the attack
@param jitter: jitter to use for the attack
@param parameters: parameters to pass to the ability
"""
# Add operation: curl -X PUT -H "KEY:$KEY" http://127.0.0.1:8888/api/rest -d '{"index":"operations","name":"testoperation1"}'
# observed from GUI sniffing: PUT {'name': 'schnuffel2', 'group': 'red', 'adversary_id': '0f4c3c67-845e-49a0-927e-90ed33c044e0', 'state': 'running', 'planner': 'atomic', 'autonomous': '1', 'obfuscator': 'plain-text', 'auto_close': '1', 'jitter': '4/8', 'source': 'Alice Filters', 'visibility': '50'}
sources_name = "source_" + name
self.add_sources(sources_name, parameters)
print("Got:")
print(self.get_source("source_name"))
payload = {"index": "operations",
"name": name,
"state": state,
@ -310,7 +381,7 @@ class CalderaControl():
'obfuscator': obfuscator,
'auto_close': '1',
'jitter': jitter,
'source': 'Alice Filters',
'source': sources_name,
'visibility': '50',
"group": group,
#
@ -348,12 +419,13 @@ class CalderaControl():
# TODO View the abilities a given agent could execute. curl -H "key:$API_KEY" -X POST localhost:8888/plugin/access/abilities -d '{"paw":"$PAW"}'
def execute_ability(self, paw, ability_id, obfuscator="plain-text"):
def execute_ability(self, paw, ability_id, obfuscator="plain-text", parameters=None):
""" Executes an ability on a target. This happens outside of the scop of an operation. You will get no result of the ability back
@param paw: Paw of the target
@param ability_id: ability to execute
@param obfuscator: Obfuscator to use
@param parameters: parameters to pass to the ability
"""
# curl -H "key:ADMIN123" -X POST localhost:8888/plugin/access/exploit -d '{"paw":"$PAW","ability_id":"$ABILITY_ID"}'```
@ -362,6 +434,15 @@ class CalderaControl():
payload = {"paw": paw,
"ability_id": ability_id,
"obfuscator": obfuscator}
if parameters is not None:
facts = []
for k, v in parameters.items():
facts.append({"trait": k, "value": v})
payload["facts"] = facts
print(payload)
return self.__contact_server__(payload, rest_path="plugin/access/exploit_ex")
def execute_operation(self, operation_id, state="running"):
@ -506,7 +587,7 @@ class CalderaControl():
# ######## All inclusive methods
def attack(self, attack_logger: AttackLog = None, paw="kickme", ability_id="bd527b63-9f9e-46e0-9816-b8434d2b8989", group="red", target_platform=None):
def attack(self, attack_logger: AttackLog = None, paw="kickme", ability_id="bd527b63-9f9e-46e0-9816-b8434d2b8989", group="red", target_platform=None, parameters = None):
""" Attacks a system and returns results
@param attack_logger: An attack logger class to log attacks with
@ -514,6 +595,7 @@ class CalderaControl():
@param group: Group to attack. Paw must be in the group
@param ability_id: Ability to run against the target
@param target_platform: Platform of the target machine. Optional. Used for quick-outs
@param parameters: Dict containing key-values of parameters to pass to the ability
@:return : True if the attack was executed. False if it was not. For example the target os is not supported by this attack
"""
@ -561,7 +643,8 @@ class CalderaControl():
advid=adid,
group=group,
obfuscator=obfuscator,
jitter=jitter
jitter=jitter,
parameters=parameters
)
self.attack_logger.vprint(pformat(res), 3)
@ -606,6 +689,8 @@ class CalderaControl():
self.attack_logger.vprint(f"{CommandlineColors.BACKGROUND_GREEN} Output: {outp} {CommandlineColors.ENDC}", 2)
pprint(output)
self.attack_logger.vprint(self.list_facts_for_name("source_"+operation_name), 2)
# ######## Cleanup
self.execute_operation(opid, "cleanup")
self.delete_adversary(adid)

@ -24,6 +24,36 @@ def list_agents(calcontrol, arguments): # pylint: disable=unused-argument
print(f"Running agents: {calcontrol.list_agents()}")
def list_facts(calcontrol, arguments): # pylint: disable=unused-argument
""" Call list fact stores ("sources") in caldera control
@param calcontrol: Connection to the caldera server
@param arguments: Parser command line arguments
"""
printme = "No found"
if arguments.name:
printme = calcontrol.list_facts_for_name(arguments.name)
else:
printme = calcontrol.list_sources()
print(f"Stored facts: {printme}")
def add_facts(calcontrol, arguments): # pylint: disable=unused-argument
""" Generate new facts in caldera
@param calcontrol: Connection to the caldera server
@param arguments: Parser command line arguments
"""
name = "Test"
data = {"foo": "bar"}
print(f'Created fact: {calcontrol.add_sources(name, data)}')
def delete_agents(calcontrol, arguments): # pylint: disable=unused-argument
""" Call list agents in caldera control
@ -103,6 +133,13 @@ def create_parser():
parser_delete_agents.add_argument("--paw", default=None, help="PAW to delete. if not set it will delete all agents")
parser_delete_agents.set_defaults(func=delete_agents)
parser_facts = subparsers.add_parser("facts", help="facts")
parser_facts.set_defaults(func=list_facts)
parser_facts.add_argument("--name", default=None, help="Name of a fact source to focus on")
parser_facts = subparsers.add_parser("add_facts", help="facts")
parser_facts.set_defaults(func=add_facts)
# For all parsers
main_parser.add_argument("--caldera_url", help="caldera url, including port", default="http://192.168.178.125:8888/")
main_parser.add_argument("--apikey", help="caldera api key", default="ADMIN123")

@ -98,16 +98,20 @@ class AttackPlugin(BasePlugin):
"""
self.caldera = caldera
def caldera_attack(self, target, ability_id):
def caldera_attack(self, target, ability_id, parameters=None):
""" Attack a single target using caldera
@param target: Target machine object
@param ability_id: Ability if od caldera ability to run
@param parameters: parameters to pass to the ability
"""
self.caldera.attack(self.attack_logger,
paw=target.get_paw(),
ability_id=ability_id,
group=target.get_group(),
target_platform=target.get_os()
target_platform=target.get_os(),
parameters=parameters
)
def get_attacker_playground(self):

Loading…
Cancel
Save