Files

47 lines
2.1 KiB
Python

from __future__ import annotations
import socket
import ssl
import time
from redflare.core.models import ModuleResult, Target
from .base import Module, ModuleContext
class PassiveReconModule(Module):
name = "passive_recon"
description = "Resolve DNS and collect TLS certificate metadata"
def run(self, target: Target, context: ModuleContext) -> ModuleResult:
started = time.monotonic()
result = ModuleResult(self.name, target.url)
try:
context.emit(target.url, self.name, "progress", f"Resolving {target.host}")
addresses = sorted({item[4][0] for item in socket.getaddrinfo(target.host, target.port)})
result.observations["addresses"] = addresses
context.emit(target.url, self.name, "info", f"Resolved addresses: {', '.join(addresses)}")
if target.scheme == "https":
context.emit(target.url, self.name, "progress", f"Negotiating TLS on port {target.port}")
tls_context = ssl.create_default_context()
with socket.create_connection((target.host, target.port), timeout=context.timeout) as raw:
with tls_context.wrap_socket(raw, server_hostname=target.host) as wrapped:
cert = wrapped.getpeercert()
result.observations["tls"] = {
"subject": cert.get("subject"),
"issuer": cert.get("issuer"),
"not_before": cert.get("notBefore"),
"not_after": cert.get("notAfter"),
"san": [value for key, value in cert.get("subjectAltName", []) if key == "DNS"],
}
context.emit(
target.url,
self.name,
"info",
f"TLS certificate expires {cert.get('notAfter', 'unknown')}",
)
except Exception as exc:
result.status = "error"
result.errors.append(f"{type(exc).__name__}: {exc}")
result.duration_seconds = round(time.monotonic() - started, 4)
return result