OpenCTI Feed 4.X
Ingest indicators from the OpenCTI feed. Compatible with OpenCTI 5.12.17 and above.
Data Enrichment & Threat Intelligence · OpenCTI Feed · Feed
Details
| ID | OpenCTI Feed 4.X |
|---|---|
| Provider | Filigran |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.5.0 |
| Docker Image | demisto/vendors-sdk:1.0.0.115493 |
| Supported Modules | Agentix XSIAM |
README
Ingest indicators from the OpenCTI feed. Compatible with OpenCTI 5.12.17 and above.
Configure OpenCTI Feed 4.X in Cortex
| Parameter | Description | Required |
|---|---|---|
| Base URL | True | |
| API Key (leave empty. Fill in the API key in the password field.) | False | |
| Indicator types to fetch | The indicator types to fetch. Out-of-the-box indicator types supported in XSOAR are: Account, Domain, Email, File, Host, IP, IPv6, Registry Key, and URL. Other types will not cause automatic indicator creation in XSOAR. | True |
| Max indicators per fetch | False | |
| Fetch indicators | False | |
| Indicator Reputation | Indicators from this integration instance will get this reputation. If none of the options is chosen, the indicator reputation will be set according to the indicator data. | False |
| Source Reliability | Reliability of the source providing the intelligence data. | True |
| Traffic Light Protocol Color | The Traffic Light Protocol (TLP) designation to apply to indicators fetched from the feed. If none of the options is chosen, the TLP color will be set according to the indicator data. | False |
| Feed Fetch Interval | False | |
| Tags | CSV values are supported. | False |
| Bypass exclusion list | When selected, the exclusion list is ignored for indicators from this feed. This means that if an indicator from this feed is on the exclusion list, the indicator might still be added to the system. | False |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False | |
| Score minimum value | Score minimum value to filter by. Values range is 1-100. | False |
| Score maximum value | Score maximum value to filter by. Values range is 1-100. | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
opencti-reset-fetch-indicators
WARNING: This command will reset your fetch history.
Base Command
opencti-reset-fetch-indicators
Input
There are no input arguments for this command.
Context Output
There is no context output for this command.
Command Example
#### Human Readable Output
>Fetch history deleted successfully
### opencti-get-indicators
***
Gets indicators from the feed.
#### Base Command
`opencti-get-indicators`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| limit | The maximum number of indicators to return per fetch. Default value is 50. Maximum value is 500. | Optional |
| indicator_types | The indicator types to fetch. Out-of-the-box indicator types supported in XSOAR are: Account, Domain, Email, File, Host, IP, IPv6, Registry Key, and URL. Other types will not cause automatic indicator creation in XSOAR. Possible values are: ALL, Account, Domain, Email, File, Host, IP, IPv6, Registry Key, URL. Default is ALL. | Optional |
| last_run_id | The last ID from the previous call, from which to begin pagination for this call. You can find this value at the OpenCTI.IndicatorsList.LastRunID context path. | Optional |
| score_start | Score minimum value to filter by. Values range is 1-100. | Optional |
| score_end | Score naximum value to filter by. Values range is 1-100. | Optional |
#### Context Output
There is no context output for this command.
#### Command Example
```!opencti-get-indicators limit=2 indicator_types="IP"```
#### Context Example
```json
{
"OpenCTI": {
"Indicators": {
"IndicatorsList": [
{
"createdBy": "1e12fe87-db3e-4838-8391-6910547bf60d",
"description": "test_desc",
"externalReferences": [],
"id": "700c8187-2dce-4aeb-bf3a-0864cb7b02c7",
"labels": [
"dev1"
],
"marking": [
"TLP:AMBER"
],
"score": 70,
"type": "IP",
"value": "1.2.3.4"
},
{
"createdBy": "1e12fe87-db3e-4838-8391-6910547bf60d",
"description": "test fetch one",
"externalReferences": [],
"id": "33bd535b-fa1c-41e2-a6f9-80d82dd29a9b",
"labels": [
"dev1",
"test-label-1"
],
"marking": [],
"score": 100,
"type": "IP",
"value": "1.1.1.1"
}
],
"lastRunID": "YXJyYXljb25uZWN0aW9uOjI="
}
}
}
Human Readable Output
Indicators
type value id IP 1.2.3.4 700c8187-2dce-4aeb-bf3a-0864cb7b02c7 IP 1.1.1.1 33bd535b-fa1c-41e2-a6f9-80d82dd29a9b
Configuration parameters
base_url— Base URL (required)credentials— API Key (leave empty. Fill in the API key in the password field.)indicator_types— Indicator types to fetch (required)max_indicator_to_fetch— Max indicators per fetchfeed— Fetch indicatorsfeedReputation— Indicator ReputationfeedReliability— Source Reliability (required)tlp_color— Traffic Light Protocol ColorfeedExpirationPolicy—feedExpirationInterval—feedFetchInterval— Feed Fetch IntervalfeedTags— TagsfeedBypassExclusionList— Bypass exclusion listinsecure— Trust any certificate (not secure)proxy— Use system proxy settingsscore_start— Score minimum valuescore_end— Score maximum value
Commands (2)
-
opencti-get-indicatorsGets indicators from the feed.
-
opencti-reset-fetch-indicatorsWARNING: This command will reset your fetch history.
from typing import Any import demistomock as demisto # noqa: F401 import urllib3 from CommonServerPython import * # noqa: F401 from pycti import OpenCTIApiClient # Disable insecure warnings urllib3.disable_warnings() # Disable info logging from the api logging.getLogger().setLevel(logging.ERROR) OPENCTI_LOGS = "opencti_logs" XSOAR_TYPES_TO_OPENCTI = { "account": "User-Account", "domain": "Domain-Name", "email": "Email-Addr", "file-md5": "StixFile", "file-sha1": "StixFile", "file-sha256": "StixFile", "file": "StixFile", "host": "X-OpenCTI-Hostname", "ip": "IPv4-Addr", "ipv6": "IPv6-Addr", "registry key": "Windows-Registry-Key", "url": "Url", } OPENCTI_TYPES_TO_XSOAR = { "User-Account": "Account", "Domain-Name": "Domain", "Email-Addr": "Email", "StixFile": "File", "X-OpenCTI-Hostname": "Host", "IPv4-Addr": "IP", "IPv6-Addr": "IPv6", "Windows-Registry-Key": "Registry Key", "Url": "URL", } def build_indicator_list(indicator_list: list[str]) -> list[str]: """Builds an indicator list for the query Args: indicator_list: List of XSOAR indicators types to return.. Returns: indicators: list of OPENCTI indicators types""" result = [] if "ALL" in indicator_list: # Replaces "ALL" for all types supported on XSOAR. result = [ "User-Account", "Domain-Name", "Email-Addr", "StixFile", "X-OpenCTI-Hostname", "IPv4-Addr", "IPv6-Addr", "Windows-Registry-Key", "Url", ] else: result = [XSOAR_TYPES_TO_OPENCTI.get(indicator.lower(), indicator) for indicator in indicator_list] return result def reset_last_run(): """ Reset the last run from the integration context """ demisto.setIntegrationContext({}) return CommandResults(readable_output="Fetch history deleted successfully") def get_indicators( client: OpenCTIApiClient, indicator_types: list[str], score: list[str] = None, limit: int | None = 500, last_run_id: str | None = None, tlp_color: str | None = None, tags: list[str] = None, ) -> tuple[str, list]: """Retrieving indicators from the API Args: score: Range of scores to filter by. client: OpenCTI Client object. indicator_types: List of indicators types to return. last_run_id: The last id from the previous call to use pagination. limit: the max indicators to fetch tlp_color: traffic Light Protocol color tags: user tags Returns: new_last_run: the id of the last indicator indicators: list of indicators """ indicator_type = build_indicator_list(indicator_types) demisto.debug(f"{OPENCTI_LOGS} - in get_indicators - builded indicator type : {indicator_type}") filters: dict[str, Any] = { "mode": "and", "filters": [{"key": "entity_type", "values": indicator_type, "operator": "eq", "mode": "or"}], "filterGroups": [], } if score: filters["filters"].append({"key": "x_opencti_score", "values": score, "operator": "eq", "mode": "or"}) demisto.debug(f"{OPENCTI_LOGS} - in get_indicators - {filters=}") observables = client.stix_cyber_observable.list(filters=filters, after=last_run_id, first=limit, withPagination=True) new_last_run = observables.get("pagination").get("endCursor") demisto.debug(f"{OPENCTI_LOGS} - in get_indicators - {new_last_run=}") indicators = [] for item in observables.get("entities"): indicator = { "value": item["observable_value"], "type": OPENCTI_TYPES_TO_XSOAR.get(item["entity_type"], item["entity_type"]), "rawJSON": item, "fields": { "tags": [tag.get("value") for tag in item.get("objectLabel")], "description": item.get("x_opencti_description"), }, } if tags: indicator["fields"]["tags"] += tags if not tlp_color: if object_marking := item.get("objectMarking", []): new_tlp_color = object_marking[0].get("definition", "").split(":") indicator["fields"]["trafficlightprotocol"] = new_tlp_color[1] else: indicator["fields"]["trafficlightprotocol"] = tlp_color score = item.get("x_opencti_score") if score in [*range(21)]: indicator["score"] = 1 elif score in [*range(21, 71)]: indicator["score"] = 2 elif score in [*range(71, 101)]: indicator["score"] = 3 indicators.append(indicator) demisto.debug(f"{OPENCTI_LOGS} - in get_indicators - sum of indicators: {len(indicators)}") return new_last_run, indicators def fetch_indicators_command( client: OpenCTIApiClient, indicator_types: list, max_fetch: int, score: list = None, tlp_color=None, tags=None, is_test=False ) -> list: """fetch indicators from the OpenCTI Args: score: Range of scores to filter by. client: OpenCTI Client object indicator_types(list): List of indicators types to get. max_fetch: (int) max indicators to fetch. tlp_color: (str) tags: (list) is_test: (bool) Indicates that it's a test and then does not save the last run. Returns: list of indicators(list) """ last_run_id = demisto.getIntegrationContext().get("last_run_id") demisto.info(f"{OPENCTI_LOGS} - in fetch_indicators_command - get last run = {last_run_id}") new_last_run, indicators_list = get_indicators( client, indicator_types, limit=max_fetch, last_run_id=last_run_id, tlp_color=tlp_color, score=score, tags=tags ) if new_last_run and not is_test: demisto.setIntegrationContext({"last_run_id": new_last_run}) demisto.debug(f"{OPENCTI_LOGS} - in fetch_indicators_command - set last run = {new_last_run}") # we submit the indicators in batches for b in batch(indicators_list, batch_size=2000): demisto.createIndicators(b) demisto.debug(f"{OPENCTI_LOGS} - in fetch_indicators_command - indicators created successfully.") return indicators_list def get_indicators_command(client: OpenCTIApiClient, args: dict) -> CommandResults: """Gets indicator from opencti to readable output Args: client: OpenCTI Client object args: demisto.args() Returns: readable_output, raw_response """ indicator_types = argToList(args.get("indicator_types")) last_run_id = args.get("last_run_id") limit = arg_to_number(args.get("limit", 50)) start = arg_to_number(args.get("score_start", 1)) end = arg_to_number(args.get("score_end", 100)) + 1 # type:ignore demisto.debug(f"{OPENCTI_LOGS} - in get_indicators_command - {indicator_types=} {last_run_id=} {limit=} {start=} {end=}") score = None if start or end: score = [str(i) for i in range(start, end)] # type:ignore demisto.debug(f"{OPENCTI_LOGS} - in get_indicators_command -{score=}") last_run_id, indicators_list = get_indicators( client=client, indicator_types=indicator_types, limit=limit, last_run_id=last_run_id, score=score ) if indicators_list: indicators = [ { "type": indicator["type"], "value": indicator["value"], "id": indicator["rawJSON"]["id"], "rawJSON": indicator["rawJSON"], } for indicator in indicators_list ] readable_output = tableToMarkdown("Indicators", indicators, headers=["type", "value", "id"], removeNull=True) return CommandResults(readable_output=readable_output, raw_response=indicators_list) else: return CommandResults(readable_output="No indicators") def main(): params = demisto.params() args = demisto.args() credentials = params.get("credentials", {}) api_key = credentials.get("password") base_url = params.get("base_url").strip("/") indicator_types = params.get("indicator_types", ["ALL"]) max_fetch = params.get("max_indicator_to_fetch") tlp_color = params.get("tlp_color") tags = argToList(params.get("feedTags")) if max_fetch: max_fetch = arg_to_number(max_fetch) else: max_fetch = 500 start = arg_to_number(params.get("score_start", 1)) end = arg_to_number(params.get("score_end", 100)) + 1 # type:ignore score = None if start or end: score = [str(i) for i in range(start, end)] # type:ignore try: client = OpenCTIApiClient(base_url, api_key, ssl_verify=params.get("insecure"), log_level="error", proxies=handle_proxy()) command = demisto.command() demisto.info(f"Command being called is {command}") # Switch case if command == "fetch-indicators": fetch_indicators_command(client, indicator_types, max_fetch, tlp_color=tlp_color, score=score, tags=tags) elif command == "test-module": """When setting up an OpenCTI Client it is checked that it is valid and allows requests to be sent. and if not he immediately sends an error""" fetch_indicators_command(client, indicator_types, max_fetch, is_test=True) return_results("ok") elif command == "opencti-get-indicators": return_results(get_indicators_command(client, args)) elif command == "opencti-reset-fetch-indicators": return_results(reset_last_run()) except Exception as e: demisto.error(traceback.format_exc()) # print the traceback return_error(f"Error:\n [{e}]") if __name__ in ("__main__", "__builtin__", "builtins"): main()