From 351d42ca6290f70520aea9b745bfd18083e6ee6f Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Fri, 4 Oct 2024 13:41:51 +0000 Subject: [PATCH 01/10] BoefjeResources now only create their module when they are not a docker-boefje --- boefjes/boefjes/plugins/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boefjes/boefjes/plugins/models.py b/boefjes/boefjes/plugins/models.py index af08e385971..2dbf65a2800 100644 --- a/boefjes/boefjes/plugins/models.py +++ b/boefjes/boefjes/plugins/models.py @@ -64,7 +64,7 @@ def __init__(self, path: Path, package: str): self.boefje.produces = self.boefje.produces.union(set(_default_mime_types(self.boefje))) self.module: Runnable | None = None - if (path / ENTRYPOINT_BOEFJES).exists(): + if (path / ENTRYPOINT_BOEFJES).exists() and self.boefje.oci_image is None: self.module = get_runnable_module_from_package(package, ENTRYPOINT_BOEFJES, parameter_count=1) if (path / SCHEMA_FILE).exists(): From 65300372c14dfa7306e3114d204cf1980c1408f2 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Mon, 7 Oct 2024 08:10:34 +0000 Subject: [PATCH 02/10] Check if boefje is a docker-boefje first and then if path exists As suggested by https://github.com/minvws/nl-kat-coordination/pull/3621/commits/351d42ca6290f70520aea9b745bfd18083e6ee6f#r1789720949 --- boefjes/boefjes/plugins/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boefjes/boefjes/plugins/models.py b/boefjes/boefjes/plugins/models.py index 2dbf65a2800..b468124a6ff 100644 --- a/boefjes/boefjes/plugins/models.py +++ b/boefjes/boefjes/plugins/models.py @@ -64,7 +64,7 @@ def __init__(self, path: Path, package: str): self.boefje.produces = self.boefje.produces.union(set(_default_mime_types(self.boefje))) self.module: Runnable | None = None - if (path / ENTRYPOINT_BOEFJES).exists() and self.boefje.oci_image is None: + if self.boefje.oci_image is None and (path / ENTRYPOINT_BOEFJES).exists(): self.module = get_runnable_module_from_package(package, ENTRYPOINT_BOEFJES, parameter_count=1) if (path / SCHEMA_FILE).exists(): From 6cba8d165030853900a0ebd3fea4bb2db1d6b039 Mon Sep 17 00:00:00 2001 From: Stephanie Date: Mon, 25 Nov 2024 12:50:34 +0100 Subject: [PATCH 03/10] Update findingsDB and tweak bit for separate RDP port --- .../kat_kat_finding_types/kat_finding_types.json | 7 +++++++ .../port_classification_ip.py | 16 +++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json b/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json index a23c8d04f2f..f0b76f9c43c 100644 --- a/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json +++ b/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json @@ -132,6 +132,13 @@ "impact": "System administrator ports should only be reachable from safe and known locations to reduce attack surface.", "recommendation": "Determine if this port should be reachable from the identified location. Limit access to reduce the attack surface if necessary." }, + "KAT-REMOTE-DESKTOP-PORT": { + "description": "An open Microsoft Remote Desktop Protocol (RDP) port was detected.", + "source": "https://www.cloudflare.com/en-gb/learning/access-management/rdp-security-risks/", + "risk": "critical", + "impact":"Remote desktop ports are often the root cause in ransomware attacks, due to weak password usage, outdated software or insecure configurations.", + "recommendation": "Disable the Microsoft RDP service on port 3389 if this is publicly reachable. Add additional security layers, such as VPN access if these ports do require to be enabled to limit the attack surface." + }, "KAT-OPEN-DATABASE-PORT": { "description": "A database port is open.", "source": "https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers", diff --git a/octopoes/bits/port_classification_ip/port_classification_ip.py b/octopoes/bits/port_classification_ip/port_classification_ip.py index 7ac7fbbb4cc..47e42a4de53 100644 --- a/octopoes/bits/port_classification_ip/port_classification_ip.py +++ b/octopoes/bits/port_classification_ip/port_classification_ip.py @@ -26,7 +26,6 @@ 21, # FTP 22, # SSH 23, # Telnet - 3389, # Remote Desktop 5900, # VNC ] DB_TCP_PORTS = [ @@ -36,6 +35,9 @@ 3306, # MySQL 5432, # PostgreSQL ] +MICROSOFT_RDP_PORTS = [ + 3389, # Microsoft Remote Desktop +] def get_ports_from_config(config, config_key, default): @@ -53,6 +55,7 @@ def run(input_ooi: IPPort, additional_oois: list, config: dict[str, Any]) -> Ite common_udp_ports = get_ports_from_config(config, "common_udp_ports", COMMON_UDP_PORTS) sa_tcp_ports = get_ports_from_config(config, "sa_tcp_ports", SA_TCP_PORTS) db_tcp_ports = get_ports_from_config(config, "db_tcp_ports", DB_TCP_PORTS) + microsoft_rdp_ports = get_ports_from_config(config, "microsoft_rdp_ports", MICROSOFT_RDP_PORTS) for ip_port in additional_oois: port = ip_port.port @@ -79,6 +82,17 @@ def run(input_ooi: IPPort, additional_oois: list, config: dict[str, Any]) -> Ite ooi=ip_port.reference, description=f"Port {port}/{protocol.value} is a database port and should not be open.", ) + elif (protocol == Protocol.TCP or protocol == Protocol.UDP) and port in microsoft_rdp_ports: + open_rdp_port = KATFindingType(id="KAT-REMOTE-DESKTOP-PORT") + if aggregate_findings: + open_ports.append(ip_port.port) + else: + yield open_rdp_port + yield Finding( + finding_type=open_rdp_port.reference, + ooi=ip_port.reference, + description=f"Port {port}/{protocol.value} is a Microsoft Remote Desktop port and should not be open.", + ) elif (protocol == Protocol.TCP and port not in common_tcp_ports) or ( protocol == Protocol.UDP and port not in common_udp_ports ): From 1639424ce9b0ea2568bbe01ca1d6f9b2bdc26b14 Mon Sep 17 00:00:00 2001 From: Stephanie Date: Mon, 25 Nov 2024 12:53:18 +0100 Subject: [PATCH 04/10] Update severity --- .../plugins/kat_kat_finding_types/kat_finding_types.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json b/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json index f0b76f9c43c..a062d8f96d9 100644 --- a/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json +++ b/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json @@ -135,7 +135,7 @@ "KAT-REMOTE-DESKTOP-PORT": { "description": "An open Microsoft Remote Desktop Protocol (RDP) port was detected.", "source": "https://www.cloudflare.com/en-gb/learning/access-management/rdp-security-risks/", - "risk": "critical", + "risk": "medium", "impact":"Remote desktop ports are often the root cause in ransomware attacks, due to weak password usage, outdated software or insecure configurations.", "recommendation": "Disable the Microsoft RDP service on port 3389 if this is publicly reachable. Add additional security layers, such as VPN access if these ports do require to be enabled to limit the attack surface." }, From c2fe379f22680ae0de6c1803a630745833f31180 Mon Sep 17 00:00:00 2001 From: Stephanie Date: Tue, 26 Nov 2024 09:25:07 +0100 Subject: [PATCH 05/10] Update question schema --- octopoes/bits/ask_port_specification/question_schema.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/octopoes/bits/ask_port_specification/question_schema.json b/octopoes/bits/ask_port_specification/question_schema.json index e3226c96175..13077c14c08 100644 --- a/octopoes/bits/ask_port_specification/question_schema.json +++ b/octopoes/bits/ask_port_specification/question_schema.json @@ -30,6 +30,12 @@ "pattern": "^(\\s*(,*)[0-9]+,?\\s*)*$", "default": "1433,1434,3050,3306,5432" }, + "microsoft_rdp_ports": { + "description": "Comma separated list of (Microsoft) RDP ports", + "type": "string", + "pattern": "^(\\s*(,*)[0-9]+,?\\s*)*$", + "default": "3389" + }, "aggregate_findings": { "description": "Do you want to aggregate findings into one finding of the IP? Answer with true or false.", "type": "string", From 105d91d9a8539500ce86e9715643954a95596f3b Mon Sep 17 00:00:00 2001 From: stephanie0x00 <9821756+stephanie0x00@users.noreply.github.com> Date: Tue, 26 Nov 2024 09:32:46 +0100 Subject: [PATCH 06/10] Update port_classification_ip.py update finding texts. --- .../bits/port_classification_ip/port_classification_ip.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/octopoes/bits/port_classification_ip/port_classification_ip.py b/octopoes/bits/port_classification_ip/port_classification_ip.py index 47e42a4de53..5b4c8d5ae05 100644 --- a/octopoes/bits/port_classification_ip/port_classification_ip.py +++ b/octopoes/bits/port_classification_ip/port_classification_ip.py @@ -69,7 +69,7 @@ def run(input_ooi: IPPort, additional_oois: list, config: dict[str, Any]) -> Ite yield Finding( finding_type=open_sa_port.reference, ooi=ip_port.reference, - description=f"Port {port}/{protocol.value} is a system administrator port and should not be open.", + description=f"Port {port}/{protocol.value} is a system administrator port and should possibly not be open.", ) elif protocol == Protocol.TCP and port in db_tcp_ports: ft = KATFindingType(id="KAT-OPEN-DATABASE-PORT") @@ -91,7 +91,7 @@ def run(input_ooi: IPPort, additional_oois: list, config: dict[str, Any]) -> Ite yield Finding( finding_type=open_rdp_port.reference, ooi=ip_port.reference, - description=f"Port {port}/{protocol.value} is a Microsoft Remote Desktop port and should not be open.", + description=f"Port {port}/{protocol.value} is a Microsoft Remote Desktop port and should possibly not be open.", ) elif (protocol == Protocol.TCP and port not in common_tcp_ports) or ( protocol == Protocol.UDP and port not in common_udp_ports From 6bf6118d1760e8a5b0968a49a65cc01a33439cc1 Mon Sep 17 00:00:00 2001 From: Ammar Date: Tue, 26 Nov 2024 11:59:02 +0100 Subject: [PATCH 07/10] Fixed tests and formatting --- .../plugins/kat_kat_finding_types/kat_finding_types.json | 2 +- .../bits/port_classification_ip/port_classification_ip.py | 8 +++++--- octopoes/tests/integration/test_api_connector.py | 4 ++-- octopoes/tests/test_bit_ports.py | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json b/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json index a062d8f96d9..2262f34d4be 100644 --- a/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json +++ b/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json @@ -136,7 +136,7 @@ "description": "An open Microsoft Remote Desktop Protocol (RDP) port was detected.", "source": "https://www.cloudflare.com/en-gb/learning/access-management/rdp-security-risks/", "risk": "medium", - "impact":"Remote desktop ports are often the root cause in ransomware attacks, due to weak password usage, outdated software or insecure configurations.", + "impact": "Remote desktop ports are often the root cause in ransomware attacks, due to weak password usage, outdated software or insecure configurations.", "recommendation": "Disable the Microsoft RDP service on port 3389 if this is publicly reachable. Add additional security layers, such as VPN access if these ports do require to be enabled to limit the attack surface." }, "KAT-OPEN-DATABASE-PORT": { diff --git a/octopoes/bits/port_classification_ip/port_classification_ip.py b/octopoes/bits/port_classification_ip/port_classification_ip.py index 5b4c8d5ae05..857d1f9c4fb 100644 --- a/octopoes/bits/port_classification_ip/port_classification_ip.py +++ b/octopoes/bits/port_classification_ip/port_classification_ip.py @@ -36,7 +36,7 @@ 5432, # PostgreSQL ] MICROSOFT_RDP_PORTS = [ - 3389, # Microsoft Remote Desktop + 3389 # Microsoft Remote Desktop ] @@ -69,7 +69,8 @@ def run(input_ooi: IPPort, additional_oois: list, config: dict[str, Any]) -> Ite yield Finding( finding_type=open_sa_port.reference, ooi=ip_port.reference, - description=f"Port {port}/{protocol.value} is a system administrator port and should possibly not be open.", + description=f"Port {port}/{protocol.value} is a system administrator port and " + f"should possibly not be open.", ) elif protocol == Protocol.TCP and port in db_tcp_ports: ft = KATFindingType(id="KAT-OPEN-DATABASE-PORT") @@ -91,7 +92,8 @@ def run(input_ooi: IPPort, additional_oois: list, config: dict[str, Any]) -> Ite yield Finding( finding_type=open_rdp_port.reference, ooi=ip_port.reference, - description=f"Port {port}/{protocol.value} is a Microsoft Remote Desktop port and should possibly not be open.", + description=f"Port {port}/{protocol.value} is a Microsoft Remote Desktop port and " + f"should possibly not be open.", ) elif (protocol == Protocol.TCP and port not in common_tcp_ports) or ( protocol == Protocol.UDP and port not in common_udp_ports diff --git a/octopoes/tests/integration/test_api_connector.py b/octopoes/tests/integration/test_api_connector.py index 6795ecafaf8..afce19ecfab 100644 --- a/octopoes/tests/integration/test_api_connector.py +++ b/octopoes/tests/integration/test_api_connector.py @@ -239,7 +239,7 @@ def test_no_disappearing_ports(octopoes_api_connector: OctopoesAPIConnector): assert findings.items == [ Finding( finding_type=KATFindingType(id="KAT-OPEN-DATABASE-PORT").reference, - description="Port 3306/tcp is a database port and should not be open.", + description="Port 3306/tcp is a database port and should possibly not be open.", ooi=tcp_port.reference, ) ] @@ -276,7 +276,7 @@ def test_no_disappearing_ports(octopoes_api_connector: OctopoesAPIConnector): assert findings.items == [ Finding( finding_type=KATFindingType(id="KAT-OPEN-DATABASE-PORT").reference, - description="Port 3306/tcp is a database port and should not be open.", + description="Port 3306/tcp is a database port and should possibly not be open.", ooi=tcp_port.reference, ) ] diff --git a/octopoes/tests/test_bit_ports.py b/octopoes/tests/test_bit_ports.py index 09c9a86c483..d301c23b207 100644 --- a/octopoes/tests/test_bit_ports.py +++ b/octopoes/tests/test_bit_ports.py @@ -29,7 +29,7 @@ def test_port_classification_tcp_22(): assert len(results) == 2 finding = results[-1] assert isinstance(finding, Finding) - assert finding.description == "Port 22/tcp is a system administrator port and should not be open." + assert finding.description == "Port 22/tcp is a system administrator port and should possibly not be open." def test_port_classification_tcp_5432(): @@ -40,7 +40,7 @@ def test_port_classification_tcp_5432(): assert len(results) == 2 finding = results[-1] assert isinstance(finding, Finding) - assert finding.description == "Port 5432/tcp is a database port and should not be open." + assert finding.description == "Port 5432/tcp is a database port and should possibly not be open." def test_port_classification_tcp_12345(): From 3a7c7ef7109fe66220abc24f8d081cd2751f9080 Mon Sep 17 00:00:00 2001 From: Ammar Date: Tue, 26 Nov 2024 12:04:07 +0100 Subject: [PATCH 08/10] Fixed test --- octopoes/tests/test_bit_ports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/octopoes/tests/test_bit_ports.py b/octopoes/tests/test_bit_ports.py index d301c23b207..4efbc3b065d 100644 --- a/octopoes/tests/test_bit_ports.py +++ b/octopoes/tests/test_bit_ports.py @@ -40,7 +40,7 @@ def test_port_classification_tcp_5432(): assert len(results) == 2 finding = results[-1] assert isinstance(finding, Finding) - assert finding.description == "Port 5432/tcp is a database port and should possibly not be open." + assert finding.description == "Port 5432/tcp is a database port and should not be open." def test_port_classification_tcp_12345(): From 4532b5a26a612e4b0b14d14c3fadcb3b2bd9e417 Mon Sep 17 00:00:00 2001 From: Ammar Date: Tue, 26 Nov 2024 12:04:07 +0100 Subject: [PATCH 09/10] Fixed test --- octopoes/tests/integration/test_api_connector.py | 4 ++-- octopoes/tests/test_bit_ports.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/octopoes/tests/integration/test_api_connector.py b/octopoes/tests/integration/test_api_connector.py index afce19ecfab..6795ecafaf8 100644 --- a/octopoes/tests/integration/test_api_connector.py +++ b/octopoes/tests/integration/test_api_connector.py @@ -239,7 +239,7 @@ def test_no_disappearing_ports(octopoes_api_connector: OctopoesAPIConnector): assert findings.items == [ Finding( finding_type=KATFindingType(id="KAT-OPEN-DATABASE-PORT").reference, - description="Port 3306/tcp is a database port and should possibly not be open.", + description="Port 3306/tcp is a database port and should not be open.", ooi=tcp_port.reference, ) ] @@ -276,7 +276,7 @@ def test_no_disappearing_ports(octopoes_api_connector: OctopoesAPIConnector): assert findings.items == [ Finding( finding_type=KATFindingType(id="KAT-OPEN-DATABASE-PORT").reference, - description="Port 3306/tcp is a database port and should possibly not be open.", + description="Port 3306/tcp is a database port and should not be open.", ooi=tcp_port.reference, ) ] diff --git a/octopoes/tests/test_bit_ports.py b/octopoes/tests/test_bit_ports.py index d301c23b207..4efbc3b065d 100644 --- a/octopoes/tests/test_bit_ports.py +++ b/octopoes/tests/test_bit_ports.py @@ -40,7 +40,7 @@ def test_port_classification_tcp_5432(): assert len(results) == 2 finding = results[-1] assert isinstance(finding, Finding) - assert finding.description == "Port 5432/tcp is a database port and should possibly not be open." + assert finding.description == "Port 5432/tcp is a database port and should not be open." def test_port_classification_tcp_12345(): From 21ee6918b60929ceeadee2e1892c32eec5ef3d3a Mon Sep 17 00:00:00 2001 From: noamblitz <43830693+noamblitz@users.noreply.github.com> Date: Thu, 28 Nov 2024 10:39:20 +0100 Subject: [PATCH 10/10] Update octopoes/bits/port_classification_ip/port_classification_ip.py Co-authored-by: Jan Klopper --- octopoes/bits/port_classification_ip/port_classification_ip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/octopoes/bits/port_classification_ip/port_classification_ip.py b/octopoes/bits/port_classification_ip/port_classification_ip.py index 857d1f9c4fb..1ff5ed39533 100644 --- a/octopoes/bits/port_classification_ip/port_classification_ip.py +++ b/octopoes/bits/port_classification_ip/port_classification_ip.py @@ -83,7 +83,7 @@ def run(input_ooi: IPPort, additional_oois: list, config: dict[str, Any]) -> Ite ooi=ip_port.reference, description=f"Port {port}/{protocol.value} is a database port and should not be open.", ) - elif (protocol == Protocol.TCP or protocol == Protocol.UDP) and port in microsoft_rdp_ports: + elif port in microsoft_rdp_ports: open_rdp_port = KATFindingType(id="KAT-REMOTE-DESKTOP-PORT") if aggregate_findings: open_ports.append(ip_port.port)