Пример #1
0
def main():
    args = parseargs()
    client = act.Act(args.act_baseurl, args.user_id, args.loglevel,
                     args.logfile, "mitre-attack")

    for url in (MITRE_ENTERPRISE_ATTACK_URL, MITRE_MOBILE_ATTACK_URL,
                MITRE_PRE_ATTACK_URL):
        cache = notify_cache(args.notifycache)

        # Get attack dataset as Stix Memory Store
        attack = get_attack(url, args.proxy_string, args.timeout)

        (techniques, techniques_notify) = get_techniques(attack)
        (groups, groups_notify) = get_groups(attack)
        (software, software_notify) = get_software(attack)

        # Add facts to platform
        facts = techniques + groups + software
        for (source_type, source_values, fact_type, destination_type,
             destination_values, link_type) in facts:
            add_fact(client, source_type, source_values, fact_type,
                     destination_type, destination_values, link_type)

        # Get revoked objects, excluding those in cache
        notify = [
            notify
            for notify in techniques_notify + groups_notify + software_notify
            if notify.id not in cache
        ]

        if notify:
            send_notification(notify, args.notifycache, args.smtphost,
                              args.sender, args.recipient)
Пример #2
0
def test_get_object_by_type_value():
    mock = get_mock_data("data/post_v1_object_facts_200.json")
    responses.add(
        responses.POST,
        mock["url"],
        json=mock["json"],
        status=mock["status_code"])

    c = act.Act("http://localhost:8080", 1)

    obj = c.object(type="ipv4", value="127.0.0.1")

    facts = obj.facts()

    assert not facts.complete
    assert len(facts) == facts.size

    # We should have at least one fact
    assert len(facts) > 1

    # All facts should be of type Fact
    assert all([isinstance(fact, act.fact.Fact) for fact in facts])

    # All facts should have an UUID
    assert all([re.search(RE_UUID_MATCH, fact.id) for fact in facts])
Пример #3
0
def test_object_search():
    mock = get_mock_data("data/post_v1_object_search_200.json")
    responses.add(
        responses.POST,
        mock["url"],
        json=mock["json"],
        status=mock["status_code"])

    c = act.Act("http://localhost:8080", 1)

    objects = c.object_search(
        fact_type=["seenIn"],
        fact_value=["report"],
        limit=25)

    assert not objects.complete
    assert objects.size == 25
    assert objects.count > 1000

    obj = objects[0]

    # Objects should not have "object_type", since that property is stored in
    # "type"
    with pytest.raises(AttributeError):
        # pylint: disable=pointless-statement
        obj.object_type

    # Objects should not have "object_value", since that property is stored in
    # "value"
    with pytest.raises(AttributeError):
        # pylint: disable=pointless-statement
        obj.object_value

    # All facts should have an UUID
    assert all([re.search(RE_UUID_MATCH, obj.id) for obj in objects])
Пример #4
0
def setup():
    cfg = cli.getConfStanza('act', 'config')
    app = cli.getConfStanza('app', 'launcher')
    api_url = cfg.get("api_url")
    user_id = cfg.get("act_userid")
    api_proxy = cfg.get("api_proxy")
    api_http_user = cfg.get("api_http_user")
    api_http_password = cfg.get("api_http_auth")

    requests_opt = {
        "headers": {  # Include version string in user agent header
            "User-Agent": "act-splunk-{}".format(app.get("version"))
        }
    }
    if api_http_user or api_http_password:
        requests_opt["auth"] = (api_http_user, api_http_password)

    if api_proxy:
        requests_opt["proxies"] = {
            "http": api_proxy,
            "https": api_proxy,
        }

    return act.Act(api_url,
                   user_id=user_id,
                   log_level="warning",
                   requests_common_kwargs=requests_opt)
Пример #5
0
def test_fact_acl():
    mock = get_mock_data("data/get_v1_fact_uuid_access_200.json")
    responses.add(responses.GET,
                  mock["url"],
                  json=mock["json"],
                  status=mock["status_code"])

    c = act.Act("http://localhost:8080", 1)
    uuid = re.search(RE_UUID, mock["url"]).group("uuid")
    acl = c.fact(id=uuid).get_acl()
    assert acl == []
Пример #6
0
def test_get_fact_types():
    mock = get_mock_data("data/get_v1_factType_200.json")
    responses.add(responses.GET,
                  mock["url"],
                  json=mock["json"],
                  status=mock["status_code"])

    c = act.Act("http://localhost:8080", 1)
    fact_types = c.get_fact_types()

    assert fact_types.size == len(fact_types)
Пример #7
0
def main():
    """main function"""

    args = parse_args()

    actapi = act.Act(args.act_baseurl, args.user_id, args.loglevel,
                     args.logfile, "cyber-uio")

    in_data = sys.stdin.read().strip()

    if args.hexdigest:
        handle_hexdigest(actapi, in_data, args.proxy)
Пример #8
0
def test_fact_add_comment():
    mock = get_mock_data("data/post_v1_fact_uuid_comments_201.json")
    responses.add(responses.POST,
                  mock["url"],
                  json=mock["json"],
                  status=mock["status_code"])

    c = act.Act("http://localhost:8080", 1)

    # Get comments
    uuid = re.search(RE_UUID, mock["url"]).group("uuid")

    c.fact(id=uuid).add_comment("Test comment")
Пример #9
0
def test_create_object_type():
    mock = get_mock_data("data/post_v1_objectType_201.json")
    responses.add(
        responses.POST,
        mock["url"],
        json=mock["json"],
        status=mock["status_code"])

    c = act.Act("http://localhost:8080", 1)
    object_type = c.object_type(
        name="threatActor",
        validator=".+").add()

    assert object_type.name == "threatActor"
    assert re.search(RE_UUID_MATCH, object_type.id)
Пример #10
0
def test_fact_get_comments():
    mock = get_mock_data("data/get_v1_fact_uuid_comments_200.json")
    responses.add(responses.GET,
                  mock["url"],
                  json=mock["json"],
                  status=mock["status_code"])

    c = act.Act("http://localhost:8080", 1)

    # Get comments
    uuid = re.search(RE_UUID, mock["url"]).group("uuid")
    comments = c.fact(id=uuid).get_comments()
    assert comments  # Should be non empty
    assert comments[0].comment == "Test comment"
    assert re.search(RE_TIMESTAMP, comments[0].timestamp)
    assert all([isinstance(comment, act.base.Comment) for comment in comments])
Пример #11
0
def test_add_fact():
    mock = get_mock_data("data/post_v1_fact_201.json")
    responses.add(responses.POST,
                  mock["url"],
                  json=mock["json"],
                  status=mock["status_code"])

    c = act.Act("http://localhost:8080", 1)

    f = c.fact("seenIn", "report") \
        .source("ipv4", "127.0.0.1") \
        .destination("report", "xyz")

    assert f.type.name == "seenIn"
    assert f.value == "report"

    # We do not have id or timestamp yet
    assert f.id is None
    assert f.timestamp is None
    assert f.source_object is not None
    assert f.destination_object is not None
    assert f.bidirectional_binding is not None

    # Add fact
    f.add()

    fact_repr = repr(f)
    repr_f = eval(fact_repr)

    assert f == repr_f
    assert f.value == repr_f.value
    assert f.type.name == repr_f.type.name
    assert f.source_object == repr_f.source_object
    assert f.source_object.value == repr_f.source_object.value
    assert f.destination_object.type == repr_f.destination_object.type
    assert f.destination_object.value == repr_f.destination_object.value

    assert str(f) == str(repr_f)

    assert str(f) == \
        "(ipv4/127.0.0.1) -[seenIn/report]-> (report/87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7)"

    # id, timestamp and organization should now be fetched from API
    assert re.search(RE_UUID_MATCH, f.id)
    assert re.search(RE_TIMESTAMP_MATCH, f.timestamp)
    assert re.search(RE_UUID_MATCH, f.organization.id)
Пример #12
0
def test_get_object_by_uuid():
    mock = get_mock_data("data/post_v1_object_uuid_facts_200.json")
    responses.add(
        responses.POST,
        mock["url"],
        json=mock["json"],
        status=mock["status_code"])

    uuid = re.search(RE_UUID, mock["url"]).group("uuid")

    c = act.Act("http://localhost:8080", 1)

    obj = c.object(id=uuid)

    facts = obj.facts()

    assert all([re.search(RE_UUID_MATCH, fact.id) for fact in facts])
Пример #13
0
def test_get_object_search():
    mock = get_mock_data("data/post_v1_object_traverse_200.json")
    responses.add(
        responses.POST,
        mock["url"],
        json=mock["json"],
        status=mock["status_code"])

    c = act.Act("http://localhost:8080", 1)

    obj = c.object(type="ipv4", value="127.0.0.1")

    path = obj.traverse('g.bothE("seenIn").bothV().path().unfold()')

    # Should contain both objects and facts
    assert any([isinstance(elem, act.obj.Object) for elem in path])
    assert any([isinstance(elem, act.fact.Fact) for elem in path])
Пример #14
0
def test_get_object_types():
    mock = get_mock_data("data/get_v1_objectType_200.json")
    responses.add(
        responses.GET,
        mock["url"],
        json=mock["json"],
        status=mock["status_code"])

    c = act.Act("http://localhost:8080", 1)
    object_types = c.get_object_types()

    # We should have a fqdn object type
    assert "fqdn" in [object_t.name for object_t in object_types]

    # All object types should have a valid uuid
    assert all([re.search(RE_UUID_MATCH, object_t.id)
                for object_t in object_types])
Пример #15
0
def test_fact_search():
    mock = get_mock_data("data/post_v1_fact_search_200.json")
    responses.add(responses.POST,
                  mock["url"],
                  json=mock["json"],
                  status=mock["status_code"])

    c = act.Act("http://localhost:8080", 1)

    facts = c.fact_search(fact_type=["seenIn"],
                          fact_value=["report"],
                          limit=25)

    assert not facts.complete
    assert facts.size == 25
    assert facts.count > 1000

    # All facts should have an UUID
    assert all([re.search(RE_UUID_MATCH, fact.id) for fact in facts])
Пример #16
0
def main():
    """main function"""

    args = parse_args()

    actapi = act.Act(args.act_baseurl, args.user_id, args.loglevel,
                     args.logfile, "vt-enrichment")

    in_data = sys.stdin.read().strip()

    proxies = {'http': args.proxy, 'https': args.proxy} if args.proxy else None

    vtapi = VirusTotalApi(args.apikey, proxies=proxies)

    if args.hexdigest:
        handle_hexdigest(actapi, vtapi, in_data)

    if args.ip:
        handle_ip(actapi, vtapi, in_data)

    if args.domain:
        handle_domain(actapi, vtapi, in_data)
Пример #17
0
def test_create_fact_type():
    mock = get_mock_data("data/post_v1_factType_201.json")
    responses.add(responses.POST,
                  mock["url"],
                  json=mock["json"],
                  status=mock["status_code"])

    mock_data = mock["json"]["data"]
    threat_actor_id = mock_data["relevantObjectBindings"][0][
        "destinationObjectType"]["id"]

    c = act.Act("http://localhost:8080", 1)
    fact_type = c.fact_type(name="threatActorAlias",
                            validator=".+",
                            relevant_object_bindings=[
                                act.fact.RelevantObjectBindings(
                                    act.obj.Object(id=threat_actor_id),
                                    act.obj.Object(id=threat_actor_id), True)
                            ]).add()

    assert fact_type.name == "threatActorAlias"
    assert re.search(RE_UUID_MATCH, fact_type.id)
Пример #18
0
                        help="Loglevel (default = info)")

    return parser.parse_args()


def process(actapi):
    """Process stdin, parse each separat line as a JSON structure and
    register a fact based on the structure. The form of input should
    be the on the form accepted by the ACT Rest API fact API."""

    for line in sys.stdin:
        data = json.loads(line)

        fact = actapi.fact(**data)
        try:
            fact.add()
        except act.base.ResponseError as err:
            error("ResponseError while storing objects: %s" % err)


if __name__ == '__main__':
    ARGS = parseargs()

    try:
        actapi = act.Act(ARGS.act_baseurl, ARGS.user_id, ARGS.loglevel,
                         ARGS.logfile, "generic-uploader")
        process(actapi)
    except Exception as e:
        error("Unhandled exception: {}".format(traceback.format_exc()))
        raise
Пример #19
0
                                                      "uri", "*"))

            for fact in fact_chain(*chain):  # Find content value (placeholder)
                handle_fact(fact)

                # Replace content with placeholder object if this was previously unknown
                if content == "*" and fact.destination_object.type.name == "content":
                    content = fact.destination_object.value

                # Add port to uri placeholder
                if port and fact.destination_object.type.name == "uri":
                    handle_fact(
                        client.fact("port", str(port)).source(
                            "uri", fact.destination_object.value))

        if content != "*":
            handle_fact(
                client.fact("classifiedAs").source("content",
                                                   content).destination(
                                                       "tool", "carbanak"))


if __name__ == '__main__':
    args = parseargs()

    carbanak_report(
        act.Act(args.act_baseurl, args.user_id, args.loglevel, args.log_file,
                "fireye-carbanak"),
        get_md5_lookup(args.md5_lookup),
    )
Пример #20
0
def create_api_agent(baseurl, userid):
    """creates an ACT API agent"""
    c = act.Act(baseurl, userid, log_level="info")
    return c
Пример #21
0
        if location:
            client.fact("sourceGeography")\
                .destination("location", location)\
                .source("threatActor", name)\
                .add()

        elif country:
            warning("country code not found in ISO, ISO3 or FIPS: %s\n" %
                    country)

        # Loop over all items under indicators in report
        for alias in aliases:
            if alias == name:
                continue  # Do not alias to ourself
            client.fact("threatActorAlias")\
                .bidirectional("threatActor", alias, "threatActor", name)\
                .add()


if __name__ == '__main__':
    args = parseargs()

    client = act.Act(args.act_baseurl, args.user_id, args.log_level,
                     args.log_file, "misp-threat-actors")

    # Get all reports from SCIO
    ta = get_misp_threat_actors()

    # Add IOCs from reports to the ACT platform
    add_to_act(client, ta)
Пример #22
0
            if rrtype in RRTYPE_M:
                fact = actapi.fact(RRTYPE_M[rrtype]["fact_t"],
                                   RRTYPE_M[rrtype]["fact_v"])
                fact = fact.source(RRTYPE_M[rrtype]["source_t"], query)
                fact = fact.destination(RRTYPE_M[rrtype]["dest_t"], answer)

                fact.add()
            elif rrtype == "ptr":
                pass  # We do not insert ptr to act
            else:
                warning("Unsupported rrtype: %s: %s" % (rrtype, row))


class UnknownResult(Exception):
    """UnknownResult is used in API request (not 200 result)"""

    def __init__(self, *args, **kwargs):
        Exception.__init__(self, *args, **kwargs)


if __name__ == '__main__':
    ARGS = parseargs()

    try:
        actapi = act.Act(ARGS.act_baseurl, ARGS.user_id, ARGS.loglevel, ARGS.logfile, "pdns-enrichment")
        process(actapi, ARGS.pdns_baseurl, ARGS.apikey, ARGS.timeout)
    except Exception as e:
        error("Unhandled exception: {}".format(traceback.format_exc()))
        raise
Пример #23
0
        actapi,
        "threatActor",
        doc.get("threat-actor", {}).get("names", []),
        report_id)

    # Tools
    seen_in_report_fact(
        actapi,
        "tool",
        doc.get("tools", {}).get("names", []),
        report_id)

    # Sector
    seen_in_report_fact(
        actapi,
        "sector",
        doc.get("sectors", []),
        report_id)


if __name__ == '__main__':
    ARGS = parseargs()

    try:
        actapi = act.Act(ARGS.act_baseurl, ARGS.act_user_id, ARGS.loglevel, ARGS.logfile, "scio")
        # Add IOCs from reports to the ACT platform
        add_to_act(actapi, get_scio_report())
    except Exception as e:
        error("Unhandled exception: {}".format(traceback.format_exc()))
        raise
Пример #24
0
        for location_type, location in c_map.items():
            if not location:
                continue  # Skip locations with empty values

            # Skip facts that are already added
            if location_type in LOCATION_TYPE_M and location not in facts_added:
                fact_type = LOCATION_TYPE_M[location_type]
                facts_added[location] = fact_type

                fact = actapi.fact(fact_type).source("location", location)

                if actapi.act_baseurl:
                    fact.add()  # Add fact to platform, if baseurl is specified
                else:
                    print(fact.json(
                    ))  # Print fact to stdout, if baseurl is NOT specified


if __name__ == '__main__':
    ARGS = parseargs()

    try:
        actapi = act.Act(ARGS.act_baseurl, ARGS.user_id, ARGS.loglevel,
                         ARGS.logfile, "country-region")
        country_list = worker.fetch_json(ARGS.country_region_url,
                                         ARGS.proxy_string, ARGS.timeout)
        process(actapi, country_list)
    except Exception as e:
        error("Unhandled exception: {}".format(traceback.format_exc()))
        raise
Пример #25
0
        meta_fact_types = json.loads(open(meta_fact_types_filename).read())
    except json.decoder.JSONDecodeError:
        critical("Unable to parse file as json: %s" % meta_fact_types_filename)
        sys.exit(1)

    for meta_fact_type in meta_fact_types:
        name = meta_fact_type["name"]
        validator = meta_fact_type.get("validator", act.DEFAULT_VALIDATOR)
        fact_bindings = meta_fact_type.get("factBindings", [])

        if not fact_bindings:
            client.create_meta_fact_type_all_bindings(name, validator_parameter=validator)

        else:
            client.create_meta_fact_type(name, fact_bindings=fact_bindings, validator=validator)


if __name__ == "__main__":
    args = parseargs()

    client = act.Act(
        args.act_baseurl,
        args.user_id,
        args.log_level,
        args.log_file,
        "act-types")
    create_object_types(
        client, object_types_filename=args.object_types_filename)
    create_fact_types(client, fact_types_filename=args.fact_types_filename)
    create_meta_fact_types(client, meta_fact_types_filename=args.meta_fact_types_filename)
Пример #26
0
                        try:
                            fact.add()
                            n += 1
                        except act.base.ResponseError as err:
                            e += 1
                            log(str(err))
                    else:
                        print(Style.BRIGHT, Fore.YELLOW, fact.json(),
                              Style.RESET_ALL)
                log("Added {0} facts. {1} errors.".format(n, e))
        for k, v in status.items():
            log("{} {} sent to enrichment".format(v, k))


if __name__ == "__main__":
    ARGS = parseargs()
    CONF = configparser.ConfigParser()
    read = CONF.read(ARGS.config)
    if len(read) == 0:
        print("Could not read config file")
        sys.exit(1)

    try:
        actapi = act.Act(CONF['platform']['base_url'], ARGS.act_user_id,
                         CONF['misp']['loglevel'], CONF['misp']['logfile'],
                         "misp-import")
        main(actapi)
    except Exception as e:
        error("Unhandled exception: {}".format(traceback.format_exc()))
        raise
Пример #27
0
    return filtered_result


def out_result(filename, entries):
    with open(filename, "w") as f:
        f.write(
            json.dumps(entries,
                       sort_keys=True,
                       indent=4,
                       separators=(',', ': ')))


if __name__ == '__main__':
    args = parseargs()

    client = act.Act(args.act_baseurl, args.user_id, args.log_level,
                     args.log_file, "mitre-attack")

    if args.models in ("all", "attack", "pre-attack"):
        attack_software_raw = mediawiki_ask(MITRE_ATTACK_URL,
                                            "[[Category:Software]]",
                                            MITRE_ALL_PROPERTIES)

    if args.models == "all" or args.models == "attack":
        attack_group_raw = mediawiki_ask(MITRE_ATTACK_URL,
                                         "[[Category:Group]]",
                                         MITRE_ALL_PROPERTIES)
        attack_technique_raw = mediawiki_ask(MITRE_ATTACK_URL,
                                             "[[Category:Technique]]",
                                             MITRE_ALL_PROPERTIES)
        attack_tactic_raw = mediawiki_ask(MITRE_ATTACK_URL,
                                          "[[Category:Tactic]]",