Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
sshfinder — Herramienta de descubrimiento de servicios SSH en paralelo y auditor de seguridad que escanea cualquier puerto, valida banners SSH y audita métodos de autenticación, criptografía débil, vulnerabilidad Terrapin y claves de host reutilizadas entre hosts y rangos CIDR. | Kitploit
Herramientas/GitHubGitHub/kabiri-labs/sshfinder
ReconocimientoEscáneres de VulnerabilidadesEscaneo de PuertosAnálisis de VulnerabilidadesRecopilación de InformaciónSeguridad de RedesCriptografíaPruebas de Penetración
GitHubkabiri-labs/sshfinder

sshfinder

Herramienta de descubrimiento de servicios SSH en paralelo y auditor de seguridad que escanea cualquier puerto, valida banners SSH y audita métodos de autenticación, criptografía débil, vulnerabilidad Terrapin y claves de host reutilizadas entre hosts y rangos CIDR.

33hace 1 mesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Ver Repositorio
Compartir

sshfinder

CI version

Encuentra cada servicio SSH en tu red, determina si cumple con tu estándar, y recibe una notificación cuando eso cambie.

sshfinder es un único archivo Python sin dependencias requeridas. Apúntalo a un rango CIDR y descubre SSH dondequiera que esté realmente escuchando — no solo en el puerto 22 — confirma que cada uno realmente habla SSH, evalúa su postura criptográfica, y devuelve un código de salida distinto de cero cuando algo falla en tu política.


El problema que resuelve

La mayoría de los equipos no pueden responder tres preguntas sobre su propio parque SSH:

  1. ¿Cuántos servicios SSH tenemos, y dónde? No cuántas máquinas — cuántos servicios SSH en escucha, incluido el del puerto 2222 que un contratista configuró en 2019.
  2. ¿Cumplen todos con nuestro estándar? Inicio de sesión con contraseña deshabilitado, sin cifrados rotos, no expuestos a Terrapin. De forma demostrable, no por afirmación.
  3. ¿Qué cambió desde anoche? Una clave de host que se movió. Un servicio que apareció. Autenticación por contraseña que volvió tras una reconstrucción.

Las herramientas existentes responden cada una a parte de esto y se detienen:

Esa brecha — descubrimiento y evaluación y un veredicto, en un solo artefacto — es lo que esta herramienta existe para llenar. Si solo necesitas auditar un host que ya conoces, usa ssh-audit; profundiza más en un solo servicio que esto.

Para quién es

  • Seguridad interna e inventario de activos. Construye y mantén un registro de cada servicio SSH en el parque, exportado a CSV o JSON.
  • Equipos de plataforma y SRE con una obligación de cumplimiento. Demuestra, de forma programada y con un código de salida, que ningún host en una VPC acepta inicio de sesión con contraseña u ofrece criptografía débil.
  • Cualquiera que ejecute una migración post-cuántica. Un número para cuánto de la flota aún no puede negociar intercambio de claves post-cuántico, y exactamente qué servicios son esos.

Los testers de penetración encontrarán útiles la auditoría y el pivote SOCKS, pero la herramienta está diseñada en torno a ejecutar el mismo escaneo repetidamente contra un parque que posees, no en torno a un compromiso puntual.


Inicio rápido

root@kitploit:~
git clone https://github.com/kabiri-labs/sshfinder.git
cd sshfinder
python sshfinder.py 10.0.0.0/24 -p 22,2222

Sin instalación, sin dependencias. Requiere Python 3.9+.

Las tres cosas que hace, en tres comandos:

root@kitploit:~
# 1. INVENTARIO — ¿qué SSH hay ahí fuera?
python sshfinder.py 10.0.0.0/24 --audit --format csv -o ssh-inventory.csv

# 2. VEREDICTO — ¿cumple con nuestro estándar? (sale con 3 si no)
python sshfinder.py 10.0.0.0/24 -p 22,2222 --policy baseline

# 3. DERIVA — ¿qué cambió desde anoche?
python sshfinder.py 10.0.0.0/24 -p 22,2222 --baseline yesterday.json \
    --fail-on-drift

1. Inventario

Escanear los 65535 puertos es el valor predeterminado, porque un servicio SSH en un puerto no estándar es precisamente el que nadie ha documentado. Cada puerto abierto está etiquetado, por lo que un puerto abierto nunca se cuenta silenciosamente como uno SSH:

root@kitploit:~
=== 10.0.0.5 ===
  open: 10.0.0.5:22 [SSH], 10.0.0.5:8080 [not ssh]
  SSH  10.0.0.5:22  (SSH-2.0-OpenSSH_7.4)

La confirmación es un intercambio de identificación RFC 4253 real, no un vistazo a los primeros bytes en el cable. Los servidores que imprimen un banner legal primero, que esperan a que el cliente se identifique, o cuyo banner llega dividido entre segmentos TCP se reconocen correctamente — cada uno de esos es un falso negativo en una implementación ingenua.

Añade --audit para la imagen completa de cada servicio:

root@kitploit:~
  SSH  10.0.0.5:22  (SSH-2.0-OpenSSH_7.4)
       host key: ssh-ed25519 SHA256:T/ZM4jOL4amTsO5K3AaCdg2...
       auth: publickey, password  [!] password auth enabled
       [!] Terrapin (CVE-2023-48795): VULNERABLE
       [!] weak ciphers: aes128-cbc
           aes128-cbc [weak]: CBC mode is vulnerable to the SSH plaintext-recovery attack (CVE-2008-5161) and, …

Claves de host SSH compartidas (posibles hosts compartidos/clonados):
  SHA256:T/ZM4jOL4amTsO5K3AaCdg2...
    -> 10.0.0.5:22, 10.0.0.9:22

Ese último bloque vale la pena conocerlo: una clave de host reutilizada entre máquinas normalmente significa VMs clonadas o una imagen compartida, y significa que comprometer un host compromete la identidad de todos ellos.

Preparación post-cuántica

OpenSSH 10.0 hizo de mlkem768x25519-sha256 el intercambio de claves predeterminado, y 10.1 advierte que las sesiones clásicas están abiertas a la captura de almacena ahora, descifra después. --pq-report responde la pregunta a nivel de flota directamente, usando solo el KEXINIT — por lo que no necesita ninguna biblioteca de terceros:

root@kitploit:~
python sshfinder.py 10.0.0.0/24 -p 22,2222 --pq-report
root@kitploit:~
Post-quantum readiness:
  1/3 service(s) negotiate post-quantum key exchange with a current client
  [!] no PQ key exchange offered (1):
        10.0.0.2:22
  [!] pre-standard PQ only (1) - looks post-quantum but is not:
        10.0.0.3:22
  2 service(s) exposed to store-now-decrypt-later capture; upgrade to OpenSSH 9.0+

La categoría pre-standard es la que atrapa a la gente. Un servidor que anuncia [email protected] o un borrador de Kyber parece post-cuántico en un volcado de algoritmos, pero OpenSSH eliminó ese conjunto de parámetros retirado en 2020 — por lo que un cliente actual no encuentra ningún método común y vuelve a la criptografía clásica. Contado como listo, sería peor que no mirar en absoluto.

2. Veredicto

Un informe describe un problema. Una política afirma uno, y puede hacer fallar una compilación:

root@kitploit:~
python sshfinder.py 10.0.0.0/24 -p 22,2222 --policy baseline; echo "exit $?"
root@kitploit:~
Policy 'baseline':
  No password login, no Terrapin exposure, no weak algorithms.
  1/3 service(s) pass
  [FAIL] 1 service(s):
        10.0.0.3:22
          - password_auth: password login accepted: publickey, password
          - terrapin: vulnerable to Terrapin (CVE-2023-48795)
          - post_quantum (warn): post-quantum readiness is absent, ready required
  [warn] 1 service(s):
        10.0.0.2:22
          - post_quantum (warn): post-quantum readiness is absent, ready required
exit 3

Tres políticas vienen integradas — baseline, strict y pq — nombradas por el resultado que imponen en lugar de por una distribución. Las reglas llevan una severidad fail o warn y --fail-on decide qué compuertas, por lo que un equipo puede adoptar un estándar más estricto como advertencia primero y promoverlo después sin editar nada.

Escribe las tuyas propias como JSON:

root@kitploit:~
{
  "name": "house-rules",
  "description": "What we expect of every SSH service.",
  "rules": [
    {"check": "password_auth", "severity": "fail"},
    {"check": "terrapin", "severity": "fail"},
    {"check": "post_quantum", "require": "ready", "severity": "warn"},
    {"check": "forbid", "field": "ciphers",
     "algorithms": ["3des-cbc", "arcfour"], "severity": "fail"},
    {"check": "require", "field": "kex_algorithms",
     "algorithms": ["curve25519-sha256"], "severity": "fail"}
  ]
}

Comprobaciones: password_auth, terrapin, weak_algorithms, post_quantum (con require: ready, legacy o absent), y forbid / require sobre un field de kex_algorithms, host_key_algorithms, ciphers o macs.

Cualquier otra cosa es un error grave cuando la política se carga, antes de que comience el escaneo. Una compuerta que omite silenciosamente una regla que no entiende es peor que ninguna compuerta: la ejecución se pone en verde y nadie se entera de que la comprobación nunca se ejecutó.

root@kitploit:~
$ sshfinder 10.0.0.0/24 --policy house.json
sshfinder: error: rule 1: unknown check 'pasword_auth'
  (known: forbid, password_auth, post_quantum, require, terrapin, weak_algorithms)

3. Deriva

Ejecútalo cada noche contra el informe de ayer y ve solo lo que se movió:

root@kitploit:~
# Nightly, in cron:
python sshfinder.py 10.0.0.0/24 -p 22,2222 --audit --json -o today.json
python sshfinder.py 10.0.0.0/24 -p 22,2222 --baseline yesterday.json \
    --fail-on-drift
root@kitploit:~
Baseline drift (vs yesterday.json):
  [alert] 2 change(s):
        10.0.0.5:22  SHA256:T/ZM4jO... -> SHA256:9aKm2Qx...; expected only after a rebuild or key rotation
        10.0.0.3:22  password login is now accepted
  [added] 1 change(s):
        10.0.0.9:2222  new SSH service (SSH-2.0-OpenSSH_9.6)
  [improved] 1 change(s):
        10.0.0.7:22  post-quantum readiness rose from absent to ready

Una clave de host que cambió es la señal que más importa aquí — esperada solo después de una reconstrucción o una rotación de claves, y digna de revisión en cualquier otro momento.

Solo alert controla --fail-on-drift. Un host dado de baja es un cambio ordinario, y hacer fallar un trabajo nocturno por ello entrenaría a todos a ignorar el resultado.

La comparación tiene cuidado de no inventar cambios. Un campo que ningún escaneo midió nunca se informa como cambiado, solo se comparan los hosts presentes en ambos escaneos, y una línea base que contiene huellas de claves de host hace que este escaneo también ejecute la sonda profunda — por lo que un reescaneo superficial nunca se lee como si cada clave hubiera desaparecido.


Formatos de salida

--format text|json|sarif|csv, opcionalmente escrito a un archivo con -o.

  • csv — una fila por servicio SSH confirmado. La forma en que un inventario de activos realmente se ordena y filtra.
  • json — el informe nativo, y el formato de entrada para --baseline.
  • sarif — SARIF 2.1.0, validado contra el esquema OASIS. Los hallazgos están anclados a ubicaciones lógicas host:port y llevan huellas estables, por lo que un consumidor rastrea el mismo hallazgo entre ejecuciones nocturnas en lugar de abrir una alerta nueva cada vez.
  • --stream — eventos JSON delimitados por nueva línea vaciados a medida que cada puerto se abre y cada servicio se confirma, para que una canalización pueda actuar sobre el primer resultado mientras el escaneo aún se está ejecutando:
root@kitploit:~
python sshfinder.py 10.0.0.0/24 --stream -q | jq -c 'select(.event=="ssh")'
root@kitploit:~
{"event":"ssh","elapsed":0.164,"host":"10.0.0.5","port":22,"banner":"SSH-2.0-OpenSSH_9.6"}
{"event":"ssh","elapsed":0.881,"host":"10.0.0.9","port":2222,"banner":"SSH-2.0-dropbear"}

Sobre SARIF y el escaneo de código de GitHub. Los resultados SARIF deben llevar una ubicación de artefacto no vacía o upload-sarif rechaza el archivo, por lo que se emite un URI sintético ssh://host:port junto con la ubicación lógica. No se resuelve a un archivo en tu repositorio, por lo que las alertas aparecen sin un ancla de código. Trata esto como SARIF para herramientas de seguridad en general — el visor SARIF de VS Code, Azure DevOps, archivado — no como una forma de anotar un diff.

Códigos de salida

Todo el punto de las funciones de política y deriva, por lo que vale la pena declararlos con precisión:

Un error grave supera a un veredicto de política, y un veredicto de política supera a la deriva. Si nada era alcanzable, el escaneo no demostró nada sobre el cumplimiento en ningún sentido, por lo que obtienes 1 en lugar de un aprobado o fallo engañoso; y fallar un estándar declarado es un hallazgo más específico que "algo cambió".


Instalación

El escaneo central, la validación de banner y las partes sin dependencias de --audit (inventario de algoritmos, banderas de criptografía débil, Terrapin, preparación post-cuántica) no necesitan nada más que Python 3.9+.

root@kitploit:~
# Recomendado: desbloquea huellas de claves de host, enumeración de métodos de autenticación y
# correlación de claves compartidas en --audit, además de --validate paramiko.
pip install -r requirements.txt

# Opcional, solo para escaneos SYN de medio abierto (necesita root):
pip install scapy>=2.5

Opciones

--scan-method auto selecciona el escaneo SYN cuando se ejecuta como root con Scapy instalado, y de lo contrario recurre al escaneo de conexión sin privilegios. SOCKS no se puede combinar con un escaneo SYN — SOCKS5 transporta flujos TCP, no paquetes crudos.

Escaneo a través de un host de salto

root@kitploit:~
python sshfinder.py 10.0.0.0/24 -p 22 --socks user:[email protected]:1080

El descubrimiento, el intercambio de banner y la auditoría atraviesan el pivote, por lo que los resultados nunca están medio tunelizados. Un proxy que es inalcanzable se informa como un error de escaneo, nunca como "no se encontró SSH".

Escaneo de producción de forma segura

--max-rate limita las sondas por segundo en todo el escaneo. La concurrencia limita cuántas conexiones están abiertas a la vez; esto limita qué tan rápido comienzan nuevas, que es el tope que necesitas poder prometer antes de escanear cualquier cosa bajo reglas de compromiso.


Cómo funciona

Notas de implementación, para cuando el comportamiento anterior necesite explicación.

El motor de escaneo. Cada conexión en vuelo se impulsa desde un solo hilo mediante un bucle de eventos del SO (epoll/kqueue/select), por lo que la concurrencia cuesta un descriptor de archivo en lugar de un hilo del SO, y cada host se resuelve una vez en lugar de una vez por puerto. Un barrido completo de 1–65535 se ejecuta aproximadamente 6× más rápido que un diseño de grupo de hilos.

Puertos SSH primero. El puñado de puertos donde SSH realmente vive (22, 2222, 22222, …) se sondean al inicio de cada barrido. En un barrido completo, el primer servicio SSH confirmado aparece en aproximadamente 0.2 segundos en lugar de 16.

Un apretón de manos por servicio. El socket que descubrió un puerto abierto se entrega directamente al intercambio de banner, por lo que un servicio SSH confirmado cuesta un apretón de manos TCP en lugar de dos.

Tiempo de espera adaptativo. Las sondas esperan tanto como el camino lo justifica, usando el estimador de ida y vuelta suavizado de RFC 6298 — el que el propio TCP usa — alimentado por cada sonda respondida y compartido en todo el escaneo. --timeout se convierte en un tope en lugar de un costo fijo: en un host vivo pero mayormente filtrado eso vale aproximadamente 5× con hallazgos idénticos. Solo una respuesta definitiva le enseña algo; un tiempo de espera agotado no dice nada sobre el camino y nunca se retroalimenta.

Dos lugares mantienen deliberadamente el tope completo. El intercambio de banner y la auditoría nunca se adaptan, porque qué tan rápido un host completa un apretón de manos TCP no dice nada sobre qué tan rápido su demonio SSH compone un saludo. Tampoco lo hace la re-sonda final de los puertos habituales de SSH, ya que un SYN caído allí es la única pérdida que realmente le cuesta a esta herramienta un hallazgo.

Salida temprana. Un host que no responde nada en absoluto en sus primeras pocas cientos de sondas se informa como no receptivo en lugar de consumir un tiempo de espera por puerto restante. Debido a que los puertos de SSH se barren primero, un servicio vivo siempre se ve antes de que esto pueda dispararse; --no-early-exit fuerza el rango completo.

Acotado por diseño. Un presupuesto de sockets a nivel de proceso derivado del límite de descriptores de archivo evita que un escaneo grande agote los descriptores y informe erróneamente servicios vivos como filtrados. La expansión de objetivos comprueba el tamaño de una red antes de materializarla, por lo que un /8 perdido se rechaza en milisegundos en lugar de consumir un gigabyte de memoria.

Juicios de algoritmos curados. Cada algoritmo marcado proviene de una tabla explícita con una severidad y una razón declarada, no de una cadena de pruebas de subcadenas. Los nombres se normalizan primero, por lo que un sufijo de proveedor no puede pasar una comprobación — [email protected] es CBC sin importar quién lo envíe — y los marcadores de negociación como [email protected] nunca se evalúan como algoritmos. Esta tabla es en lo que finalmente se basan la compuerta de política y la comparación de deriva.

Ctrl+C robusto. Se respeta incluso en Windows, donde una espera de hilo ilimitada normalmente lo traga: la primera pulsación se detiene con elegancia y devuelve resultados parciales, una segunda fuerza una salida inmediata.


Lo que deliberadamente no hace

  • Inferir CVEs a partir de versiones de banner. Las distribuciones aplican parches sin tocar la cadena de versión, por lo que OpenSSH_9.6p1 en Ubuntu 24.04 está parcheado contra la mayoría de lo que las bases de datos públicas atribuyen a 9.6p1. Eso es una máquina de falsos positivos — es por eso que ssh-audit eliminó su propia detección de CVE basada en versiones, y por qué Tenable envía un plugin cuyo único trabajo es detectar el backporting que lo rompe. Solo lo que un servidor realmente anuncia se evalúa.
  • Fuerza bruta de credenciales. Otra herramienta, otro propósito, otra postura legal.
  • Competir con nmap en escaneo de puertos general, o con masscan y zmap a escala de internet. Esos problemas están resueltos.

Desarrollo

La suite de pruebas es solo de biblioteca estándar, por lo que se ejecuta en un intérprete desnudo:

root@kitploit:~
python -m unittest discover -s tests

Instala las dependencias de ejecución para también ejercitar las pruebas de auditoría respaldadas por Paramiko, que se omiten a sí mismas cuando Paramiko falta:

root@kitploit:~
pip install -r requirements-dev.txt
python -m unittest discover -s tests

Legal

Solo escanea sistemas que posees o para los que estás explícitamente autorizado a probar. El escaneo no autorizado puede ser ilegal en tu jurisdicción.

Descargar herramienta
HerramientaDescubre SSHLo evalúaEn toda una flota
nmapsísuperficial, mediante scripts NSEsí
ssh-auditno — le das un solo hosten profundidadno
masscan / zmapa escala de internetnosí
sshfindersísísí
CódigoSignificado
0Éxito. Nada encontrado sigue siendo éxito — un parque vacío no es un error.
1Error grave: todos los objetivos fallaron al escanearse, o el archivo de salida no pudo escribirse.
2Invocación incorrecta (bandera desconocida, especificación de puerto inválida, política o proxy malformado).
3Violación de política en o por encima de --fail-on. Solo con --policy.
4Alerta de deriva de línea base. Solo con --baseline --fail-on-drift.
130Interrumpido con Ctrl+C.
OpciónDescripción
targetsUna o más IPs, nombres de host o redes CIDR.
-iL, --target-file FILELee objetivos de un archivo (uno por línea, se permiten comentarios #).
-p, --ports SPECPuertos a escanear, p. ej. 22,80,1000-2000 (predeterminado: 1-65535).
--auditAudita cada servicio SSH: algoritmos, clave de host, métodos de autenticación, Terrapin, preparación post-cuántica, correlación de claves compartidas.
--pq-reportInforma la preparación post-cuántica en todo el parque. No necesita ninguna biblioteca de terceros.
--policy NAME_OR_PATHComprueba cada servicio contra baseline, strict, pq, o un archivo de política JSON. Sale con 3 en violación.
--fail-on {fail,warn,never}Qué severidad de política controla el código de salida (predeterminado: fail).
--baseline FILECompara contra un informe --json anterior y lista qué cambió.
--fail-on-driftSale con 4 cuando la comparación genera una alerta.
--format {text,json,sarif,csv}Formato de salida (predeterminado: text).
--jsonAbreviatura de --format json.
--streamEmite eventos JSON delimitados por nueva línea a medida que se encuentran resultados.
-o, --output FILEEscribe resultados a un archivo en lugar de stdout.
--validate {banner,paramiko,none}Estrategia de validación SSH (predeterminado: banner).
--scan-method {auto,connect,syn}Back-end de escaneo (predeterminado: auto).
--socks [user:pass@]host:portAlcanza cada objetivo a través de un proxy SOCKS5.
--max-rate NLimita sondas por segundo en todo el escaneo (predeterminado: sin límite).
-t, --timeout SECONDSMáximo que una sonda puede esperar (predeterminado: 2.0).
--min-timeout SECONDSMínimo para el tiempo de espera adaptativo de la sonda (predeterminado: 0.1).
--no-adaptive-timeoutEspera el --timeout completo en cada sonda.
-w, --workers NConexiones en vuelo por host (predeterminado: 512).
--max-sockets NTope de sockets de sonda abiertos a la vez (predeterminado: del límite de descriptores de archivo).
--host-concurrency NHosts escaneados en paralelo (predeterminado: 16).
-r, --retries NReintentos para sondas con tiempo de espera agotado (predeterminado: 0).
--max-targets NRechaza listas de objetivos más grandes que esto (predeterminado: 65536).
--no-early-exitBarre cada puerto incluso en hosts que no responden nada en absoluto.
--no-progressDesactiva el indicador de progreso en vivo.
-v, --verboseRegistro detallado (-vv también desilencia Paramiko).
-q, --quietSuprime el progreso y el registro informativo.
--versionImprime la versión y sale.