1. 项目概述:从“撞库”到“撞钥”的攻防演进
在运维和渗透测试的圈子里,SSH(Secure Shell)密钥认证因其安全性远超密码,早已成为服务器远程管理的标配。我们习惯了生成一对公私钥,把公钥扔到服务器上,私钥妥善保管,从此告别繁琐的密码输入。然而,安全从来都是一个动态平衡的过程。当大量私钥文件(可能是离职员工遗留的、备份泄露的、或从某些渠道获取的)散落在各处时,一个传统但被低估的攻击面就浮现了:私有密钥的批量验证与利用。这不再是简单的密码“撞库”,而是升级版的“撞钥”——用海量的私钥文件,去尝试登录可能存在对应公钥的SSH服务器。
我最近在梳理内部安全资产时,就遇到了这样的场景:一个陈旧的备份盘里发现了上百个未经妥善处理的.pem、.ppk、id_rsa文件。手动一个个去测试它们是否还能登录现存的主机?这无异于大海捞针,效率极低。这时,一个名为Crowbar的工具进入了我的视野。它并非新生事物,但在针对SSH私钥的批量、高效验证方面,其设计思路和实战效果让我印象深刻。简单来说,Crowbar 是一个支持多种协议(如SSH、RDP、VNC)的暴力破解工具,但其核心优势在于对基于密钥的认证进行了高度优化。它能够自动化地加载一个私钥列表,并尝试用它们连接目标服务器,省去了手动配置、转换密钥格式、逐一测试的繁琐过程。对于安全审计人员,这是快速排查“僵尸密钥”隐患的利器;对于攻击者,这则是一种隐蔽且高效的横向移动手段。本文将深入拆解如何利用 Crowbar 进行 SSH 私钥的批量验证,并分享其中的技术细节、实战步骤以及我踩过的坑。
2. Crowbar工具核心原理与优势解析
2.1 为什么是Crowbar,而不是传统脚本?
在接触Crowbar之前,很多人(包括我)的第一反应可能是写个Python脚本,用paramiko库遍历私钥去连接。这当然可行,但Crowbar提供了几个难以替代的优势:
- 协议级优化与稳定性:Crowbar直接集成了对SSH协议(以及RDP、VNC等)的客户端实现。它并非简单地封装系统命令,而是实现了协议本身的逻辑。这意味着它在处理网络超时、连接拒绝、协议版本协商等边缘情况时更为健壮,避免了自制脚本因网络波动或服务器特殊配置导致的意外崩溃。
- 高效的并发与连接池管理:这是其“高效”二字的精髓。Crowbar内置了成熟的并发控制机制。你可以指定线程数,它会自动管理连接池,同时发起多个认证尝试,极大提升了在拥有大量私钥和目标IP时的测试速度。手动脚本要实现稳定的高并发,需要处理复杂的线程/协程同步和错误处理,而Crowbar开箱即用。
- 灵活的密钥与目标输入:它支持从文件读取私钥列表,也支持从标准输入读取。目标可以是单个IP、IP范围(CIDR格式)或从文件读取的IP列表。这种灵活性使得它可以轻松融入自动化流水线,与
nmap、masscan等端口扫描工具的输出结果联动。 - 内置的密钥格式处理:SSH私钥有多种格式(OpenSSH格式、PEM格式、PuTTY的PPK格式等),且可能受密码保护。Crowbar能够自动识别并尝试解析这些格式。对于受密码保护的密钥,它可以配合密码字典进行破解,这是单纯测试密钥有效性之外的又一重能力。
- 结果输出清晰:成功匹配的“密钥-目标”对会被清晰地输出到屏幕或文件,包括使用的用户名(SSH认证需要用户名+私钥)、目标IP和端口,一目了然。
2.2 核心工作流程拆解
理解Crowbar的工作流程,有助于我们在使用时做出正确的配置和问题排查。其核心流程可以概括为以下几步:
- 输入阶段:工具加载两个核心列表——私钥文件列表和目标服务器列表。同时,需要指定或使用默认的用户名列表(因为SSH认证是
username@host的形式)。 - 组合与调度阶段:Crowbar会计算所有可能的组合:每个用户 × 每个私钥 × 每个目标。然后,根据设置的并发线程数,将这些组合任务放入队列进行调度。
- 连接与认证阶段:针对每一个任务组合,Crowbar会:
- 建立到目标服务器指定端口(默认22)的TCP连接。
- 进行SSH协议版本协商。
- 发起基于密钥的认证请求。它会将私钥对应的公钥(或从私钥推导出的公钥)发送给服务器。
- 等待服务器响应。如果服务器返回认证成功,则记录该组合;如果失败(密钥不匹配、用户不存在、连接被拒等),则快速失败并尝试下一个组合。
- 结果处理阶段:所有任务完成后,输出成功的连接信息。对于受密码保护的密钥,如果在提供了密码字典的情况下认证失败,会提示密钥可能受密码保护。
注意:Crowbar的“暴力破解”体现在对“密钥-用户-目标”这个三维空间的枚举上,而非对密钥本身进行密码学破解。其前提是你已经拥有了私钥文件实体。
3. 实战环境搭建与工具准备
3.1 Crowbar的安装与依赖
Crowbar通常由Go语言编写,这使其安装非常方便。以下是主流的安装方法:
方法一:从源码编译(推荐,获取最新版)确保系统已安装Go语言环境(1.16+)。
git clone https://github.com/galkan/crowbar.git cd crowbar go build编译后会在当前目录生成名为crowbar(Linux/macOS)或crowbar.exe(Windows)的可执行文件。
方法二:直接下载预编译二进制在项目的Release页面下载对应操作系统和架构的二进制文件,解压后即可运行。
方法三:通过包管理器(如Kali Linux)在Kali等渗透测试发行版中,可以直接通过apt安装,但版本可能不是最新的。
sudo apt update sudo apt install crowbar安装完成后,可以通过./crowbar -h或crowbar -h查看帮助信息,验证安装是否成功。
3.2 密钥与目标清单的准备
这是实战前最关键的准备工作,直接决定了测试的覆盖面和效率。
1. 私钥集合整理 (-k/--keyfile)你需要一个文本文件,里面每一行都是一个私钥文件的绝对路径或相对路径。
# 示例:keys.txt /home/auditor/.ssh/old_id_rsa /tmp/leaked_keys/backup_server.pem ./found_keys/key.ppk /data/keys/employee_departed.key- 如何收集:这可能来自备份服务器、代码仓库的历史记录、离职员工的工作站镜像、甚至是一些公开的漏洞披露数据。在授权测试中,务必确保你拥有这些密钥的使用权限。
- 格式处理:如果密钥是PPK格式(PuTTY私有密钥),Crowbar可以直接读取。如果遇到其他罕见格式,可能需要先用
puttygen或ssh-keygen进行转换。
2. 目标服务器列表 (-s/--server)目标可以是以下几种形式:
- 单个IP:
-s 192.168.1.100 - IP范围(CIDR):
-s 192.168.1.0/24 - 从文件读取:
-S servers.txt,文件中每行一个IP或主机名。
# 示例:servers.txt 192.168.1.10 192.168.1.11 web-server.prod.internal 10.10.20.50最佳实践:建议先使用端口扫描工具(如nmap -p 22 --open -oG ssh_hosts.txt 192.168.1.0/24)筛选出开放了SSH端口(默认22)的主机,再将结果整理成目标列表,这样可以避免对无关主机发起大量无效连接,提升效率。
3. 用户名列表 (-u/--username)SSH认证需要用户名。你可以指定单个用户(如-u root),也可以提供一个用户名字典文件(-U users.txt)。常见的用户名包括:root,admin,ubuntu,centos,deploy,git,jenkins等。根据目标系统的性质(是Linux服务器、网络设备还是Git服务)来准备列表。
4. (可选)密钥密码字典 (-p/--password)如果私钥本身受密码(passphrase)保护,你需要一个密码字典文件来尝试破解。这个字典可以与常规密码爆破字典通用。
4. 核心操作流程与参数详解
4.1 基础批量验证命令
掌握了输入文件后,一个最基础的批量验证命令如下:
./crowbar -b sshkey -s 192.168.1.0/24 -u root -U common_users.txt -k found_keys.txt -o results.txt让我们拆解这个命令:
-b sshkey: 指定攻击模式为sshkey,这是核心参数,告诉Crowbar我们使用密钥认证。-s 192.168.1.0/24: 指定目标网段。-u root: 指定一个默认用户root,Crowbar会先尝试这个用户。-U common_users.txt: 同时加载一个用户名字典文件,进行多用户尝试。-k found_keys.txt: 指定私钥路径列表文件。-o results.txt: 将成功的结果输出到results.txt文件。
执行后,Crowbar会开始工作,屏幕上会滚动显示尝试的进度。成功的连接会像这样显示:
[+] SSHKEY-SUCCESS: 192.168.1.15:22 - root - /home/auditor/.ssh/old_id_rsa4.2 高级参数调优与性能控制
为了应对不同规模的网络和不同的测试环境,Crowbar提供了一系列调优参数:
-t/--threads:并发线程数。这是影响速度最关键的因素。默认值可能较低(如4)。在内网测试时,可以根据自身机器性能和网络状况适当调高,例如-t 50。但要注意,过高的并发可能导致本地端口耗尽或被目标网络设备误判为攻击而拦截。实操心得:我的经验是,针对一个C类网段(254个IP),设置30-50个线程是相对安全和高效的起点。可以先从20开始,观察系统负载和网络状况,再逐步增加。
-T/--timeout:连接超时时间(秒)。默认值可能不足以应对网络延迟或无响应主机。对于跨国或延迟较高的网络,可以设置为-T 10甚至更高。设置太短会导致漏报(误判可达主机为不可达),太长则会显著降低整体速度。-n/--port:目标端口。如果目标服务器的SSH服务不在默认的22端口,必须用此参数指定,例如-n 2222。-w/--wait:请求间隔时间(毫秒)。为了避免触发目标系统的安全警报(如fail2ban),可以在每次尝试之间插入一个短暂的延迟,例如-w 100表示间隔100毫秒。这在针对生产环境进行低调测试时非常有用。-d/--debug:调试模式。当遇到连接问题或奇怪的行为时,开启调试模式会输出非常详细的协议交互信息,对于排查问题至关重要。
一个调优后的、更稳健的命令示例:
./crowbar -b sshkey -S scanned_ssh_hosts.txt -U users.txt -k keys.txt -t 30 -T 8 -w 50 -o detailed_results.txt4.3 集成化工作流示例
在实际的渗透测试或安全审计中,Crowbar很少孤立运行。它通常是一个工作流中的一环。下面是一个典型的集成化流程:
资产发现与端口扫描:
# 使用masscan进行快速全网段扫描,找出开放22端口的主机 sudo masscan -p22 10.0.0.0/8 --rate=1000 -oL masscan_ssh.txt # 从结果中提取IP地址 grep -oP 'Host: \K[\d.]+' masscan_ssh.txt > ssh_hosts.txt整理待测试密钥:将收集到的所有私钥文件路径整理到
all_keys.txt。执行Crowbar批量验证:
./crowbar -b sshkey -S ssh_hosts.txt -U common_linux_users.txt -k all_keys.txt -t 40 -T 5 -o potential_access.txt结果验证与利用:对于
potential_access.txt中成功的条目,切勿直接用于未授权访问。在授权测试中,应使用ssh -i [private_key] [user]@[host]命令进行手动验证,确认权限级别,并按照测试范围进行后续操作。
5. 常见问题、排查技巧与防御建议
5.1 实战中遇到的典型问题与解决
在多次使用Crowbar的过程中,我遇到了不少问题,这里总结成排查表:
| 问题现象 | 可能原因 | 排查与解决思路 |
|---|---|---|
| 连接被立即拒绝 (Connection refused) | 目标端口未开放或IP错误;本地防火墙/出网策略限制。 | 1. 用telnet [IP] [PORT]或nc -zv [IP] [PORT]验证端口可达性。2. 检查Crowbar命令中的 -s/-S和-n参数是否正确。3. 检查测试机本身的网络出口和防火墙规则。 |
| 超时无响应 (Timeout) | 网络路由问题;目标主机防火墙(如iptables, cloud security group)丢弃了包;-T参数设置过短。 | 1. 适当增加-T超时时间(如设为10秒)。2. 从测试机 ping或traceroute目标IP,检查基础网络连通性。3. 确认目标主机的安全组/防火墙是否允许测试源IP的访问。 |
| 大量提示“SSH协议版本不匹配” | 目标主机运行着非常古老或非标准的SSH服务。 | Crowbar默认可能支持较新的协议。可以尝试其他SSH客户端工具手动连接,查看服务端版本。对于审计,这类主机本身可能就是安全风险。 |
| 密钥文件解析错误 | 密钥格式Crowbar不支持;密钥文件已损坏;密钥受密码保护但未提供密码字典。 | 1. 使用ssh-keygen -l -f [keyfile]检查密钥是否有效。2. 对于PPK格式,可用 puttygen转换为OpenSSH格式再尝试。3. 如果密钥有密码,确保使用 -p或-P参数提供密码字典。 |
| 成功率极低,甚至为0 | 密钥与目标完全不匹配(正常情况);用户名列表不正确;目标服务器禁用了密钥认证。 | 1.这是最常见的情况,说明你拥有的密钥集与目标服务器没有交集,这本身就是一个重要的安全结论——泄露的密钥未在现网使用。 2. 检查 /etc/ssh/sshd_config中PubkeyAuthentication是否设为yes(需在已授权的机器上查看)。3. 扩大用户名列表,尝试更常见的服务账户。 |
| 程序运行缓慢或卡住 | 并发线程(-t)设置过高,导致系统资源耗尽或网络拥堵;某个目标IP无响应导致线程挂起。 | 1. 降低并发线程数,例如从50降到20。 2. 适当降低超时时间 -T,避免在“僵尸主机”上等待过久。3. 使用 -d调试模式观察卡在哪一步。 |
5.2 针对此类攻击的防御建议
作为一名安全从业者,了解攻击方法是为了更好地防御。针对SSH私钥批量验证攻击,服务器端可以采取以下措施:
严格的密钥生命周期管理:
- 定期轮换:为所有用户和服务账户的SSH密钥设定有效期,强制定期更换。
- 集中管理与吊销:使用类似
ssh-certificate-authority(SSH CA)的体系。服务器不再信任分散的公钥文件,而是信任CA签发的证书。当员工离职或密钥疑似泄露时,只需在CA吊销证书即可,无需遍历所有服务器。 - 及时清理:定期审计服务器上的
~/.ssh/authorized_keys文件,移除不再使用的、过期的或来源不明的公钥。
网络层访问控制:
- 限制源IP:通过防火墙或云安全组,将SSH端口(22)的访问权限限制在特定的、可信的管理员IP地址段。
- 使用跳板机(Bastion Host):所有SSH连接必须先通过一个强化安全的跳板机,在跳板机上实施强认证和审计,内部服务器则拒绝外部直接SSH连接。
服务端强化配置:
- 禁用root密钥登录:在
sshd_config中设置PermitRootLogin prohibit-password或without-password,并尽可能使用sudo提权而非直接root登录。 - 使用非标准端口:虽然这并非安全措施(security through obscurity),但可以显著减少互联网上的自动化扫描和撞库尝试,间接降低被此类工具盯上的概率。
- 部署入侵检测:使用如
fail2ban、denyhosts等工具,监控认证日志。虽然Crowbar单次尝试看起来像合法密钥登录,但如果同一源IP在极短时间内用大量不同密钥尝试不同用户,仍然会形成异常模式,可以被规则捕捉。
- 禁用root密钥登录:在
客户端安全:
- 私钥加密:生成密钥对时,务必为私钥设置强密码(passphrase)。
- 安全存储:私钥文件应视为最高机密,存储在加密磁盘或硬件安全模块(HSM)中,避免明文存放在代码仓库、共享目录或未加密的备份中。
- 使用代理(Agent):本地使用
ssh-agent管理解密的私钥,避免私钥文件在磁盘上频繁被读取。
5.3 我的实操心得与边界思考
最后,分享几点从实战中得来的体会:
- 工具是双刃剑:Crowbar的强大效率在授权测试中能节省大量时间,快速定位安全隐患。但正因如此,它也可能被恶意使用。确保你只在拥有明确书面授权的范围内对属于你的资产进行测试。
- “零结果”的价值:一次全面的Crowbar扫描后,如果没有发现任何有效的密钥对,请不要失望。这个“阴性结果”具有极高的安全价值:它证明当前收集的泄露密钥库与你的现网系统没有交集,这是一个积极的安全信号。你应该将这次扫描的结果记录在审计报告中。
- 关注上下文信息:成功匹配到一个密钥后,不要止步于“能登录”。要进一步思考:这个密钥对应的用户是谁?这个服务器是什么角色(数据库、Web服务器、跳板机)?从这个服务器能否进行横向移动?这些上下文信息对于评估真实风险至关重要。
- 自动化与定期执行:可以将Crowbar扫描集成到定期的安全审计自动化流程中。例如,每季度自动执行一次,使用的密钥库可以更新为从内部代码扫描、外部威胁情报获取的最新泄露密钥数据。这能实现持续的风险监控。
通过Crowbar进行SSH私钥的批量验证,揭示了一个常被忽视的攻击面。它提醒我们,安全是一个覆盖资产全生命周期的持续过程,不仅在于设置复杂的密码,更在于对密钥、凭证这类“信任文件”的严格管理。作为防御方,建立完善的密钥管理体系与访问控制策略,远比在事件发生后疲于奔命更为有效。