
Este projeto explora se o OpenSSH moderno revela nomes de usuário válidos por meio de diferenças sutis de resposta ou de tempo. Investigação de enumeração de usuários CVE-2016-6210 ( teste t de Welch, d de Cohen e engenharia de detecção ) em um laboratório controlado no Ubuntu 22.04.5 LTS; também examina os rastros que tais tentativas deixam para trás e como podem ser detectados.
Uma reinvestigação reproduzível da enumeração de nomes de usuário do OpenSSH usando análise estatística.
Este projeto reinvestiga o CVE-2016-6210, um canal lateral de temporização documentado do OpenSSH, para determinar se ele permanece observável em um servidor Ubuntu moderno usando a configuração padrão do PAM.
Em vez de assumir que o comportamento publicado ainda se aplica, o projeto avalia medições de temporização de autenticação coletadas por sondagem manual, Hydra e Metasploit usando o teste t de Welch e o d de Cohen para distinguir sinais de temporização genuínos do ruído de medição.
O estudo não encontrou nenhuma diferença de temporização estatisticamente significativa na configuração padrão testada, demonstrando o valor da experimentação reproduzível e da validação baseada em evidências de alegações de segurança publicadas.
⚠️ Aviso Legal
Este projeto foi conduzido inteiramente em um ambiente de laboratório isolado e de propriedade própria. Todas as descobertas se aplicam apenas à configuração testada. Nunca teste sistemas que você não possui ou para os quais não tenha autorização explícita por escrito.
Enumeração de usuários - a capacidade de determinar se um nome de usuário específico existe em um sistema remoto sem credenciais válidas. É um primeiro passo crítico na cadeia de ataque que leva ao comprometimento da conta:``` Reconnaissance → [User Enumeration] → Password Attack → Access ↑ This project investigates here
Se um atacante consegue distinguir "este usuário existe" de "este usuário não existe" ao analisar as respostas do servidor, pode reduzir drasticamente o espaço de chaves para ataques subsequentes de força bruta ou credential stuffing.
SSH é um alvo frequente porque é quase universalmente exposto, lida com autenticação por senha e implementações antigas apresentavam diferenças de tempo mensuráveis entre nomes de usuário válidos e inválidos (CVE-2016-6210).
**Esta investigação faz duas perguntas:**
1. O OpenSSH moderno no Ubuntu 22.04.5 LTS com configuração padrão vaza a existência de nome de usuário por meio de mensagens de resposta, tempo ou sinais relatados por ferramentas?
2. Se um atacante fizer a tentativa de qualquer forma, quais artefatos ela deixa? e com que confiabilidade esses podem ser detectados?
---
## 🖥️ Configuração do Laboratório
Todos os testes foram realizados em uma rede virtual isolada apenas para host, sem exposição à internet.
| Máquina | SO | Função | IP | Versão SSH |
|----------|---------------------------|-----------------------------------------|------------------|------------------|
| Atacante | Kali Linux 2024.1 | Ferramentas ofensivas, scripts de análise | 192.168.56.5 | — |
| Alvo | Ubuntu Server 22.04.5 LTS | Executando OpenSSH com configuração **padrão** | 192.168.56.10 | OpenSSH 8.9p1 |
**Configuração SSH do alvo (`/etc/ssh/sshd_config` padrão):**```
PasswordAuthentication yes
UsePAM yes # Key setting — normalises timing via dummy hash
PermitRootLogin prohibit-password
MaxAuthTries 6
LogLevel INFO
UsePAM yes é a configuração crítica de hardening. Ela força o OpenSSH a executar um cálculo bcrypt fictício para usuários inexistentes, igualando o tempo de uma verificação de senha real.
Isso foi introduzido especificamente como uma contramedida para o CVE-2016-6210.
Cada método de ataque foi executado como um teste independente com um estado de log limpo:```bash
sudo truncate -s 0 /var/log/auth.log
sudo cp /var/log/auth.log ~/evidence/trial-N-auth.log
Evidências coletadas por tentativa:
- Saída padrão/erro da ferramenta (salva textualmente)
- `/var/log/auth.log` do alvo
- Amostras de tempo de resposta via `time.perf_counter()` no `manual_ssh.py`
- Banner SSH capturado antes de qualquer tentativa de autenticação
### Métodos de Ataque
| Método | Ferramenta | Wordlist | Propósito |
|-----------------------|---------------------------------------|-------------------------|--------------------------------------------------|
| SSH manual | `ssh` CLI + Paramiko | 50 nomes de usuário comuns | Linha de base; inspecionar respostas brutas |
| Força bruta Hydra | `hydra` | mesmos 50 | Automatizado; utiliza modo enum nativo do Hydra |
| Módulo Metasploit | `auxiliary/scanner/ssh/ssh_enumuser` | mesmos 50 | Módulo de enumeração dedicado do framework |
| Impressão digital de banner | `BannerFingerprinter` personalizado | N/A | Vazamento de versão sem autenticação, verificação de CVE |
| Análise de temporização | `ResponseAnalyzer` personalizado | subconjunto válido vs inválido | Verificação estatística de canal lateral |
---
## O Que Foi Construído
Este projeto vai além de executar ferramentas — ele encapsula cada ataque e toda a lógica de detecção em uma base de código Python estruturada e fornece um orquestrador que executa todo o pipeline de ponta a ponta.
### Ferramentas de Ataque (`src/attack_tools/`)
**`ManualSSHEnumerator`** — Testa cada nome de usuário N vezes com `paramiko`, registrando
tempo preciso, tipo de resultado e banner SSH. Calcula média/desvio padrão por usuário.
Criticamente, **não** reutiliza conexões entre tentativas, garantindo que cada amostra capture
o tempo total de processamento do servidor.
**`BannerFingerprinter`** — Captura o banner SSH através de um socket TCP bruto (sem credenciais
necessárias). Analisa nome da implementação, string de versão e dica de SO. Cruza referências
com um registro local de CVEs. Uma versão como `OpenSSH_8.9p1 Ubuntu-3ubuntu0.6` revela
o software exato do servidor — potencialmente suficiente para identificar vulnerabilidades conhecidas
antes mesmo de qualquer autenticação ser tentada.
**`HydraAutomation`** — Wrapper de subprocesso em torno do Hydra. Analisa a saída padrão para extrair
logins bem-sucedidos, mensagens de erro e o próprio veredito de enumeração do Hydra
(`does not support user enumeration`).
**`MetasploitScanner`** — Escreve um script de recurso temporário e executa `msfconsole`
via subprocesso. Analisa a saída em busca de detecção de hardening e quaisquer nomes de usuário encontrados.
### Ferramentas de Detecção (`src/detection_tools/`)
**`LogParser`** — Analisador de auth.log baseado em regex, suportando cinco tipos de eventos SSH:
`failed_invalid_user`, `failed_valid_user`, `pre_auth_reject`, `accepted`,
`disconnected`. Retorna dicionários de eventos estruturados com timestamp, tipo de evento, nome de usuário,
IP de origem e porta.
**`ResponseAnalyzer`** — Realiza o teste t de Welch nas distribuições de temporização de nomes de usuário
válidos vs inválidos. Calcula delta de temporização (ms), valor-p, tamanho de efeito d de Cohen e
uma conclusão em linguagem simples. Limiar: delta ≥ 5ms E p < 0,05 dispara um aviso
de canal lateral.
**`EnumerationDetector`** — Quatro padrões de detecção:
- **Sondagens rápidas de usuário**: janela deslizante - mesmo IP, ≥10 nomes de usuário distintos em 60s
- **Correlação com wordlist**: taxa de correspondência entre nomes de usuário tentados e listas de ataque conhecidas
- **Temporização sequencial**: coeficiente de variação nos intervalos entre tentativas (baixo CoV → ferramenta)
- **Sondagem distribuída**: mesmo nome de usuário de múltiplos IPs (reconhecimento de credential stuffing)
**`AlertingSystem`** — Emissor de alertas leve. Gera alertas JSON com timestamp para
a saída padrão. Extensível com integrações de e-mail/SIEM/webhook conforme necessário.
### Orquestrador
**`run_investigation.py`** — Driver de linha de comando que executa todos os quatro estágios em sequência e escreve
os resultados em `data/results/`. Execute com `--help` para uso completo.```bash
python run_investigation.py \
-target 192.168.xx.xxxx \
-usernames data/wordlists/common-usernames-50.txt \
-log data/sample-logs/auth.log \
-known-valid root ubuntu \
-samples 10
Hipótese testada: O OpenSSH retorna uma mensagem de erro diferente para um utilizador inexistente do que para um utilizador existente com uma palavra-passe errada?```bash
$ ssh [email protected] Permission denied (publickey,password).
$ ssh [email protected] Permission denied (publickey,password).
**Resultado:** As respostas são idênticas byte por byte. O protocolo não vaza nada.
**Porquê:** Desde o OpenSSH 7.3, `UsePAM yes` força o servidor a executar uma operação `crypt()` fictícia para utilizadores inexistentes, igualando tanto o tempo como o caminho de erro de uma autenticação falhada real. A correção foi uma resposta direta ao CVE-2016-6210.
---
### Descoberta 2: Nenhum Canal Lateral de Tempo Detectado
**Hipótese testada:** Mesmo que as mensagens de erro coincidam, existe uma diferença de tempo mensurável entre nomes de utilizador válidos e inválidos que pudesse ser explorada estatisticamente?
Dez amostras de tempo foram recolhidas para cada um dos 50 nomes de utilizador. Utilizadores conhecidos como válidos (confirmados no sistema) foram comparados com o conjunto de utilizadores inválidos.
| Métrica | Valor |
|------------------------------|-------------------------------------|
| Tempo médio — utilizadores inválidos | ~312 ms |
| Tempo médio — utilizadores válidos | ~311 ms |
| Delta | **~1 ms** |
| Valor p do teste t de Welch | > 0,40 |
| Conclusão | **Nenhum canal lateral distinguível** |
O delta de ~1ms está muito abaixo do limiar de ruído de 5ms e não é estatisticamente significativo (p >> 0,05). O cálculo de hash fictício do OpenSSH é eficaz.
---
### Descoberta 3: Hydra Reporta Nenhum Suporte a Enumeração
O modo de enumeração SSH do Hydra depende de um de três sinais: mensagens de erro diferentes, tempos diferentes ou comportamento de conexão diferente. Com todos os três normalizados, o Hydra reporta explicitamente:```
[ERROR] target ssh://192.168.56.10:22/ does not support user enumeration
[STATUS] 50/50 tries completed, 0 valid logins found
Efeito colateral observado: Apesar de falhar na enumeração, todas as 50 tentativas são registradas em
/var/log/auth.log com IP de origem, timestamp e nome de usuário tentado. A presença do atacante
é totalmente visível.
O módulo auxiliary/scanner/ssh/ssh_enumuser verifica a versão do OpenSSH a partir do
banner antes de tentar a enumeração. Versões ≥ 7.3 com UsePAM yes são sinalizadas como
endurecidas e o módulo sai precocemente:```
[] 192.168.xx.xxxx:22 - SSH - Checking for vulnerability
[] 192.168.xx.xxxx:22 - SSH - Target is not vulnerable: OpenSSH 8.9p1 (hardened)
Esta é uma descoberta útil: o banner por si só comunica a postura defensiva do servidor a um atacante antes de qualquer tentativa de enumeração.
---
### Descoberta 5: A Detecção é Confiável Mesmo Quando a Enumeração Falha
O insight principal da perspectiva de um defensor: **o ataque gera ruído mesmo quando não tem sucesso**. Todos os quatro padrões de detecção dispararam corretamente contra o auth.log coletado:
| Detecção | Gatilho | Severidade |
|----------------------|-----------------------------------------------|----------|
| Sonda rápida de utilizador | IP Kali sondou 50 nomes de utilizador em <60s | ALTA |
| Correlação de wordlist | 48/50 nomes tentados corresponderam à wordlist | ALTA |
| Temporização sequencial | CoV entre tentativas = 0.04 (assinatura da ferramenta) | MÉDIA |
| Sonda apenas de banner | Desconexões pré-autenticação antes de qualquer nome de utilizador enviado | BAIXA |
---
## Processo de Raciocínio
### Porquê a Enumeração Manual SSH Primeiro?
O instinto de começar com testes manuais foi metodologicamente sólido: antes de confiar na saída da ferramenta, é necessário entender o que o protocolo bruto realmente diz. Executar `ssh ghost@target` e observar a mensagem de erro exata diz-lhe se há *alguma coisa* para enumerar antes de investir tempo em automação.
A primeira observação, de que `Permission denied (publickey,password)` parece idêntico independentemente de o utilizador existir ou não, foi a descoberta central. Tudo o que se seguiu foi validação desse resultado.
### Suposições Que Foram Feitas (e Reexaminadas)
A suposição inicial era que o Hydra e o Metasploit seriam *mais* capazes do que os testes manuais, por isso, se o teste manual falhasse, as ferramentas ainda poderiam ter sucesso. Isto acabou por estar errado na direção esperada, mas correto no *porquê*: as ferramentas não acrescentam capacidade aqui porque o protocolo em si não vaza o sinal. As ferramentas são apenas automação sobre o mesmo protocolo.
Uma segunda suposição que vale a pena examinar: a primeira tentativa manual foi notoriamente mais lenta do que as subsequentes, e a tentativa com senha bem-sucedida foi rápida. Isto foi inicialmente interpretado como um potencial sinal de temporização. Após reflexão, a lentidão foi devido à sobrecarga de estabelecimento da conexão TCP num estado de rede novo (resolução ARP, configuração da conexão), e não tempo de processamento no lado do servidor. Controlar isto — medindo a partir de `time.perf_counter()` *após* o handshake TCP, ou descartando a primeira amostra — teria sido mais rigoroso. A implementação do `ManualSSHEnumerator` aborda isto recolhendo 10 amostras por nome de utilizador e reportando a média/desvio padrão, o que dilui o ruído da primeira amostra.
### O Que Mudou Durante o Projeto
O âmbito original era estreito: executar três ferramentas, documentar se funcionam. O projeto evoluiu em duas direções:
**Para dentro (análise mais profunda):** Quando os resultados iniciais foram negativos, a pergunta natural tornou-se *porquê* — o que levou a ler os changelogs do OpenSSH, a CVE-2016-6210 e a implementação do `UsePAM`. Compreender o mecanismo é mais valioso do que apenas registar o resultado.
**Para fora (pivô de deteção):** Um resultado de ataque negativo ainda é um ponto de dados defensivo útil. O pivô para "embora a enumeração tenha falhado, o que é que o servidor viu?" levou aos componentes de análise de logs e engenharia de deteção, que transformaram um exercício unidimensional de execução de ferramentas numa investigação bilateral.
### O Que Seria Feito de Forma Diferente
As medições de temporização foram feitas numa rede virtual apenas de host, que introduz menos jitter do que uma rede real, mas também significa que os resultados são otimistas. Num ambiente real com latência TCP, jitter e retransmissões, o piso de ruído seria mais alto e a análise de temporização precisaria de mais amostras por nome de utilizador. Uma metodologia mais robusta testaria num link WAN simulado (usando `tc netem` para introduzir latência e jitter controlados) para ver como as conclusões se mantêm em condições realistas.
---
## Riscos de Segurança
Embora a enumeração não tenha tido sucesso neste laboratório, a superfície de ataque e os riscos associados são:
**Se a enumeração *fosse* possível (por exemplo, OpenSSH mais antigo, `UsePAM no`, pilha PAM personalizada):**
- Os atacantes poderiam restringir uma campanha de força bruta apenas a nomes de utilizador confirmados como válidos, reduzindo o risco de deteção e aumentando drasticamente a eficiência.
- Combinado com pulverização de senhas (uma senha comum em todos os nomes de utilizador válidos), isto contorna os bloqueios por utilizador do `MaxAuthTries`.
**Riscos que se aplicam mesmo com resistência à enumeração:**
- O banner SSH vaza a versão exata do OpenSSH e o SO. Um atacante que veja `OpenSSH_8.9p1` pode verificar imediatamente se a CVE-2024-6387 (regreSSHion) se aplica, antes de enviar um único pacote de autenticação.
- Todas as tentativas de enumeração são registadas com o IP de origem. Se a monitorização de logs estiver ausente, um ataque lento (uma tentativa por hora) pode sondar milhares de nomes de utilizador sem acionar alertas baseados em taxa.
- `PasswordAuthentication yes` mantém a superfície de ataque baseada em senha aberta mesmo que a enumeração não seja viável. Ataques de credenciais pós-OSINT (usando listas de senhas violadas contra nomes de utilizador derivados de OSINT) não requerem enumeração do lado do servidor.
---
## Estratégias de Mitigação
| Ameaça | Mitigação | Alteração de Configuração Necessária |
|---------------------------|------------------------------------------------------------------|-------------------------------------------|
| Canal lateral de temporização | Garantir `UsePAM yes` (padrão no Ubuntu) | Nenhuma — já é padrão |
| Divulgação de versão do banner | `VersionAddendum none` e `DebianBanner no` em `sshd_config` | Sim |
| Ataques baseados em senha | `PasswordAuthentication no` — autenticação apenas por chave | Sim |
| Força bruta após OSINT | `fail2ban` com jail `sshd` | Instalar + configurar |
| Enumeração lenta | Envio de logs para SIEM; alerta em >N nomes de utilizador distintos/IP/hora | SIEM necessário |
| Login root | `PermitRootLogin no` | Sim (o padrão é `prohibit-password`) |
| Desconexões pré-autenticação | `MaxStartups 10:30:60` para limitar a taxa de conexões não autenticadas | Sim |
**Adições mínimas recomendadas ao `sshd_config` para uma implementação reforçada:**```
PasswordAuthentication no
PermitRootLogin no
MaxAuthTries 3
MaxStartups 10:30:60
VersionAddendum none
LogLevel VERBOSE
O projeto atual testa um protocolo em uma configuração. Extensões naturais:
Enumerar outros serviços no mesmo host. SMTP (VRFY/EXPN), LDAP (consultas de atributos), formulários de login HTTP e SNMP são vetores comuns de vazamento de nomes de usuário na mesma máquina que é reforçada no SSH. Um estudo comparativo entre serviços produziria um quadro de risco mais completo.
Testar configurações SSH não padrão. UsePAM no, módulos PAM personalizados, backends de autenticação Kerberos e versões mais antigas do OpenSSH (implantadas em sistemas embarcados, appliances de rede) ainda podem apresentar vazamentos de temporização. Testar o mesmo pipeline contra uma configuração deliberadamente vulnerável demonstraria o contraste.
Detecção ao vivo com inotify. A detecção atual é executada post-hoc em um arquivo de log copiado. Uma versão de nível de produção usaria inotify (ou tail -f + uma thread de análise) para detectar e alertar em tempo quase real, dentro de segundos após o início de uma tentativa de enumeração.
Detecção em nível de rede. Auth.log é um artefato baseado em host. Complemente-o com detecção em nível de pacote: conexões TCP de curta duração para a porta 22 que fecham antes de completar o handshake de autenticação são uma assinatura de fingerprinting apenas de banner. Isso poderia ser implementado como uma regra Zeek ou Suricata.
Jupyter notebooks para relatórios estatísticos. Os dados de temporização coletados são adequados para visualização - gráficos de caixa das distribuições de temporização por nome de usuário, gráficos de dispersão da frequência de tentativas ao longo do tempo, mapas de calor de IPs de origem. Os notebooks tornariam a análise reproduzível e compartilhável.
ssh-enumeration-analysis/ │ ├── README.md ├── run_investigation.py ← Full pipeline orchestrator (start here) ├── requirements.txt │ ├── src/ │ ├── attack_tools/ │ │ ├── init.py │ │ ├── manual_ssh.py ← Paramiko-based timing probe │ │ ├── banner_fingerprinter.py ← No-auth banner grab + CVE lookup │ │ ├── hydra_automation.py ← Hydra subprocess wrapper │ │ └── metasploit_scanner.py ← MSF console automation │ │ │ └── detection_tools/ │ ├── init.py │ ├── log_parser.py ← auth.log regex parser │ ├── response_analyzer.py ← Welch t-test + Cohen's d │ ├── pattern_detector.py ← 4 detection patterns │ └── alerting_system.py ← JSON alert emitter │ ├── data/ │ ├── sample-logs/ │ │ ├── auth-baseline.log ← Normal SSH activity (no attacks) │ │ ├── auth-hydra-run.log ← Captured during Hydra trial │ │ └── auth-msf-run.log ← Captured during Metasploit trial │ │ │ ├── wordlists/ │ │ ├── common-usernames-50.txt │ │ └── common-usernames-100.txt │ │ │ └── results/ ← Auto-generated (gitignored) │ ├── investigation-summary.json │ ├── manual-enumeration-results.json │ ├── timing-analysis.json │ └── detection-report.json │ ├── tests/ │ ├── test_enumeration.py │ ├── test_detection.py │ └── test_log_parser.py │ ├── case-study/ │ └── User_Enumeration_attempt_using_manual_SSH.docx │ └── screenshots/ ├── manual-ssh-same-response.png ├── hydra-no-enumeration-support.png ├── metasploit-hardened-detected.png ├── auth-log-hydra-evidence.png └── detection-alerts-output.png
---
## ⚡ Início Rápido```bash
# 1. Clone and install dependencies
git clone https://github.com/Alisha-chaudhary/ssh-enum
cd ssh-enum
pip install -r requirements.txt
# 2. Run just the banner fingerprint (no credentials needed)
python -c "
from src.attack_tools.banner_fingerprinter import BannerFingerprinter
r = BannerFingerprinter().grab('192.168.xx.xxxx')
print(r.raw_banner, r.cves)
"
# 3. Run the full investigation pipeline
python run_investigation.py \
-target 192.168.xx.xxxx \
-usernames data/wordlists/common-usernames-50.txt \
-log data/sample-logs/auth-hydra-run.log \
-known-valid root ubuntu \
-samples 10
# 4. Analyse a log file only (no live target needed)
python -c "
from src.detection_tools.pattern_detector import EnumerationDetector
d = EnumerationDetector('data/sample-logs/auth-hydra-run.log')
import json; print(json.dumps(d.run_all(), indent=2))
"
Requisitos:``` paramiko>=3.3.1 scipy>=1.11.0 Hydra and Metasploit must be installed separately (pre-installed on Kali Linux).
---
## 📚 Referências
| Recurso | Relevância |
|--------------------------------------------------------------------------------------|--------------------------------------------------|
| [CVE-2016-6210](https://nvd.nist.gov/vuln/detail/CVE-2016-6210) | O canal lateral de temporização testado por este projeto |
| [CVE-2024-6387 (regreSSHion)](https://nvd.nist.gov/vuln/detail/CVE-2024-6387) | RCE não autenticada em OpenSSH ≤ 9.7 |
| [Manual do sshd_config do OpenSSH](https://man.openbsd.org/sshd_config) | `UsePAM`, `MaxAuthTries`, `VersionAddendum` |
| [OWASP — Enumeração de Usuários](https://owasp.org/www-community/attacks/User_Enumeration) | Padrões gerais de ataque de enumeração |
| [RFC 4252 — Protocolo de Autenticação SSH](https://tools.ietf.org/html/rfc4252) | Especificação do protocolo; define comportamento de mensagens de erro |
| [Documentação do fail2ban](https://www.fail2ban.org/wiki/index.php/Main_Page) | Limitação de taxa e bloqueio de IP |
---
## 🎓 Habilidades Demonstradas
| Domínio | Evidência |
|-------------------------|----------------------------------------------------------------------------------------------------------|
| Internos do Protocolo SSH | Compreensão da normalização de temporização do `UsePAM`, correção do CVE-2016-6210, exposição de informações do banner |
| Segurança Ofensiva | Uso prático do Hydra, Metasploit e sondagem personalizada com Paramiko em uma metodologia estruturada |
| Análise Estatística | Teste t de Welch, d de Cohen, coeficiente de variação aplicados a dados de temporização |
| Engenharia de Detecção | Detecção de IOC baseada em logs em quatro tipos de padrão; saída de alerta estruturada |
| Engenharia Python | Dataclasses, dicas de tipo, automação com subprocess, análise com regex, bibliotecas estatísticas |
| Pesquisa em Segurança | Hipótese → experimento controlado → coleta de evidências → descobertas documentadas → conclusões acionáveis |
---
**Status:** Completo | **Testado em:** Ubuntu Server 22.04 LTS + OpenSSH 8.9p1 | Kali Linux 2024.1