socfortress threat intel added (#48)
* socfortress threat intel added * precommit
taylor_socfortress committed
Jul 18, 2023 at 08:20 UTC
d0a448bde2150a72719bff29627823ee07fd2f0a
6 files changed
+290
backend/app/__init__.py
+2
@@ -56,6 +56,7 @@ from app.routes.rules import bp as rules_bp
56
from app.routes.shuffle import bp as shuffle_bp
57
from app.routes.smtp import bp as smtp_bp
58
from app.routes.sublime import bp as sublime_bp
59
+from app.routes.threatintel import bp as threatintel_bp
60
from app.routes.velociraptor import bp as velociraptor_bp
61
from app.routes.wazuhindexer import bp as wazuhindexer_bp
62
@@ -72,3 +73,4 @@ app.register_blueprint(sublime_bp) # Register the sublime blueprint
73
app.register_blueprint(influxdb_bp) # Register the influxdb blueprint
74
app.register_blueprint(smtp_bp) # Register the smtp blueprint
75
app.register_blueprint(healthchecks_bp) # Register the healthchecks blueprint
76
+app.register_blueprint(threatintel_bp) # Register the threatintel blueprint
backend/app/models/connectors.py
+55
@@ -479,6 +479,60 @@ class AskSOCFortressConnector(Connector):
479
return {"connectionSuccessful": False, "response": None}
480
481
482
+class SocfortressThreatIntelConnector(Connector):
483
+ """
484
+ A connector for the SocfortressThreatIntel service, a subclass of Connector.
485
+
486
+ Args:
487
+ connector_name (str): The name of the connector.
488
+ """
489
+
490
+ def __init__(self, connector_name: str):
491
+ super().__init__(attributes=self.get_connector_info_from_db(connector_name))
492
+
493
+ def verify_connection(self) -> Dict[str, Any]:
494
+ """
495
+ Verifies the connection to ASK SOCFortress service.
496
+
497
+ Returns:
498
+ dict: A dictionary containing 'connectionSuccessful' status and 'response' if the connection is successful.
499
+ """
500
+ logger.info(
501
+ f"Verifying the ASK SOCFortress connection to {self.attributes['connector_url']}",
502
+ )
503
+ try:
504
+ headers = {
505
+ "Content-Type": "application/json",
506
+ "x-api-key": f"{self.attributes['connector_api_key']}",
507
+ "module-version": "1.0",
508
+ }
509
+ params = {
510
+ "value": "evil.socfortress.co",
511
+ }
512
+ socfortress_threat_intel = requests.get(
513
+ f"{self.attributes['connector_url']}",
514
+ headers=headers,
515
+ params=params,
516
+ verify=False,
517
+ timeout=60,
518
+ )
519
+ if socfortress_threat_intel.status_code == 200:
520
+ logger.info(
521
+ f"Connection to {self.attributes['connector_url']} successful",
522
+ )
523
+ return {"connectionSuccessful": True}
524
+ else:
525
+ logger.error(
526
+ f"Connection to {self.attributes['connector_url']} failed with error: {socfortress_threat_intel.text}",
527
+ )
528
+ return {"connectionSuccessful": False, "response": None}
529
+ except Exception as e:
530
+ logger.error(
531
+ f"Connection to {self.attributes['connector_url']} failed with error: {e}",
532
+ )
533
+ return {"connectionSuccessful": False, "response": None}
534
+
535
+
536
class InfluxDBConnector(Connector):
537
"""
538
A connector for the InfluxDB service, a subclass of Connector.
@@ -633,3 +687,4 @@ connector_factory.register_creator("Shuffle", "ShuffleConnector")
687
connector_factory.register_creator("Sublime", "SublimeConnector")
688
connector_factory.register_creator("InfluxDB", "InfluxDBConnector")
689
connector_factory.register_creator("AskSocfortress", "AskSOCFortressConnector")
690
+connector_factory.register_creator("SocfortressThreatIntel", "SocfortressThreatIntelConnector")
backend/app/models/models.py
+1
@@ -111,6 +111,7 @@ class Connectors(db.Model):
111
"sublime": True,
112
"influxdb": True,
113
"asksocfortress": True,
114
+ "socfortressthreatintel": True,
115
}
116
117
def __init__(
backend/app/routes/threatintel.py
new
+22
@@ -0,0 +1,22 @@
1
+from flask import Blueprint
2
+from flask import jsonify
3
+from loguru import logger
4
+
5
+from app.services.threat_intel.socfortress.universal import (
6
+ SocfortressThreatIntelService,
7
+)
8
+
9
+bp = Blueprint("threatintel", __name__)
10
+
11
+
12
+@bp.route("/threatintel/socfortress/<ioc_value>", methods=["GET"])
13
+def get_socfortress_threatintel(ioc_value: str) -> jsonify:
14
+ """
15
+ Endpoint to check IoC in Socfortress Threat Intel.
16
+
17
+ Returns:
18
+ jsonify: A JSON response containing the list of all alerts from Socfortress.
19
+ """
20
+ logger.info("Received request to check IoC in Socfortress Threat Intel")
21
+ ioc_enriched = SocfortressThreatIntelService("SocfortressThreatIntel").invoke_socfortress_threat_intel(data=ioc_value)
22
+ return jsonify(ioc_enriched)
backend/app/services/threat_intel/socfortress/universal.py
new
+152
@@ -0,0 +1,152 @@
1
+from typing import Any
2
+from typing import Dict
3
+from typing import Optional
4
+from typing import Tuple
5
+
6
+import requests
7
+from loguru import logger
8
+
9
+from app.models.connectors import Connector
10
+from app.models.connectors import connector_factory
11
+
12
+
13
+class SocfortressThreatIntelService:
14
+ """
15
+ A service class that encapsulates the logic for interfacing with ASK SOCFortress. This class handles tasks like retrieving connector
16
+ details, and invoking the ask_socfortress connector.
17
+ """
18
+
19
+ def __init__(self, connector_name: str) -> None:
20
+ """
21
+ Initializes the SocfortressThreatIntelService by collecting SOCFortress Threat Intel details associated with the specified
22
+ connector name.
23
+
24
+ Args:
25
+ connector_name (str): The name of the SOCFortress Threat Intel connector.
26
+ """
27
+ self.connector_url, self.connector_api_key = self.collect_socfortress_threat_intel_details(
28
+ connector_name,
29
+ )
30
+
31
+ def collect_socfortress_threat_intel_details(
32
+ self,
33
+ connector_name: str,
34
+ ) -> Tuple[Optional[str], Optional[str]]:
35
+ """
36
+ Collects the details of the SOCFortress Threat Intel connector.
37
+
38
+ Args:
39
+ connector_name (str): The name of the SOCFortress Threat Intel connector.
40
+
41
+ Returns:
42
+ tuple: A tuple containing the connection URL and API key. If the connection is not successful, both elements of the tuple are
43
+ None.
44
+ """
45
+ connector_instance = connector_factory.create(connector_name, connector_name)
46
+ connection_successful = connector_instance.verify_connection()
47
+ if connection_successful:
48
+ connection_details = Connector.get_connector_info_from_db(connector_name)
49
+ return (
50
+ connection_details.get("connector_url"),
51
+ connection_details.get("connector_api_key"),
52
+ )
53
+ else:
54
+ return None, None
55
+
56
+ def create_payload(self, data: str) -> Dict[str, Any]:
57
+ """
58
+ Creates the payload for the SOCFortress Threat Intel API request.
59
+
60
+ Args:
61
+ data (str): The data to be enriched.
62
+
63
+ Returns:
64
+ dict: The payload to be sent to the SOCFortress Threat Intel API.
65
+ """
66
+ return {"value": data}
67
+
68
+ def create_headers(self) -> Dict[str, str]:
69
+ """
70
+ Creates the headers for the SOCFortress Threat Intel API request.
71
+
72
+ Returns:
73
+ dict: The headers to be used for the SOCFortress Threat Intel API request.
74
+ """
75
+ return {
76
+ "Content-Type": "application/json",
77
+ "x-api-key": self.connector_api_key,
78
+ "module-version": "1.0",
79
+ }
80
+
81
+ def make_request(self, payload: Dict[str, Any], headers: Dict[str, str]) -> requests.Response:
82
+ """
83
+ Makes the HTTP request to the SOCFortress Threat Intel API.
84
+
85
+ Args:
86
+ payload (dict): The payload to be sent to the SOCFortress Threat Intel API.
87
+ headers (dict): The headers to be used for the SOCFortress Threat Intel API request.
88
+
89
+ Returns:
90
+ requests.Response: The HTTP response from the SOCFortress Threat Intel API.
91
+ """
92
+ return requests.get(
93
+ self.connector_url,
94
+ params=payload,
95
+ headers=headers,
96
+ timeout=120,
97
+ )
98
+
99
+ def handle_response(self, response: requests.Response) -> Dict[str, Any]:
100
+ """
101
+ Handles the response from the SOCFortress Threat Intel API.
102
+
103
+ Args:
104
+ response (requests.Response): The HTTP response from the SOCFortress Threat Intel API.
105
+
106
+ Returns:
107
+ dict: A dictionary containing a success key indicating the success or failure of the connection,
108
+ a response key containing the response from the SOCFortress Threat Intel API (if successful), and
109
+ a message key containing further information about the connection result.
110
+ """
111
+ try:
112
+ response.raise_for_status()
113
+ response_data = response.json()
114
+ return {
115
+ "success": True,
116
+ "response": response_data["data"],
117
+ "message": "Successfully invoked SOCFortress Threat Intel API",
118
+ }
119
+ except requests.exceptions.HTTPError as e:
120
+ logger.error(f"Value not found in SOCFortress Threat Intel API: {e}")
121
+ return {
122
+ "success": True,
123
+ "response": None,
124
+ "message": "Value not found in SOCFortress Threat Intel API",
125
+ }
126
+ except Exception as e:
127
+ logger.error(f"Unable to invoke SOCFortress Threat Intel API: {e}")
128
+ return {
129
+ "success": False,
130
+ "response": None,
131
+ "message": f"Unable to invoke SOCFortress Threat Intel API: {e}",
132
+ }
133
+
134
+ def invoke_socfortress_threat_intel(self, data: str) -> Dict[str, Any]:
135
+ """
136
+ Invokes the SOCFortress Threat Intel API to enrich data via a POST request.
137
+
138
+ The function creates the payload and headers, makes the HTTP request, and handles the response.
139
+
140
+ Args:
141
+ data (str): The data to be enriched.
142
+
143
+ Returns:
144
+ dict: A dictionary containing a success key indicating the success or failure of the connection,
145
+ a response key containing the response from the SOCFortress Threat Intel API (if successful), and
146
+ a message key containing further information about the connection result.
147
+ """
148
+ logger.info(f"Invoking SOCFortress Threat Intel API with data: {data}")
149
+ payload = self.create_payload(data)
150
+ headers = self.create_headers()
151
+ response = self.make_request(payload, headers)
152
+ return self.handle_response(response)
backend/app/static/swagger.json
+58
@@ -105,6 +105,14 @@
105
"description": "Find out more",
106
"url": "http://swagger.io"
107
}
108
+ },
109
+ {
110
+ "name": "Threat Intel",
111
+ "description": "Everything about Threat Intel",
112
+ "externalDocs": {
113
+ "description": "Find out more",
114
+ "url": "http://swagger.io"
115
+ }
116
}
117
],
118
"paths": {
@@ -3117,6 +3125,56 @@
3125
"operationId": "getVelociraptorAgentHealthcheckByAgentID",
3126
"tags": ["Healthcheck"]
3127
}
3128
+ },
3129
+ "/threatintel/socfortress/{ioc_value}": {
3130
+ "get": {
3131
+ "summary": "Get SOC Fortress threat intelligence by IOC value",
3132
+ "description": "Endpoint to get SOC Fortress threat intelligence by IOC value.",
3133
+ "parameters": [
3134
+ {
3135
+ "name": "ioc_value",
3136
+ "in": "path",
3137
+ "description": "The IOC value.",
3138
+ "required": true,
3139
+ "schema": {
3140
+ "type": "string"
3141
+ }
3142
+ }
3143
+ ],
3144
+ "responses": {
3145
+ "200": {
3146
+ "description": "Successful operation",
3147
+ "content": {
3148
+ "application/json": {
3149
+ "schema": {
3150
+ "type": "object",
3151
+ "properties": {
3152
+ "threat_intel": {
3153
+ "type": "array",
3154
+ "items": {
3155
+ "type": "object",
3156
+ "description": "Threat intelligence details"
3157
+ }
3158
+ }
3159
+ }
3160
+ }
3161
+ }
3162
+ }
3163
+ },
3164
+ "default": {
3165
+ "description": "Unexpected error",
3166
+ "content": {
3167
+ "application/json": {
3168
+ "schema": {
3169
+ "$ref": "#/components/schemas/Error"
3170
+ }
3171
+ }
3172
+ }
3173
+ }
3174
+ },
3175
+ "operationId": "getSOCFortressThreatIntelByIOCValue",
3176
+ "tags": ["Threat Intel"]
3177
+ }
3178
}
3179
},
3180
"components": {