Created
January 23, 2026 13:37
-
-
Save sinansh/94697ef612d70d9c3fa203101de96feb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import paramiko | |
| import csv | |
| import sys | |
| import socket | |
| import re | |
| # --- AYARLAR --- | |
| INPUT_CSV = "servers.csv" | |
| OUTPUT_REPORT = "envanter_analiz_raporu.csv" | |
| # Ubuntu 10.04, CentOS 5 vb. için eski algoritmalar | |
| def get_legacy_transport_options(): | |
| return { | |
| "disabled_algorithms": None, | |
| "kex": [ | |
| "diffie-hellman-group1-sha1", | |
| "diffie-hellman-group14-sha1", | |
| "diffie-hellman-group-exchange-sha1" | |
| ], | |
| "ciphers": [ | |
| "aes128-cbc", "3des-cbc", "aes256-cbc", "blowfish-cbc" | |
| ] | |
| } | |
| def create_ssh_client(ip, port, user, password): | |
| client = paramiko.SSHClient() | |
| client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) | |
| # 1. Deneme: Modern Bağlantı | |
| try: | |
| client.connect(ip, port=int(port), username=user, password=password, timeout=5, allow_agent=False, look_for_keys=False) | |
| return client, "Standard" | |
| except (paramiko.ssh_exception.SSHException, socket.error): | |
| pass # Modern başarısız, Legacy dene | |
| # 2. Deneme: Legacy Bağlantı (Ubuntu 10.04, RHEL 5 vb.) | |
| try: | |
| legacy_opts = get_legacy_transport_options() | |
| client.connect( | |
| ip, port=int(port), username=user, password=password, timeout=5, | |
| allow_agent=False, look_for_keys=False, | |
| disabled_algorithms=legacy_opts['disabled_algorithms'] | |
| ) | |
| return client, "Legacy-Mode" | |
| except Exception as e: | |
| return None, str(e) | |
| def run_command(client, command): | |
| try: | |
| stdin, stdout, stderr = client.exec_command(command, timeout=8) | |
| output = stdout.read().decode('utf-8', errors='ignore').strip() | |
| # Satır sonlarını temizle | |
| return output.replace('\n', ' ').replace('\r', '') | |
| except Exception: | |
| return "" | |
| def determine_strategy(os_name, kernel, arch): | |
| """ | |
| Sunucuya hangi güvenlik paketinin kurulacağına karar veren mantık. | |
| """ | |
| os_lower = os_name.lower() | |
| kernel_lower = kernel.lower() | |
| # 1. Appliance / Özel Sistemler (DOKUNMA) | |
| if "photon" in os_lower or "esx" in os_lower or "coreos" in os_lower: | |
| return "SKIP (Appliance/Container OS)" | |
| # 2. Mimari Kontrolü | |
| if arch not in ["x86_64"]: | |
| return "LEGACY (32-bit/Non-x64)" | |
| # 3. Kernel Versiyon Analizi | |
| # Kernel string örneği: "5.4.0-15-generic" veya "3.10.0-1160.el7.x86_64" | |
| try: | |
| # Sadece ana versiyonu al (Major.Minor) | |
| match = re.search(r'^(\d+)\.(\d+)', kernel) | |
| if match: | |
| major = int(match.group(1)) | |
| minor = int(match.group(2)) | |
| else: | |
| major, minor = 0, 0 | |
| except: | |
| major, minor = 0, 0 | |
| # --- MODERN (Sysmon + Auditd) --- | |
| # Kernel 5.x ve üzeri (Ubuntu 20+, Debian 11+, RHEL 9) | |
| if major >= 5: | |
| return "MODERN" | |
| # Kernel 4.17+ (RHEL 8, Rocky 8, Ubuntu 18.04 HWE) | |
| if major == 4 and minor >= 17: | |
| return "MODERN" | |
| # --- HYBRID / ÖZEL DURUM (CentOS 7) --- | |
| # RHEL/CentOS 7'de kernel 3.10 olsa da, build 1127+ ise Sysmon çalışır (eBPF backport) | |
| if "el7" in kernel_lower: | |
| # Build numarasını çekmeye çalış (3.10.0-1160...) | |
| if "3.10.0-" in kernel: | |
| try: | |
| build_part = kernel.split("3.10.0-")[1].split(".")[0] | |
| if int(build_part) >= 1127: | |
| return "MODERN (RHEL7 Backport)" | |
| except: | |
| pass # Parse edemezse Legacy kabul et | |
| return "LEGACY (CentOS 7 Old Kernel)" | |
| # --- LEGACY (Sadece Auditd) --- | |
| # Kernel < 4.17 (Ubuntu 16.04, CentOS 6, Debian 9) | |
| return "LEGACY" | |
| def main(): | |
| print(f"[*] Envanter Kesif ve Analiz Baslatiliyor...") | |
| print(f"[*] Hedef Dosya: {INPUT_CSV}") | |
| print("-" * 60) | |
| results = [] | |
| try: | |
| with open(INPUT_CSV, 'r') as f: | |
| reader = csv.DictReader(f) | |
| rows = list(reader) | |
| total = len(rows) | |
| for i, row in enumerate(rows, 1): | |
| host = row.get('Host', 'Unknown') | |
| ip = row['IP'] | |
| user = row['User'] | |
| password = row['Password'] | |
| port = row.get('SSH_Port', 22) | |
| print(f"[{i}/{total}] {host} ({ip}) ...", end=" ") | |
| sys.stdout.flush() | |
| ssh, conn_status = create_ssh_client(ip, port, user, password) | |
| if ssh: | |
| # 1. Bilgi Toplama Komutları | |
| kernel = run_command(ssh, "uname -r") | |
| arch = run_command(ssh, "uname -m") | |
| # OS İsmi Bulma (Garantili Yöntem) | |
| os_name = run_command(ssh, "cat /etc/os-release | grep PRETTY_NAME | cut -d= -f2 | tr -d '\"'") | |
| if not os_name: os_name = run_command(ssh, "cat /etc/redhat-release") | |
| if not os_name: os_name = run_command(ssh, "cat /etc/issue | head -n 1") | |
| if not os_name: os_name = "Unknown Linux" | |
| # Temizlik | |
| os_name = os_name.replace('\\n', '').replace('\\l', '').strip() | |
| # Service Manager (systemd vs init) | |
| init_proc = run_command(ssh, "ps -p 1 -o comm=") | |
| service_mgr = "systemd" if "systemd" in init_proc else "init/upstart" | |
| # 2. Analiz ve Karar | |
| strategy = determine_strategy(os_name, kernel, arch) | |
| print(f"OK -> {strategy}") | |
| results.append({ | |
| "Host": host, | |
| "IP": ip, | |
| "Status": "Success", | |
| "SSH_Mode": conn_status, | |
| "OS_Distribution": os_name, | |
| "Kernel_Version": kernel, | |
| "Architecture": arch, | |
| "Service_Manager": service_mgr, | |
| "Recommended_Strategy": strategy, | |
| "Notes": "" | |
| }) | |
| ssh.close() | |
| else: | |
| print(f"FAIL ({conn_status})") | |
| results.append({ | |
| "Host": host, | |
| "IP": ip, | |
| "Status": "Failed", | |
| "SSH_Mode": "-", | |
| "OS_Distribution": "-", | |
| "Kernel_Version": "-", | |
| "Architecture": "-", | |
| "Service_Manager": "-", | |
| "Recommended_Strategy": "MANUAL CHECK", | |
| "Notes": conn_status | |
| }) | |
| except FileNotFoundError: | |
| print(f"HATA: {INPUT_CSV} dosyasi bulunamadi!") | |
| return | |
| # Raporu Kaydet | |
| try: | |
| with open(OUTPUT_REPORT, 'w', newline='', encoding='utf-8') as f: | |
| fieldnames = ["Host", "IP", "Status", "SSH_Mode", "OS_Distribution", "Kernel_Version", "Architecture", "Service_Manager", "Recommended_Strategy", "Notes"] | |
| writer = csv.DictWriter(f, fieldnames=fieldnames) | |
| writer.writeheader() | |
| writer.writerows(results) | |
| print("-" * 60) | |
| print(f"[+] Rapor olusturuldu: {OUTPUT_REPORT}") | |
| print("[*] Excel ile acip 'Recommended_Strategy' sutununa gore filtreleyebilirsiniz.") | |
| except Exception as e: | |
| print(f"HATA: Rapor yazilamadi -> {e}") | |
| if __name__ == "__main__": | |
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Host | IP | SSH_Port | User | Password | |
|---|---|---|---|---|---|
| SRV-App-01 | 192.168.1.100 | 22 | root | Sifre123 | |
| SRV-Web-Legacy | 192.168.1.101 | 22 | admin | AdminPass | |
| SRV-Photon-Test | 192.168.1.102 | 22 | root | VMware123 | |
| SRV-Ubuntu-Old | 192.168.1.103 | 22 | root | OldPass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment