diff --git a/code/src/database_connection.py b/code/src/database_connection.py new file mode 100644 index 0000000000000000000000000000000000000000..d527a31bc19ca5f47e3423b093781452ffeca8f7 --- /dev/null +++ b/code/src/database_connection.py @@ -0,0 +1,87 @@ +from scapy.layers.inet import IP, TCP +from scapy.layers.l2 import Ether, ARP +import duckdb as duckdb + +UNDEFINED = 'Undefined' +def initiate_database(connection): + connection.sql("CREATE TABLE IF NOT EXISTS packets (" + "source_ip VARCHAR, " + "destination_ip VARCHAR, " + "source_mac VARCHAR, " + "destination_mac VARCHAR, " + "source_port VARCHAR, " + "destination_port VARCHAR, " + "is_dangerous BOOLEAN, " + "type_of_threat VARCHAR)") +def add_address(connection, packet): + source_ip = packet[IP].src if IP in packet else UNDEFINED + destination_ip = packet[IP].dst if IP in packet else UNDEFINED + source_mac = packet[Ether].src if Ether in packet else UNDEFINED + destination_mac = packet[Ether].dst if Ether in packet else UNDEFINED + source_port = packet[TCP].sport if TCP in packet else UNDEFINED + destination_port = packet[TCP].dport if TCP in packet else UNDEFINED + is_dangerous = False + type_of_threat = 'None' + + if not contains_address(connection, packet): + connection.sql(f"INSERT INTO packets VALUES (" + f"'{source_ip}', " + f"'{destination_ip}', " + f"'{source_mac}', " + f"'{destination_mac}', " + f"'{source_port}', " + f"'{destination_port}', " + f"{is_dangerous}, " + f"'{type_of_threat}')") + +def update_address(connection, packet, is_dangerous, type_of_threat): + source_ip = packet[IP].src if IP in packet else UNDEFINED + destination_ip = packet[IP].dst if IP in packet else UNDEFINED + source_mac = packet[Ether].src if Ether in packet else UNDEFINED + destination_mac = packet[Ether].dst if Ether in packet else UNDEFINED + source_port = packet[TCP].sport if TCP in packet else UNDEFINED + destination_port = packet[TCP].dport if TCP in packet else UNDEFINED + + connection.sql(f"UPDATE packets SET " + f"is_dangerous = {is_dangerous}, " + f"type_of_threat = '{type_of_threat}' " + f"WHERE source_ip = '{source_ip}' AND " + f"destination_ip = '{destination_ip}' AND " + f"source_mac = '{source_mac}' AND " + f"destination_mac = '{destination_mac}' AND " + f"source_port = '{source_port}' AND " + f"destination_port = '{destination_port}'") + +def contains_address(connection, packet): + source_ip = packet[IP].src if IP in packet else UNDEFINED + destination_ip = packet[IP].dst if IP in packet else UNDEFINED + source_mac = packet[Ether].src if Ether in packet else UNDEFINED + destination_mac = packet[Ether].dst if Ether in packet else UNDEFINED + source_port = packet[TCP].sport if TCP in packet else UNDEFINED + destination_port = packet[TCP].dport if TCP in packet else UNDEFINED + + contains = connection.sql(f"SELECT EXISTS ( FROM packets WHERE " + f"source_ip = '{source_ip}' AND " + f"destination_ip = '{destination_ip}' AND " + f"source_mac = '{source_mac}' AND " + f"destination_mac = '{destination_mac}' AND " + f"source_port = '{source_port}' AND " + f"destination_port = '{destination_port}')").fetchone()[0] + + return contains + +def get_address(connection, packet): + source_ip = packet[IP].src if IP in packet else UNDEFINED + destination_ip = packet[IP].dst if IP in packet else UNDEFINED + source_mac = packet[Ether].src if Ether in packet else UNDEFINED + destination_mac = packet[Ether].dst if Ether in packet else UNDEFINED + source_port = packet[TCP].sport if TCP in packet else UNDEFINED + destination_port = packet[TCP].dport if TCP in packet else UNDEFINED + + return connection.sql(f"SELECT * FROM packets WHERE " + f"source_ip = '{source_ip}' AND " + f"destination_ip = '{destination_ip}' AND " + f"source_mac = '{source_mac}' AND " + f"destination_mac = '{destination_mac}' AND " + f"source_port = '{source_port}' AND " + f"destination_port = '{destination_port}'").fetchone() \ No newline at end of file diff --git a/code/src/packet_capturing.py b/code/src/packet_capturing.py index 599185cf4fabf0d97748329bc9e0a8fdeccf4e7e..3fbe5626ae8b7b64a95d82b4ba60a38639e612c4 100644 --- a/code/src/packet_capturing.py +++ b/code/src/packet_capturing.py @@ -2,8 +2,12 @@ from scapy.layers.inet import IP, TCP from scapy.layers.l2 import Ether, ARP from scapy.all import sniff from collections import defaultdict +import duckdb as duckdb +import database_connection as dbConn import time +connection = duckdb.connect('packets_data.duckdb') + reserved_ips = ["192.168.1.4", "192.168.1.1", "192.168.1.7", "172.16.0.3"] syn_counts = defaultdict(int) @@ -11,19 +15,22 @@ syn_counts_last_checked = time.time() arp_table = defaultdict() -def ip_spoofing(src_mac, src_ip): +def ip_spoofing(src_mac, src_ip, packet): if src_ip not in reserved_ips: if src_ip.startswith("10.") or src_ip.startswith("192.168.") or src_ip.startswith("169.254."): + dbConn.update_address(connection=connection, packet=packet, is_dangerous=True, type_of_attack="IP Spoofing") print("Possible IP spoofing using private networks detected.") elif src_ip.startswith("172."): octet = int(src_ip.split(".")[1]) if 16 <= octet <= 31: + dbConn.update_address(connection=connection, packet=packet, is_dangerous=True, type_of_attack="IP Spoofing") print("Possible IP spoofing using private networks detected.") def syn_fin(packet): if TCP in packet: tcp_flags = packet[TCP].flags if 'S' in tcp_flags and 'F' in tcp_flags: + dbConn.update_address(connection=connection, packet=packet, is_dangerous=True, type_of_attack="SYN-FIN") print("Malicious packet detected: SYN-FIN combination.") print(f"MAC Address of malicious agent: {packet[Ether].src}") @@ -31,6 +38,7 @@ def null_packet(packet): if TCP in packet: tcp_flags = packet[TCP].flags if tcp_flags == 0: + dbConn.update_address(connection=connection, packet=packet, is_dangerous=True, type_of_attack="Null Packet") print("Malicious null packet found.") print(f"MAC Address of malicious agent: {packet[Ether].src}") @@ -39,6 +47,7 @@ def port_check(packet): src_port = packet[TCP].sport dst_port = packet[TCP].dport if src_port == 0 or dst_port == 0: + dbConn.update_address(connection=connection, packet=packet, is_dangerous=True, type_of_attack="TCP Port 0") print("Illegal packet with source or destination port 0.") print(f"MAC Address of malicious agent: {packet[Ether].src}") @@ -46,6 +55,7 @@ def destination_check(packet): if IP in packet: dest_ip = packet[IP].dst if dest_ip.endswith(".0") or dest_ip.endswith(".255"): + dbConn.update_address(connection=connection, packet=packet, is_dangerous=True, type_of_attack="Broadcast Address") print("Packets with broadcast destination address detected.") print(f"MAC Address of malicious agent: {packet[Ether].src}") @@ -55,6 +65,7 @@ def malformed_check(packet): # Attempt to parse packet packet.show() except Exception as e: + dbConn.update_address(connection=connection, packet=packet, is_dangerous=True, type_of_attack="Malformed Packet") print(f"Malformed packet detected: {e}") print(f"Source: {packet[IP].src if IP in packet else 'Unknown'}") @@ -68,6 +79,7 @@ def syn_flood_detection(packet): if time.time() - syn_counts_last_checked > 10: for ip, count in syn_counts.items(): if count > 100: + dbConn.update_address(connection=connection, packet=packet, is_dangerous=True, type_of_attack="SYN Flood") print(f"Possible SYN flood from {ip}. Number of SYN Packets in last {time.time() - syn_counts_last_checked} seconds: {count}") syn_counts.clear() syn_counts_last_checked = time.time() @@ -81,39 +93,42 @@ def arp_spoofing(packet): src_mac = packet[ARP].hwsrc if src_ip in arp_table: if arp_table[src_ip] != src_mac: + dbConn.update_address(connection=connection, packet=packet, is_dangerous=True, type_of_attack="ARP Spoofing") print(f"Possible ARP spoofing detected from IP {src_ip}. Conflicting MACs: {arp_table[src_ip]} and {src_mac}") else: arp_table[src_ip] = src_mac def tcp_reset_attack(packet): if packet[TCP].flags == 'R': + dbConn.update_address(connection=connection, packet=packet, is_dangerous=True, type_of_attack="TCP Reset") print(f"Possible TCP reset attack from {packet[IP].src}") def packet_handler(packet): + dbConn.add_address(connection=connection, packet=packet) if IP in packet: src_ip = packet[IP].src dst_ip = packet[IP].dst src_mac = packet[Ether].src if Ether in packet else None print(f"Packet captured: {src_ip} -> {dst_ip}") - ip_spoofing(src_mac, src_ip) + ip_spoofing(src_mac, src_ip, packet) + destination_check(packet) + malformed_check(packet) + syn_flood_detection(packet) + arp_spoofing(packet) if TCP in packet: syn_fin(packet) null_packet(packet) port_check(packet) tcp_reset_attack(packet) - destination_check(packet) - malformed_check(packet) - syn_flood_detection(packet) - arp_spoofing(packet) # Allows unit testing of the dict def get_dict(): return syn_counts - def dict_clear(): syn_counts.clear() def main(): + dbConn.initiate_database(connection) print("Starting packet capture...") sniff(prn=packet_handler, store=False)