From dad9c3d20766578b1129ef5660ab47848a71aa07 Mon Sep 17 00:00:00 2001 From: stephanie0x00 <9821756+stephanie0x00@users.noreply.github.com> Date: Thu, 28 Nov 2024 11:58:47 +0100 Subject: [PATCH] Create separate finding for Microsoft RDP port (#3882) Co-authored-by: Soufyan Abdellati Co-authored-by: Rieven Co-authored-by: Ammar Co-authored-by: Jan Klopper Co-authored-by: noamblitz <43830693+noamblitz@users.noreply.github.com> --- .../kat_finding_types.json | 7 +++++++ .../question_schema.json | 6 ++++++ .../port_classification_ip.py | 20 +++++++++++++++++-- octopoes/tests/test_bit_ports.py | 2 +- 4 files changed, 32 insertions(+), 3 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 a23c8d04f2f..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 @@ -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": "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." + }, "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/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", diff --git a/octopoes/bits/port_classification_ip/port_classification_ip.py b/octopoes/bits/port_classification_ip/port_classification_ip.py index 7ac7fbbb4cc..1ff5ed39533 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 @@ -66,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 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") @@ -79,6 +83,18 @@ 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 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 " + 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/test_bit_ports.py b/octopoes/tests/test_bit_ports.py index 09c9a86c483..4efbc3b065d 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():