From 3d8e8da1575e6c3f9b1159ff31cbbc217984fc49 Mon Sep 17 00:00:00 2001 From: dadokkio Date: Fri, 22 Jan 2021 15:00:53 +0100 Subject: [PATCH 1/3] Add CheckPoint Responder --- .../CheckPoint/CheckPoint_Gaia_lock.json | 44 ++++++ .../CheckPoint/CheckPoint_Gaia_unlock.json | 44 ++++++ responders/CheckPoint/README.md | 22 +++ responders/CheckPoint/checkpoint.py | 145 ++++++++++++++++++ responders/CheckPoint/requirements.txt | 2 + 5 files changed, 257 insertions(+) create mode 100644 responders/CheckPoint/CheckPoint_Gaia_lock.json create mode 100644 responders/CheckPoint/CheckPoint_Gaia_unlock.json create mode 100644 responders/CheckPoint/README.md create mode 100755 responders/CheckPoint/checkpoint.py create mode 100644 responders/CheckPoint/requirements.txt diff --git a/responders/CheckPoint/CheckPoint_Gaia_lock.json b/responders/CheckPoint/CheckPoint_Gaia_lock.json new file mode 100644 index 000000000..024fb1083 --- /dev/null +++ b/responders/CheckPoint/CheckPoint_Gaia_lock.json @@ -0,0 +1,44 @@ +{ + "name": "CheckPoint Lock", + "version": "1.0", + "author": "@dadokkio LDO-CERT", + "url": "https://github.com/TheHive-Project/Cortex-Analyzers", + "license": "AGPL-V3", + "description": "Lock ip on CheckPoint Gaia", + "dataTypeList": ["thehive:case_artifact"], + "command": "CheckPoint/checkpoint.py", + "baseConfig": "CheckPoint", + "config": { + "service": "lock" + }, + "configurationItems": [ + { + "name": "server", + "description": "Checkpoint API server", + "type": "string", + "multi": false, + "required": true + }, + { + "name": "username", + "description": "CheckPoint username", + "type": "string", + "multi": false, + "required": true + }, + { + "name": "password", + "description": "CheckPoint password", + "type": "string", + "multi": false, + "required": true + }, + { + "name": "group_name", + "description": "CheckPoint group name ip will be added/removed from", + "type": "string", + "multi": false, + "required": true + } + ] +} \ No newline at end of file diff --git a/responders/CheckPoint/CheckPoint_Gaia_unlock.json b/responders/CheckPoint/CheckPoint_Gaia_unlock.json new file mode 100644 index 000000000..9dba20506 --- /dev/null +++ b/responders/CheckPoint/CheckPoint_Gaia_unlock.json @@ -0,0 +1,44 @@ +{ + "name": "CheckPoint Unlock", + "version": "1.0", + "author": "@dadokkio LDO-CERT", + "url": "https://github.com/TheHive-Project/Cortex-Analyzers", + "license": "AGPL-V3", + "description": "Unlock ip on CheckPoint Gaia", + "dataTypeList": ["thehive:case_artifact"], + "command": "CheckPoint/checkpoint.py", + "baseConfig": "CheckPoint", + "config": { + "service": "unlock" + }, + "configurationItems": [ + { + "name": "server", + "description": "Checkpoint API server", + "type": "string", + "multi": false, + "required": true + }, + { + "name": "username", + "description": "CheckPoint username", + "type": "string", + "multi": false, + "required": true + }, + { + "name": "password", + "description": "CheckPoint password", + "type": "string", + "multi": false, + "required": true + }, + { + "name": "group_name", + "description": "CheckPoint group name ip will be added/removed from", + "type": "string", + "multi": false, + "required": true + } + ] +} \ No newline at end of file diff --git a/responders/CheckPoint/README.md b/responders/CheckPoint/README.md new file mode 100644 index 000000000..cb9435c79 --- /dev/null +++ b/responders/CheckPoint/README.md @@ -0,0 +1,22 @@ +### CkeckPoint + +This responder permits you to add/remove selected observable from a specific group. + +Some notes: + + - API must permit access from cortex machine. + + - First login from API must be manual because it needs fingerprint acceptance. This will generate a fingerprints.txt file that must be placed near to the analyzer python file. + + - It doesn't work in dockerized analyzer! + + - If group doesn't exists it'll be created [when blocking]. At the moment without any default rule. + + +#### Requirements +The following options are required in CheckPoint Responder configuration: + +- `server` : URL of CheckPoint instance +- `username`: user accessing CheckPoint instance +- `password`: password for the user accessing CheckPoint instance +- `group_name`: name of the group ip will be added to or removed diff --git a/responders/CheckPoint/checkpoint.py b/responders/CheckPoint/checkpoint.py new file mode 100755 index 000000000..ef902e31b --- /dev/null +++ b/responders/CheckPoint/checkpoint.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python3 +# encoding: utf-8 +import os +import json +from cortexutils.responder import Responder +from cpapi import APIClient, APIClientArgs + + +class CheckPoint(Responder): + def __init__(self): + Responder.__init__(self) + # Mail settings + server = self.get_param("config.server", None, "Missing server in config") + self.username = self.get_param( + "config.username", None, "Missing username in config" + ) + self.password = self.get_param( + "config.password", None, "Missing password in config" + ) + try: + fingerprint_path = "{}/fingerprints.txt".format(os.path.dirname(__file__)) + fingerprint = json.loads(open(fingerprint_path, "r").read())[server] + self.client_args = APIClientArgs(server=server, fingerprint=fingerprint) + except: + self.error( + "Fingerprint check failed. It should be locate here {}".format( + fingerprint_path + ) + ) + + self.service = self.get_param("config.service", None) + self.group_name = self.get_param( + "config.group_name", None, "Missing group_name in config" + ) + + def run(self): + Responder.run(self) + + data = self.get_param("data.data") + + return_dict = {} + + with APIClient(self.client_args) as client: + login = client.login(self.username, self.password) + + if not login.success: + self.error("Login failed!") + + if self.service == "lock": + + # Check if group exists + get_group_response = client.api_call( + "show-group", {"name": self.group_name} + ) + + if not get_group_response.success: + # if no create it + add_group_response = client.api_call( + "add-group", {"name": self.group_name} + ) + + if not add_group_response.success: + self.error( + "Error during group creation: {}".format( + add_group_response.error_message + ) + ) + else: + client.api_call("publish", {}) + return_dict["group_created"] = True + else: + return_dict["group_created"] = False + + # Check if host exists + get_host_response = client.api_call("show-host", {"name": data}) + + if not get_host_response.success: + return_dict["host_created"] = True + + # Create host from ip + add_host_response = client.api_call( + "add-host", + { + "name": data, + "ip-address": data, + "comments": "From TheHive responder", + }, + ) + + if not add_host_response.success: + self.error( + "Error during host creation: {}".format( + add_host_response.error_message + ) + ) + else: + client.api_call("publish", {}) + return_dict["host_created"] = False + + # Add observable to group + response = client.api_call( + "set-group", + {"name": self.group_name, "members": {"add": data}}, + ) + + if not response.success: + self.error( + "Error adding host to group: {}".format(response.error_message) + ) + else: + # COMMIT CHANGES + client.api_call("publish", {}) + return_dict["Success"] = True + + elif self.service == "unlock": + # Check if host exists + get_host_response = client.api_call("show-host", {"name": data}) + + if not get_host_response.success: + self.error( + "Host doen't exists: {}".format(get_host_response.error_message) + ) + + # Remove observable from group + response = client.api_call( + "set-group", + {"name": self.group_name, "members": {"remove": data}}, + ) + + if not response.success: + self.error( + "Error removing host from group: {}".format( + response.error_message + ) + ) + else: + # COMMIT CHANGES + client.api_call("publish", {}) + return_dict["Success"] = True + + self.report({"message": return_dict}) + + +if __name__ == "__main__": + CheckPoint().run() diff --git a/responders/CheckPoint/requirements.txt b/responders/CheckPoint/requirements.txt new file mode 100644 index 000000000..5cc83284d --- /dev/null +++ b/responders/CheckPoint/requirements.txt @@ -0,0 +1,2 @@ +cortexutils +-e git+https://github.com/CheckPointSW/cp_mgmt_api_python_sdk#egg=cpapi cpapi From 454a26c1dc7d6f29ebb790db7637bb4bbd4677af Mon Sep 17 00:00:00 2001 From: dadokkio Date: Mon, 25 Jan 2021 12:07:03 +0100 Subject: [PATCH 2/3] add exclusion list to avoid lock/unlock ip or subnets --- .../CheckPoint/CheckPoint_Gaia_lock.json | 7 +++++++ .../CheckPoint/CheckPoint_Gaia_unlock.json | 7 +++++++ responders/CheckPoint/checkpoint.py | 21 +++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/responders/CheckPoint/CheckPoint_Gaia_lock.json b/responders/CheckPoint/CheckPoint_Gaia_lock.json index 024fb1083..5c6125e68 100644 --- a/responders/CheckPoint/CheckPoint_Gaia_lock.json +++ b/responders/CheckPoint/CheckPoint_Gaia_lock.json @@ -39,6 +39,13 @@ "type": "string", "multi": false, "required": true + }, + { + "name": "exclusions", + "description": "ip/subnet that cannot be locked or unlocked", + "type": "string", + "multi": true, + "required": false } ] } \ No newline at end of file diff --git a/responders/CheckPoint/CheckPoint_Gaia_unlock.json b/responders/CheckPoint/CheckPoint_Gaia_unlock.json index 9dba20506..80662ce4c 100644 --- a/responders/CheckPoint/CheckPoint_Gaia_unlock.json +++ b/responders/CheckPoint/CheckPoint_Gaia_unlock.json @@ -39,6 +39,13 @@ "type": "string", "multi": false, "required": true + }, + { + "name": "exclusions", + "description": "ip/subnet that cannot be locked or unlocked", + "type": "string", + "multi": true, + "required": false } ] } \ No newline at end of file diff --git a/responders/CheckPoint/checkpoint.py b/responders/CheckPoint/checkpoint.py index ef902e31b..948eb4e62 100755 --- a/responders/CheckPoint/checkpoint.py +++ b/responders/CheckPoint/checkpoint.py @@ -2,6 +2,7 @@ # encoding: utf-8 import os import json +import ipaddress from cortexutils.responder import Responder from cpapi import APIClient, APIClientArgs @@ -32,11 +33,31 @@ def __init__(self): self.group_name = self.get_param( "config.group_name", None, "Missing group_name in config" ) + self.exclusions = self.get_param("config.exclusions", []) def run(self): Responder.run(self) data = self.get_param("data.data") + try: + data = ipaddress.ip_address(data) + except ValueError: + self.error("{} is not a valid ip".format(data)) + + for excl in self.exclusions: + try: + excl = ipaddress.ip_address(excl) + if data == excl: + self.error("{} in exclusions".format(data)) + except ValueError: + try: + excl = ipaddress.ip_network(excl) + if data in excl: + self.error("{} in exclusions".format(data)) + except ValueError: + continue + + data = str(data) return_dict = {} From aa5d7a4ee05ae01fa517d079fbfc8d6fec1d0abe Mon Sep 17 00:00:00 2001 From: dadokkio Date: Wed, 27 Jan 2021 17:20:43 +0100 Subject: [PATCH 3/3] add tags --- responders/CheckPoint/CheckPoint_Gaia_lock.json | 14 ++++++++++++++ responders/CheckPoint/CheckPoint_Gaia_unlock.json | 14 ++++++++++++++ responders/CheckPoint/checkpoint.py | 8 ++++++++ 3 files changed, 36 insertions(+) diff --git a/responders/CheckPoint/CheckPoint_Gaia_lock.json b/responders/CheckPoint/CheckPoint_Gaia_lock.json index 5c6125e68..6951efd7b 100644 --- a/responders/CheckPoint/CheckPoint_Gaia_lock.json +++ b/responders/CheckPoint/CheckPoint_Gaia_lock.json @@ -46,6 +46,20 @@ "type": "string", "multi": true, "required": false + }, + { + "name": "added_tag", + "description": "Tag added to observable when adding to FW", + "type": "string", + "multi": false, + "required": false + }, + { + "name": "removed_tag", + "description": "Tag added to observable when removing from FW", + "type": "string", + "multi": false, + "required": false } ] } \ No newline at end of file diff --git a/responders/CheckPoint/CheckPoint_Gaia_unlock.json b/responders/CheckPoint/CheckPoint_Gaia_unlock.json index 80662ce4c..c313c7a23 100644 --- a/responders/CheckPoint/CheckPoint_Gaia_unlock.json +++ b/responders/CheckPoint/CheckPoint_Gaia_unlock.json @@ -46,6 +46,20 @@ "type": "string", "multi": true, "required": false + }, + { + "name": "added_tag", + "description": "Tag added to observable when adding to FW", + "type": "string", + "multi": false, + "required": false + }, + { + "name": "removed_tag", + "description": "Tag added to observable when removing from FW", + "type": "string", + "multi": false, + "required": false } ] } \ No newline at end of file diff --git a/responders/CheckPoint/checkpoint.py b/responders/CheckPoint/checkpoint.py index 948eb4e62..5489fcb9a 100755 --- a/responders/CheckPoint/checkpoint.py +++ b/responders/CheckPoint/checkpoint.py @@ -34,6 +34,8 @@ def __init__(self): "config.group_name", None, "Missing group_name in config" ) self.exclusions = self.get_param("config.exclusions", []) + self.added_tag = self.get_param("config.added_tag", None) + self.removed_tag = self.get_param("config.removed_tag", None) def run(self): Responder.run(self) @@ -161,6 +163,12 @@ def run(self): self.report({"message": return_dict}) + def operations(self, raw): + if self.service == "lock" and self.added_tag: + return [self.build_operation("AddTagToArtifact", tag=self.added_tag)] + elif self.service == "unlock" and self.removed_tag: + return [self.build_operation("AddTagToArtifact", tag=self.removed_tag)] + if __name__ == "__main__": CheckPoint().run()