cipher-scanner.py
import os
import platform
import sys
import subprocess
import re
import socket
import requests
# ANSI color codes
RED = "\033[91m"
GREEN = "\033[92m"
YELLOW = "\033[33m"
BLUE = "\033[34m"
WHITE = "\033[37m"
RESET = "\033[0m"
# Function to ping a host
def ping_host(host):
command = ['ping', '-n' if platform.system().lower() == 'windows' else '-c', '1', host.strip()]
response = os.system(' '.join(command) + " > /dev/null 2>&1")
return response == 0 # Returns True if host is reachable
# Function to check if a port is open using telnet (socket)
def check_port(ip, port):
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.settimeout(5)
result = sock.connect_ex((ip, port))
return result == 0 # Returns True if the port is open
except:
return False
# Function to check cipher security using the API
def check_cipher_security(cipher_name):
url = f"https://ciphersuite.info/api/cs/{cipher_name}/"
response = requests.get(url)
if response.status_code == 200:
cipher_data = response.json()
if cipher_name in cipher_data:
security_status = cipher_data[cipher_name].get('security', 'unknown')
return security_status
else:
return "Cipher suite information not found"
else:
return "Error"
# Function to display the cipher security status
def display_security_status(cipher_name, security_status):
color_map = {
'weak': YELLOW,
'insecure': RED,
'recommended': BLUE,
'secure': GREEN
}
color = color_map.get(security_status.lower(), WHITE)
return f"{cipher_name} --> {color}{security_status.capitalize()}{RESET}"
# Function to run nmap and parse the output
def run_nmap_ssl_enum(ip, port):
result = ""
try:
result = subprocess.run(
["nmap", "--script", "ssl-enum-ciphers", "-p", port, ip],
capture_output=True,
text=True
).stdout
except Exception as e:
print(f"An error occurred while running nmap: {e}")
formatted_output = parse_nmap_output(ip, port, result)
return formatted_output
# Function to parse nmap output and combine it with security checks
def parse_nmap_output(ip, port, output):
formatted_output = (
f"Hosts: {BLUE}{ip}{RESET}\n"
f"Port: {BLUE}{port}{RESET}\n"
)
tls_version_re = re.compile(r"\|\s+(TLSv[0-9]\.[0-9]):")
cipher_re = re.compile(r"\|\s+([A-Z0-9_]+(?:_[A-Z0-9]+)*)")
tls_versions = tls_version_re.findall(output)
ciphers_by_tls = {}
for tls_version in tls_versions:
ciphers_by_tls[tls_version] = []
current_tls = None
for line in output.splitlines():
tls_match = tls_version_re.match(line)
if tls_match:
current_tls = tls_match.group(1)
elif current_tls:
cipher_match = cipher_re.match(line)
if cipher_match:
cipher = cipher_match.group(1)
if "NULL" not in cipher and "64" not in cipher:
ciphers_by_tls[current_tls].append(cipher)
cipher_found = False
for tls_version, ciphers in ciphers_by_tls.items():
if ciphers:
cipher_found = True
formatted_output += f"\nCiphers:\n"
formatted_output += f"{tls_version}\n"
for cipher in ciphers:
security_status = check_cipher_security(cipher)
formatted_output += f"{display_security_status(cipher, security_status)}\n"
formatted_output += "\n"
if not cipher_found:
return None
return formatted_output.strip()
# Main function to process the input file and integrate all functions
def process_ip_port_file(filename):
if not os.path.isfile(filename):
print(f"File {filename} not found.")
return
try:
with open(filename, "r") as file:
for line in file:
if line.strip():
ip_port_pair = line.strip().split()
ports = ip_port_pair[0].split(',')
ip = ip_port_pair[1]
for port in ports:
formatted_output = run_nmap_ssl_enum(ip, port)
if formatted_output:
print(formatted_output + "\n" + "-"*50 + "\n")
else:
# No ciphers found, check telnet
print(f"Hosts: {BLUE}{ip}{RESET}\nPort: {BLUE}{port}{RESET}\nCipher status: No")
if not check_port(ip, int(port)):
print(f"Telnet: {RED}Port closed{RESET}")
if ping_host(ip):
print(f"Ping: {GREEN}Host reachable{RESET}")
else:
print(f"Ping: {RED}Host not reachable{RESET}")
else:
print(f"Telnet: {GREEN}Port open{RESET}")
print("\n" + "-"*50 + "\n")
except Exception as e:
print(f"An error occurred while processing the file: {e}")
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python cipher-scanner.py hosts.txt")
sys.exit(1)
input_filename = sys.argv[1]
process_ip_port_file(input_filename)
Last updated