Esempio n. 1
0
    async def add_manual_command(self, access, data):
        for parameter in ['operation', 'agent', 'executor', 'command']:
            if parameter not in data.keys():
                return dict(error='Missing parameter: %s' % parameter)

        operation_search = {'id': data['operation'], **access}
        operation = next(iter(await self.get_service('data_svc').locate('operations', match=operation_search)), None)
        if not operation:
            return dict(error='Operation not found')

        agent_search = {'paw': data['agent'], **access}
        agent = next(iter(await self.get_service('data_svc').locate('agents', match=agent_search)), None)
        if not agent:
            return dict(error='Agent not found')

        if data['executor'] not in agent.executors:
            return dict(error='Agent missing specified executor')

        encoded_command = self.encode_string(data['command'])
        ability_id = str(uuid.uuid4())

        executor = Executor(name=data['executor'], platform=agent.platform, command=data['command'])
        ability = Ability(ability_id=ability_id, tactic='auto-generated', technique_id='auto-generated',
                          technique_name='auto-generated', name='Manual Command', description='Manual command ability',
                          executors=[executor])
        link = Link.load(dict(command=encoded_command, paw=agent.paw, cleanup=0, ability=ability, score=0, jitter=2,
                              executor=executor, status=operation.link_status()))
        link.apply_id(agent.host)
        operation.add_link(link)

        return dict(link=link.unique)
Esempio n. 2
0
 def test_builtin_fact_replacement_with_upstream_dest(
         self, loop, obfuscator, init_base_world):
     executor = Executor(
         name='psh',
         platform='windows',
         command=
         'echo #{paw} #{server} #{group} #{location} #{exe_name} #{upstream_dest}'
     )
     ability = Ability(ability_id='123', executors=[executor])
     agent = Agent(paw='123',
                   sleep_min=2,
                   sleep_max=8,
                   watchdog=0,
                   executors=['pwsh', 'psh'],
                   platform='windows',
                   group='my_group',
                   server='http://10.10.10.10:8888',
                   location='testlocation',
                   exe_name='testexe',
                   upstream_dest='http://127.0.0.1:12345')
     loop.run_until_complete(agent.task([ability], 'plain-text', []))
     assert 1 == len(agent.links)
     link = agent.links[0]
     decoded_command = b64decode(link.command).decode('utf-8')
     want = 'echo 123 http://10.10.10.10:8888 my_group testlocation testexe http://127.0.0.1:12345'
     assert want == decoded_command
Esempio n. 3
0
def setup_rest_svc_test(loop, data_svc):
    BaseWorld.apply_config(name='default',
                           config={
                               'app.contact.http': '0.0.0.0',
                               'plugins': ['sandcat', 'stockpile'],
                               'crypt_salt': 'BLAH',
                               'api_key': 'ADMIN123',
                               'encryption_key': 'ADMIN123',
                               'exfil_dir': '/tmp'
                           })
    loop.run_until_complete(
        data_svc.store(
            Ability(ability_id='123',
                    test=BaseWorld.encode_string('curl #{app.contact.http}'),
                    variations=[])))
    loop.run_until_complete(
        data_svc.store(
            Adversary(adversary_id='123',
                      name='test',
                      description='test',
                      phases=[])))
    loop.run_until_complete(
        data_svc.store(Agent(paw='123', sleep_min=2, sleep_max=8, watchdog=0)))
    loop.run_until_complete(
        data_svc.store(
            Planner(planner_id='123',
                    name='test',
                    module='test',
                    params=dict())))
    loop.run_until_complete(
        data_svc.store(Source(identifier='123', name='test', facts=[])))
Esempio n. 4
0
 def setUp(self):
     # for those that are curious -- when abilities are created, commands are b64 encoded
     # by default.
     self.command = 'whoami'
     self.encoded_command = b64encode(
         self.command.strip().encode('utf-8')).decode()
     self.dummy_ability = Ability(ability_id=None,
                                  tactic=None,
                                  technique_id=None,
                                  technique=None,
                                  name=None,
                                  test=None,
                                  description=None,
                                  cleanup=None,
                                  executor='sh',
                                  platform=None,
                                  payload=None,
                                  variations=[],
                                  parsers=None,
                                  requirements=None,
                                  privilege=None)
     self.dummy_agent = Agent(paw='123',
                              platform='linux',
                              executors=['sh'],
                              server='http://localhost:8888',
                              sleep_min=0,
                              sleep_max=0,
                              watchdog=0)
     self.dummy_link = Link(id='abc',
                            operation='123',
                            command=self.encoded_command,
                            paw='123',
                            ability=self.dummy_ability)
Esempio n. 5
0
async def _save_ability(data_svc, entries, test):
    ability_id = hashlib.md5(json.dumps(test).encode()).hexdigest()
    at_ingested = 0
    at_total = 0
    for p in test['supported_platforms']:
        at_total += 1
        if test['executor']['name'] == 'manual':
            # this test is expected to be run manually by a human, no automation is provided
            continue
        encoded_command, encoded_cleanup = await _prepare_executor(test)
        await data_svc.store(
            Ability(ability_id=ability_id,
                    tactic='redcanary',
                    technique_id=entries['attack_technique'],
                    technique=entries['display_name'],
                    name=test['name'],
                    description=test['description'],
                    platform=PLATFORMS.get(p, 'unknown'),
                    executor=EXECUTORS.get(test['executor']['name'],
                                           'unknown'),
                    test=encoded_command,
                    cleanup=encoded_cleanup,
                    requirements=[],
                    parsers=[],
                    variations=[]))
        at_ingested += 1

    return (at_ingested, at_total)
 def test_privileged_to_run__1(self, loop, data_svc):
     """ Test ability.privilege == None """
     agent = loop.run_until_complete(data_svc.store(Agent(sleep_min=1, sleep_max=2, watchdog=0)))
     ability = loop.run_until_complete(data_svc.store(
         Ability(ability_id='123', privilege=None)
     ))
     assert agent.privileged_to_run(ability)
 def test_privileged_to_run__6(self, loop, data_svc):
     """ Test ability.privilege == 'None' and agent.privilege == 'Elevated' """
     agent = loop.run_until_complete(data_svc.store(Agent(sleep_min=1, sleep_max=2, watchdog=0, privilege='Elevated')))
     ability = loop.run_until_complete(data_svc.store(
         Ability(ability_id='123')
     ))
     assert agent.privileged_to_run(ability)
Esempio n. 8
0
 def test_privileged_to_run__1(self):
     """ Test ability.privilege == None """
     agent = self.run_async(
         self.data_svc.store(Agent(sleep_min=1, sleep_max=2, watchdog=0)))
     ability = self.run_async(
         self.data_svc.store(
             Ability(ability_id='123', privilege=None, variations=[])))
     self.assertTrue(agent.privileged_to_run(ability))
Esempio n. 9
0
    def test_task_with_facts(self, loop, obfuscator, init_base_world):
        ability = Ability(ability_id='123', test=BaseWorld.encode_string('net user #{domain.user.name} /domain'),
                          variations=[], executor='psh', platform='windows')
        agent = Agent(paw='123', sleep_min=2, sleep_max=8, watchdog=0, executors=['pwsh', 'psh'], platform='windows')
        fact = Fact(trait='domain.user.name', value='bob')

        loop.run_until_complete(agent.task([ability], 'plain-text', [fact]))
        assert 1 == len(agent.links)
Esempio n. 10
0
 async def _create_ability(self, ability_id, name=None, description=None, tactic=None, technique_id=None,
                           technique_name=None, executors=None, requirements=None, privilege=None,
                           repeatable=False, buckets=None, access=None, singleton=False, plugin='', **kwargs):
     ability = Ability(ability_id=ability_id, name=name, description=description, tactic=tactic,
                       technique_id=technique_id, technique_name=technique_name, executors=executors,
                       requirements=requirements, privilege=privilege, repeatable=repeatable, buckets=buckets,
                       access=access, singleton=singleton, plugin=plugin, **kwargs)
     return await self.store(ability)
Esempio n. 11
0
 def from_json(cls, json):
     ability = Ability.from_json(json['ability'])
     return cls(id=json['id'],
                pin=json['pin'],
                operation=json['operation'],
                command=json['command'],
                paw=json['paw'],
                ability=ability)
Esempio n. 12
0
    def test_task_with_facts(self, event_loop, obfuscator, init_base_world, knowledge_svc):
        executor = Executor(name='psh', platform='windows', command='net user #{domain.user.name} /domain')
        ability = Ability(ability_id='123', executors=[executor])
        agent = Agent(paw='123', sleep_min=2, sleep_max=8, watchdog=0, executors=['pwsh', 'psh'], platform='windows')
        fact = Fact(trait='domain.user.name', value='bob')

        event_loop.run_until_complete(agent.task([ability], 'plain-text', [fact]))
        assert 1 == len(agent.links)
Esempio n. 13
0
    async def add_manual_command(self, access, data):
        for parameter in ['operation', 'agent', 'executor', 'command']:
            if parameter not in data.keys():
                return dict(error='Missing parameter: %s' % parameter)

        try:
            operation_id = int(data['operation'])
        except ValueError:
            return dict(error='Invalid operation ID')
        operation_search = {'id': operation_id, **access}
        operation = next(
            iter(await
                 self.get_service('data_svc').locate('operations',
                                                     match=operation_search)),
            None)
        if not operation:
            return dict(error='Operation not found')

        agent_search = {'paw': data['agent'], **access}
        agent = next(
            iter(await
                 self.get_service('data_svc').locate('agents',
                                                     match=agent_search)),
            None)
        if not agent:
            return dict(error='Agent not found')

        if data['executor'] not in agent.executors:
            return dict(error='Agent missing specified executor')

        encoded_command = self.encode_string(data['command'])
        ability = Ability(ability_id='auto-generated',
                          tactic='auto-generated',
                          technique_id='auto-generated',
                          technique='auto-generated',
                          name='Manual Command',
                          description='Manual command ability',
                          cleanup='',
                          test=encoded_command,
                          executor=data['executor'],
                          platform=agent.platform,
                          payloads=[],
                          parsers=[],
                          requirements=[],
                          privilege=None,
                          variations=[])
        link = Link.load(
            dict(command=encoded_command,
                 paw=agent.paw,
                 cleanup=0,
                 ability=ability,
                 score=0,
                 jitter=2,
                 status=operation.link_status()))
        link.apply_id(agent.host)
        operation.add_link(link)

        return dict(link=link.unique)
Esempio n. 14
0
def setup_rest_svc_test(loop, data_svc):
    BaseWorld.apply_config(name='main', config={'app.contact.http': '0.0.0.0',
                                                'plugins': ['sandcat', 'stockpile'],
                                                'crypt_salt': 'BLAH',
                                                'api_key': 'ADMIN123',
                                                'encryption_key': 'ADMIN123',
                                                'exfil_dir': '/tmp'})
    loop.run_until_complete(data_svc.store(
        Ability(ability_id='123', test=BaseWorld.encode_string('curl #{app.contact.http}'), variations=[],
                executor='psh', platform='windows'))
    )
    loop.run_until_complete(data_svc.store(
        Ability(ability_id='456', test=BaseWorld.encode_string('whoami'), variations=[],
                executor='sh', platform='linux'))
    )
    loop.run_until_complete(data_svc.store(
        Ability(ability_id='789', test=BaseWorld.encode_string('hostname'), variations=[],
                executor='sh', platform='linux'))
    )
    adversary = Adversary(adversary_id='123', name='test', description='test', atomic_ordering=[])
    loop.run_until_complete(data_svc.store(adversary))

    agent = Agent(paw='123', sleep_min=2, sleep_max=8, watchdog=0, executors=['pwsh', 'psh'], platform='windows')
    loop.run_until_complete(data_svc.store(agent))

    loop.run_until_complete(data_svc.store(
        Objective(id='495a9828-cab1-44dd-a0ca-66e58177d8cc', name='default', goals=[Goal()])
    ))

    loop.run_until_complete(data_svc.store(
        Planner(planner_id='123', name='test', module='test', params=dict())
    ))

    source = Source(id='123', name='test', facts=[], adjustments=[])
    loop.run_until_complete(data_svc.store(source))

    loop.run_until_complete(data_svc.store(
        Operation(name='test', agents=[agent], adversary=adversary, id='123', source=source)
    ))

    loop.run_until_complete(data_svc.store(
        Obfuscator(name='plain-text',
                   description='Does no obfuscation to any command, instead running it in plain text',
                   module='plugins.stockpile.app.obfuscators.plain_text')
    ))
Esempio n. 15
0
 def _generate_ability(ability_id=None, variations=None, *args, **kwargs):
     if not ability_id:
         ability_id = random.randint(0, 999999)
     if not variations:
         variations = []
     return Ability(ability_id=ability_id,
                    variations=variations,
                    *args,
                    **kwargs)
Esempio n. 16
0
 def test_privileged_to_run__3(self, loop, data_svc):
     """ Test ability.privilege == 'Elevated' """
     agent = loop.run_until_complete(
         data_svc.store(Agent(sleep_min=1, sleep_max=2, watchdog=0)))
     ability = loop.run_until_complete(
         data_svc.store(
             Ability(ability_id='123', privilege='Elevated',
                     variations=[])))
     assert not agent.privileged_to_run(ability)
Esempio n. 17
0
 async def _create_ability(self, ability_id, tactic=None, technique_name=None, technique_id=None, name=None,
                           test=None, description=None, executor=None, platform=None, cleanup=None, payloads=None,
                           parsers=None, requirements=None, privilege=None, timeout=60, access=None, buckets=None,
                           repeatable=False, code=None, language=None, build_target=None, variations=None, **kwargs):
     ps = []
     for module in parsers:
         ps.append(Parser.load(dict(module=module, parserconfigs=parsers[module])))
     rs = []
     for requirement in requirements:
         for module in requirement:
             rs.append(Requirement.load(dict(module=module, relationship_match=requirement[module])))
     ability = Ability(ability_id=ability_id, name=name, test=test, tactic=tactic,
                       technique_id=technique_id, technique=technique_name, code=code, language=language,
                       executor=executor, platform=platform, description=description, build_target=build_target,
                       cleanup=cleanup, payloads=payloads, parsers=ps, requirements=rs,
                       privilege=privilege, timeout=timeout, repeatable=repeatable,
                       variations=variations, buckets=buckets, **kwargs)
     ability.access = access
     return await self.store(ability)
Esempio n. 18
0
 def test_task_no_facts(self, loop, data_svc, obfuscator, init_base_world):
     executor = Executor(name='psh', platform='windows', command='whoami')
     ability = Ability(ability_id='123', executors=[executor])
     agent = Agent(paw='123',
                   sleep_min=2,
                   sleep_max=8,
                   watchdog=0,
                   executors=['pwsh', 'psh'],
                   platform='windows')
     loop.run_until_complete(agent.task([ability], obfuscator='plain-text'))
     assert 1 == len(agent.links)
Esempio n. 19
0
 def setUp(self):
     self.initialize()
     self.ability = Ability(ability_id='123',
                            executor='sh',
                            test=BaseWorld.encode_string('mkdir test'),
                            cleanup=BaseWorld.encode_string('rm -rf test'))
     self.agent = Agent(sleep_min=1, sleep_max=2, watchdog=0)
     self.operation = Operation(name='test1',
                                agents=self.agent,
                                adversary='hunter')
     self.run_async(self.data_svc.store(self.ability))
Esempio n. 20
0
 async def _create_ability(self, ability_id, tactic=None, technique_name=None, technique_id=None, name=None, test=None,
                           description=None, executor=None, platform=None, cleanup=None, payloads=None, parsers=None,
                           requirements=None, privilege=None, timeout=60, access=None, repeatable=False, variations=None):
     ps = []
     for module in parsers:
         pcs = [(ParserConfig(**m)) for m in parsers[module]]
         ps.append(Parser(module=module, parserconfigs=pcs))
     rs = []
     for requirement in requirements:
         for module in requirement:
             relation = [Relationship(source=r['source'], edge=r.get('edge'), target=r.get('target')) for r in
                         requirement[module]]
             rs.append(Requirement(module=module, relationships=relation))
     ability = Ability(ability_id=ability_id, name=name, test=test, tactic=tactic,
                       technique_id=technique_id, technique=technique_name,
                       executor=executor, platform=platform, description=description,
                       cleanup=cleanup, payloads=payloads, parsers=ps, requirements=rs,
                       privilege=privilege, timeout=timeout, repeatable=repeatable, variations=variations)
     ability.access = access
     return await self.store(ability)
Esempio n. 21
0
 def setUp(self):
     self.initialize()
     BaseWorld.apply_config({
         'app.contact.http': '0.0.0.0',
         'plugins': ['sandcat', 'stockpile']
     })
     self.run_async(
         self.data_svc.store(
             Ability(
                 ability_id='123',
                 test=BaseWorld.encode_string('curl #{app.contact.http}'))))
Esempio n. 22
0
 def test_privileged_to_run__4(self):
     """ Test ability.privilege == 'User' and agent.privilege == 'Elevated' """
     agent = self.run_async(
         self.data_svc.store(
             Agent(sleep_min=1,
                   sleep_max=2,
                   watchdog=0,
                   privilege='Elevated')))
     ability = self.run_async(
         self.data_svc.store(
             Ability(ability_id='123', privilege='User', variations=[])))
     self.assertTrue(agent.privileged_to_run(ability))
Esempio n. 23
0
 def test_task_missing_fact(self, loop, obfuscator, init_base_world):
     executor = Executor(name='psh',
                         platform='windows',
                         command='net user #{domain.user.name} /domain')
     ability = Ability(ability_id='123', executors=[executor])
     agent = Agent(paw='123',
                   sleep_min=2,
                   sleep_max=8,
                   watchdog=0,
                   executors=['pwsh', 'psh'],
                   platform='windows')
     loop.run_until_complete(agent.task([ability], obfuscator='plain-text'))
     assert 0 == len(agent.links)
Esempio n. 24
0
def test_ability(loop, api_v2_client, executor):
    executor_linux = executor(name='sh', platform='linux')
    ability = Ability(ability_id='123',
                      name='Test Ability',
                      executors=[executor_linux],
                      technique_name='collection',
                      technique_id='1',
                      description='',
                      privilege='',
                      tactic='discovery',
                      plugin='testplugin')
    loop.run_until_complete(BaseService.get_service('data_svc').store(ability))
    return ability
Esempio n. 25
0
    def test_ability(self):
        self.run_async(
            self.data_svc.store(
                Ability(ability_id='123',
                        tactic='discovery',
                        technique_id='1',
                        technique='T1033',
                        name='test',
                        test='d2hvYW1pCg==',
                        description='find active user',
                        cleanup='',
                        executor='sh',
                        platform='darwin',
                        payload='wifi.sh',
                        parsers=[],
                        requirements=[],
                        privilege=None,
                        variations=[])))
        self.run_async(
            self.data_svc.store(
                Ability(ability_id='123',
                        tactic='discovery',
                        technique_id='1',
                        technique='T1033',
                        name='test',
                        test='d2hvYW1pCg==',
                        description='find active user',
                        cleanup='',
                        executor='sh',
                        platform='darwin',
                        payload='wifi.sh',
                        parsers=[],
                        requirements=[],
                        privilege=None,
                        variations=[])))
        abilities = self.run_async(self.data_svc.locate('abilities'))

        self.assertEqual(1, len(abilities))
Esempio n. 26
0
    def test_no_duplicate_ability(self, loop, data_svc):
        loop.run_until_complete(
            data_svc.store(
                Ability(ability_id='123',
                        tactic='discovery',
                        technique_id='1',
                        technique='T1033',
                        name='test',
                        test='d2hvYW1pCg==',
                        description='find active user',
                        cleanup='',
                        executor='sh',
                        platform='darwin',
                        payload='wifi.sh',
                        parsers=[],
                        requirements=[],
                        privilege=None,
                        variations=[])))
        loop.run_until_complete(
            data_svc.store(
                Ability(ability_id='123',
                        tactic='discovery',
                        technique_id='1',
                        technique='T1033',
                        name='test',
                        test='d2hvYW1pCg==',
                        description='find active user',
                        cleanup='',
                        executor='sh',
                        platform='darwin',
                        payload='wifi.sh',
                        parsers=[],
                        requirements=[],
                        privilege=None,
                        variations=[])))
        abilities = loop.run_until_complete(data_svc.locate('abilities'))

        assert len(abilities) == 1
Esempio n. 27
0
 def test_task_no_facts(self, loop, data_svc, obfuscator, init_base_world):
     ability = Ability(ability_id='123',
                       test=BaseWorld.encode_string('whoami'),
                       variations=[],
                       executor='psh',
                       platform='windows')
     agent = Agent(paw='123',
                   sleep_min=2,
                   sleep_max=8,
                   watchdog=0,
                   executors=['pwsh', 'psh'],
                   platform='windows')
     loop.run_until_complete(agent.task([ability], obfuscator='plain-text'))
     assert 1 == len(agent.links)
Esempio n. 28
0
 def test_task_missing_fact(self, loop, init_base_world):
     ability = Ability(ability_id='123',
                       test=BaseWorld.encode_string(
                           'net user #{domain.user.name} /domain'),
                       variations=[],
                       executor='psh',
                       platform='windows')
     agent = Agent(paw='123',
                   sleep_min=2,
                   sleep_max=8,
                   watchdog=0,
                   executors=['pwsh', 'psh'],
                   platform='windows')
     loop.run_until_complete(agent.task([ability]))
     assert 0 == len(agent.links)
Esempio n. 29
0
 def test_ability(self):
     self.run_async(
         self.data_svc.store(
             Ability(ability_id='123',
                     tactic='discovery',
                     technique_id='1',
                     technique='T1033',
                     name='test',
                     test='whoami',
                     description='find active user',
                     cleanup='',
                     executor='sh',
                     platform='darwin',
                     payload='wifi.sh',
                     parsers=[],
                     requirements=[],
                     privilege=None)))
     self.run_async(
         self.data_svc.store(
             Ability(ability_id='123',
                     tactic='discovery',
                     technique_id='1',
                     technique='T1033',
                     name='test',
                     test='whoami',
                     description='find active user',
                     cleanup='',
                     executor='sh',
                     platform='darwin',
                     payload='wifi.sh',
                     parsers=[],
                     requirements=[],
                     privilege=None)))
     self.assertEqual(1, len(self.data_svc.ram['abilities']))
     for x in self.data_svc.ram['abilities']:
         json.dumps(x.display)
Esempio n. 30
0
    def test_no_autogen_cleanup_cmds(self, event_loop, data_svc):
        cleanup_executor = Executor(name='sh',
                                    platform='linux',
                                    cleanup='rm #{payload}')
        event_loop.run_until_complete(
            data_svc.store(
                Ability(
                    ability_id='4cd4eb44-29a7-4259-91ae-e457b283a880',
                    tactic='defense-evasion',
                    technique_id='T1070.004',
                    technique_name='Indicator Removal on Host: File Deletion',
                    name='Delete payload',
                    description='Remove a downloaded payload file',
                    privilege=None,
                    executors=[cleanup_executor])))
        executor = Executor(name='special_executor',
                            platform='darwin',
                            command='whoami',
                            payloads=['wifi.sh'])
        event_loop.run_until_complete(
            data_svc.store(
                Ability(ability_id='123',
                        tactic='discovery',
                        technique_id='1',
                        technique_name='T1033',
                        name='test',
                        description='find active user',
                        privilege=None,
                        executors=[executor])))
        event_loop.run_until_complete(data_svc._verify_abilities())
        abilities = event_loop.run_until_complete(
            data_svc.locate('abilities', dict(ability_id='123')))

        for ability in abilities:
            for executor in ability.executors:
                assert not executor.cleanup