@cryptotaxi247 / CoPilot / commits / d0a448bd

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": {