383 lines
20 KiB
YAML
383 lines
20 KiB
YAML
metadata:
|
||
version: "2.0"
|
||
description: "SSH安全配置检查项"
|
||
|
||
checks:
|
||
# 2.2 禁止root用户直接SSH远程登录系统
|
||
# 要求:限制root用户直接通过SSH远程登录系统,执行管理员权限操作时,需先以普通权限用户登录,再通过su或sudo命令切换到root帐号后执行
|
||
- id: "ssh_permit_root_login"
|
||
category: "SSH安全配置"
|
||
title: "禁止root远程登录"
|
||
description: "限制root用户直接通过SSH远程登录系统,执行管理员权限操作时,需先以普通权限用户登录,再通过su或sudo命令切换到root帐号后执行。该配置可降低root帐号密码泄露带来的风险。"
|
||
tags: ["low", "medium", "high", "ssh", "authentication"]
|
||
check_script: |
|
||
# 按照标准检测方法:grep -E "^PermitRootLogin" /etc/ssh/sshd_config
|
||
# 使用 || true 避免grep未找到匹配时导致脚本退出(set -e模式下)
|
||
permit_root_result=$(grep -E "^PermitRootLogin" /etc/ssh/sshd_config 2>/dev/null || true)
|
||
|
||
if [ -z "$permit_root_result" ]; then
|
||
# 无相关配置项,不符合要求
|
||
echo "FAIL: 未配置PermitRootLogin参数,使用默认值,不符合安全要求"
|
||
echo "当前配置: (无)"
|
||
echo "建议: 编辑/etc/ssh/sshd_config,添加或修改'PermitRootLogin no',然后重启ssh服务"
|
||
exit 1
|
||
elif echo "$permit_root_result" | grep -qE "^PermitRootLogin\\s+no"; then
|
||
# 输出结果为"PermitRootLogin no",符合要求
|
||
echo "PASS: root用户无法直接SSH登录"
|
||
echo "当前配置: $permit_root_result"
|
||
exit 0
|
||
else
|
||
# 输出结果为"PermitRootLogin yes"或其他值,不符合要求
|
||
echo "FAIL: 允许root用户直接SSH登录,违反安全策略"
|
||
echo "当前配置: $permit_root_result"
|
||
echo "建议: 编辑/etc/ssh/sshd_config,将'PermitRootLogin'设置为'no',然后重启ssh服务"
|
||
exit 1
|
||
fi
|
||
fix_script: |
|
||
# 删除所有PermitRootLogin配置行(包括注释)
|
||
sed -i '/^[[:space:]]*#.*PermitRootLogin/d' /etc/ssh/sshd_config
|
||
sed -i '/^PermitRootLogin/d' /etc/ssh/sshd_config
|
||
# 添加新配置
|
||
echo "PermitRootLogin no" >> /etc/ssh/sshd_config
|
||
# 重启SSH服务
|
||
systemctl restart sshd
|
||
# 验证配置
|
||
verify_result=$(grep -E "^PermitRootLogin" /etc/ssh/sshd_config)
|
||
if echo "$verify_result" | grep -qE "^PermitRootLogin\\s+no"; then
|
||
echo "已禁止root用户直接SSH登录"
|
||
echo "验证配置: $verify_result"
|
||
else
|
||
echo "警告: 配置可能未正确生效,请手动检查"
|
||
exit 1
|
||
fi
|
||
|
||
# 2.3 禁用密码直接登录SSH远程系统
|
||
# 要求:禁止通过密码验证的方式登录SSH远程系统,仅允许使用SSH密钥对进行身份验证。密钥认证相比密码认证安全性更高,可有效抵御暴力破解攻击。
|
||
- id: "ssh_password_auth"
|
||
category: "SSH安全配置"
|
||
title: "禁用SSH密码认证"
|
||
description: "禁止通过密码验证的方式登录SSH远程系统,仅允许使用SSH密钥对进行身份验证。密钥认证相比密码认证安全性更高,可有效抵御暴力破解攻击。"
|
||
tags: ["medium", "high", "ssh", "authentication"]
|
||
check_script: |
|
||
# 按照标准检测方法:grep -E "^PasswordAuthentication" /etc/ssh/sshd_config
|
||
# 使用 || true 避免grep未找到匹配时导致脚本退出(set -e模式下)
|
||
password_auth_result=$(grep -E "^PasswordAuthentication" /etc/ssh/sshd_config 2>/dev/null || true)
|
||
|
||
if [ -z "$password_auth_result" ]; then
|
||
# 无相关配置项,不符合要求
|
||
echo "FAIL: 未配置PasswordAuthentication参数,使用默认值,不符合安全要求"
|
||
echo "当前配置: (无)"
|
||
echo "建议: 编辑/etc/ssh/sshd_config,添加或修改'PasswordAuthentication no',然后重启ssh服务"
|
||
echo "注意: 请先配置SSH密钥登录,确保客户端已生成密钥对,并将公钥上传至服务器目标用户的~/.ssh/authorized_keys文件中,避免被锁定在系统外"
|
||
exit 1
|
||
elif echo "$password_auth_result" | grep -qE "^PasswordAuthentication\\s+no"; then
|
||
# 输出结果为"PasswordAuthentication no",符合要求
|
||
echo "PASS: SSH密码认证已禁用"
|
||
echo "当前配置: $password_auth_result"
|
||
exit 0
|
||
else
|
||
# 输出结果为"PasswordAuthentication yes"或其他值,不符合要求
|
||
echo "FAIL: SSH密码认证未禁用,存在暴力破解风险"
|
||
echo "当前配置: $password_auth_result"
|
||
echo "建议: 编辑/etc/ssh/sshd_config,将'PasswordAuthentication'设置为'no',然后重启ssh服务"
|
||
echo "注意: 请先配置SSH密钥登录,确保客户端已生成密钥对,并将公钥上传至服务器目标用户的~/.ssh/authorized_keys文件中,且文件权限设置为600,避免被锁定在系统外"
|
||
exit 1
|
||
fi
|
||
fix_script: |
|
||
# 删除所有PasswordAuthentication配置行(包括注释)
|
||
sed -i '/^[[:space:]]*#.*PasswordAuthentication/d' /etc/ssh/sshd_config
|
||
sed -i '/^PasswordAuthentication/d' /etc/ssh/sshd_config
|
||
# 添加新配置
|
||
echo "PasswordAuthentication no" >> /etc/ssh/sshd_config
|
||
# 重启SSH服务
|
||
systemctl restart sshd
|
||
# 验证配置
|
||
verify_result=$(grep -E "^PasswordAuthentication" /etc/ssh/sshd_config)
|
||
if echo "$verify_result" | grep -qE "^PasswordAuthentication\\s+no"; then
|
||
echo "已禁用SSH密码认证"
|
||
echo "验证配置: $verify_result"
|
||
echo "提示: 请确保已配置SSH密钥登录,并测试密钥登录正常后再关闭当前会话"
|
||
else
|
||
echo "警告: 配置可能未正确生效,请手动检查"
|
||
exit 1
|
||
fi
|
||
|
||
# 2.4 检查SSH使用的协议版本
|
||
# 要求:SSH协议版本1存在安全漏洞(如中间人攻击风险、加密强度不足等),需禁用SSH协议版本1,仅使用安全性更高的协议版本2
|
||
- id: "ssh_protocol_version"
|
||
category: "SSH安全配置"
|
||
title: "检查SSH协议版本"
|
||
description: "SSH协议版本1存在安全漏洞(如中间人攻击风险、加密强度不足等),需禁用SSH协议版本1,仅使用安全性更高的协议版本2。"
|
||
tags: ["low", "medium", "high", "ssh", "protocol"]
|
||
check_script: |
|
||
# 按照标准检测方法:grep -iE "^\s*Protocol\s+" /etc/ssh/sshd_config | tail -1
|
||
protocol_result=$(grep -iE "^\s*Protocol\s+" /etc/ssh/sshd_config 2>/dev/null | tail -1)
|
||
|
||
# 验证服务当前使用的协议版本(OpenSSH版本不小于2.9)
|
||
ssh_version=$(ssh -V 2>&1 | grep -oE "OpenSSH_[0-9]+\.[0-9]+" | cut -d'_' -f2)
|
||
ssh_major=$(echo "$ssh_version" | cut -d'.' -f1)
|
||
ssh_minor=$(echo "$ssh_version" | cut -d'.' -f2)
|
||
|
||
# 检查OpenSSH版本是否满足要求(>= 2.9)
|
||
version_check_passed=false
|
||
if [ -n "$ssh_major" ] && [ -n "$ssh_minor" ]; then
|
||
if [ "$ssh_major" -gt 2 ] || ([ "$ssh_major" -eq 2 ] && [ "$ssh_minor" -ge 9 ]); then
|
||
version_check_passed=true
|
||
fi
|
||
fi
|
||
|
||
# 判断协议配置
|
||
if [ -z "$protocol_result" ]; then
|
||
# 无相关配置项,使用默认值(SSH服务默认使用版本2),符合要求
|
||
if [ "$version_check_passed" = true ]; then
|
||
echo "PASS: 未配置Protocol参数,使用默认值(协议版本2),符合要求"
|
||
echo "当前配置: (无,使用默认值)"
|
||
echo "OpenSSH版本: $ssh_version (>= 2.9,符合要求)"
|
||
exit 0
|
||
else
|
||
echo "WARN: 未配置Protocol参数,使用默认值(协议版本2),但OpenSSH版本可能不符合要求"
|
||
echo "当前配置: (无,使用默认值)"
|
||
echo "OpenSSH版本: $ssh_version (要求 >= 2.9)"
|
||
exit 0
|
||
fi
|
||
elif echo "$protocol_result" | grep -qiE "Protocol\s+2"; then
|
||
# 输出结果为"Protocol 2",符合要求
|
||
if [ "$version_check_passed" = true ]; then
|
||
echo "PASS: SSH协议版本配置为2,符合要求"
|
||
echo "当前配置: $protocol_result"
|
||
echo "OpenSSH版本: $ssh_version (>= 2.9,符合要求)"
|
||
exit 0
|
||
else
|
||
echo "WARN: SSH协议版本配置为2,但OpenSSH版本可能不符合要求"
|
||
echo "当前配置: $protocol_result"
|
||
echo "OpenSSH版本: $ssh_version (要求 >= 2.9)"
|
||
exit 0
|
||
fi
|
||
elif echo "$protocol_result" | grep -qiE "Protocol\s+1"; then
|
||
# 输出结果为"Protocol 1"或"Protocol 1,2",不符合要求
|
||
echo "FAIL: SSH协议版本配置包含版本1,存在安全漏洞风险"
|
||
echo "当前配置: $protocol_result"
|
||
echo "OpenSSH版本: $ssh_version"
|
||
echo "建议: 编辑/etc/ssh/sshd_config,将'Protocol'设置为'2',然后重启ssh服务"
|
||
echo "或者: 直接删除Protocol配置项,使用默认值(协议版本2)"
|
||
exit 1
|
||
else
|
||
# 其他情况(如Protocol 2,1等)
|
||
echo "FAIL: SSH协议版本配置异常"
|
||
echo "当前配置: $protocol_result"
|
||
echo "OpenSSH版本: $ssh_version"
|
||
echo "建议: 编辑/etc/ssh/sshd_config,将'Protocol'设置为'2',然后重启ssh服务"
|
||
exit 1
|
||
fi
|
||
fix_script: |
|
||
# 删除所有Protocol配置行(包括注释)
|
||
sed -i '/^[[:space:]]*#.*Protocol/d' /etc/ssh/sshd_config
|
||
sed -i '/^[[:space:]]*Protocol/d' /etc/ssh/sshd_config
|
||
# 添加新配置
|
||
echo "Protocol 2" >> /etc/ssh/sshd_config
|
||
# 重启SSH服务
|
||
systemctl restart sshd
|
||
# 验证配置
|
||
verify_result=$(grep -iE "^\s*Protocol\s+" /etc/ssh/sshd_config | tail -1)
|
||
ssh_version=$(ssh -V 2>&1 | grep -oE "OpenSSH_[0-9]+\.[0-9]+" | cut -d'_' -f2)
|
||
if echo "$verify_result" | grep -qiE "Protocol\s+2"; then
|
||
echo "已设置SSH协议版本为2"
|
||
echo "验证配置: $verify_result"
|
||
echo "OpenSSH版本: $ssh_version"
|
||
else
|
||
echo "警告: 配置可能未正确生效,请手动检查"
|
||
exit 1
|
||
fi
|
||
|
||
# 2.5 禁止通过SSH服务连接X11图形界面转发检查
|
||
# 要求:X11图形界面转发功能可能带来安全风险(如资源占用、潜在的界面劫持等),对于无需远程图形界面的服务器,应禁止通过SSH服务进行X11转发
|
||
- id: "ssh_x11_forwarding"
|
||
category: "SSH安全配置"
|
||
title: "禁止SSH X11转发"
|
||
description: "X11图形界面转发功能可能带来安全风险(如资源占用、潜在的界面劫持等),对于无需远程图形界面的服务器,应禁止通过SSH服务进行X11转发。"
|
||
tags: ["low", "medium", "high", "ssh", "x11"]
|
||
check_script: |
|
||
# 按照标准检测方法:grep -E "^X11Forwarding" /etc/ssh/sshd_config
|
||
# 注意:只检查非注释的配置行(^X11Forwarding),不包括注释行(^#X11Forwarding)
|
||
# 使用 || true 避免grep未找到匹配时导致脚本退出(set -e模式下)
|
||
x11_forwarding_result=$(grep -E "^X11Forwarding" /etc/ssh/sshd_config 2>/dev/null || true)
|
||
|
||
if [ -z "$x11_forwarding_result" ]; then
|
||
# 无相关配置项,使用默认值(SSH默认X11Forwarding为no,即关闭状态),符合要求
|
||
echo "PASS: 未配置X11Forwarding参数,使用默认值(关闭X11转发),符合要求"
|
||
echo "当前配置: (无,使用默认值 no)"
|
||
echo "说明: SSH服务默认X11Forwarding为no(关闭),无需额外配置"
|
||
exit 0
|
||
elif echo "$x11_forwarding_result" | grep -qE "^X11Forwarding\\s+no"; then
|
||
# 输出结果为"X11Forwarding no",符合要求
|
||
echo "PASS: SSH X11转发已禁用"
|
||
echo "当前配置: $x11_forwarding_result"
|
||
exit 0
|
||
else
|
||
# 输出结果为"X11Forwarding yes"或其他值,不符合要求
|
||
echo "FAIL: SSH X11转发未禁用,存在安全风险"
|
||
echo "当前配置: $x11_forwarding_result"
|
||
echo "建议: 编辑/etc/ssh/sshd_config,将'X11Forwarding'设置为'no',然后重启ssh服务"
|
||
exit 1
|
||
fi
|
||
fix_script: |
|
||
# 备份SSH配置文件(按照标准修复建议)
|
||
backup_file="/etc/ssh/sshd_config.backup.$(date +%Y%m%d)"
|
||
cp /etc/ssh/sshd_config "$backup_file"
|
||
echo "已备份配置文件至: $backup_file"
|
||
|
||
# 删除所有X11Forwarding配置行(包括注释)
|
||
sed -i '/^[[:space:]]*#.*X11Forwarding/d' /etc/ssh/sshd_config
|
||
sed -i '/^X11Forwarding/d' /etc/ssh/sshd_config
|
||
# 添加新配置
|
||
echo "X11Forwarding no" >> /etc/ssh/sshd_config
|
||
# 重启SSH服务
|
||
systemctl restart sshd
|
||
# 验证配置
|
||
verify_result=$(grep -E "^X11Forwarding" /etc/ssh/sshd_config)
|
||
if echo "$verify_result" | grep -qE "^X11Forwarding\\s+no"; then
|
||
echo "已禁用SSH X11转发"
|
||
echo "验证配置: $verify_result"
|
||
else
|
||
echo "警告: 配置可能未正确生效,请手动检查"
|
||
exit 1
|
||
fi
|
||
|
||
# 2.12 SSH其他安全配置
|
||
# 要求:为进一步缩小SSH服务攻击面,强化远程登录安全,需补充以下SSH安全配置策略:
|
||
# 1. 限制SSH最大认证尝试次数:设置为3次
|
||
# 2. 设置SSH空闲会话超时:空闲检测间隔300秒,检测到空闲立即断开(ClientAliveCountMax=0)
|
||
# 3. 禁用空密码登录:PermitEmptyPasswords=no
|
||
# 4. 限制用户/组访问:通过AllowUsers或AllowGroups指定仅允许登录的用户或用户组(可选,但建议配置)
|
||
- id: "ssh_other_security"
|
||
category: "SSH安全配置"
|
||
title: "检查SSH其他安全配置"
|
||
description: "为进一步缩小SSH服务攻击面,强化远程登录安全,需配置:最大认证尝试次数3次、空闲会话超时300秒、禁用空密码登录、限制用户/组访问(可选)。"
|
||
tags: ["medium", "high", "ssh", "security"]
|
||
check_script: |
|
||
# 检查基础安全参数
|
||
# 按照标准检测方法:grep -E "^MaxAuthTries|^ClientAliveInterval|^ClientAliveCountMax|^PermitEmptyPasswords" /etc/ssh/sshd_config
|
||
# 使用 || true 避免grep未找到匹配时导致脚本退出(set -e模式下)
|
||
basic_config=$(grep -E "^MaxAuthTries|^ClientAliveInterval|^ClientAliveCountMax|^PermitEmptyPasswords" /etc/ssh/sshd_config 2>/dev/null || true)
|
||
|
||
# 检查访问控制参数(可选)
|
||
access_control_config=$(grep -E "^AllowUsers|^AllowGroups" /etc/ssh/sshd_config 2>/dev/null || true)
|
||
|
||
# 提取各个参数的值
|
||
max_auth_tries_value=$(echo "$basic_config" | grep "^MaxAuthTries" | awk '{print $2}' | tr -d ' ' || echo "")
|
||
client_alive_interval_value=$(echo "$basic_config" | grep "^ClientAliveInterval" | awk '{print $2}' | tr -d ' ' || echo "")
|
||
client_alive_count_max_value=$(echo "$basic_config" | grep "^ClientAliveCountMax" | awk '{print $2}' | tr -d ' ' || echo "")
|
||
permit_empty_passwords_value=$(echo "$basic_config" | grep "^PermitEmptyPasswords" | awk '{print $2}' | tr -d ' ' || echo "")
|
||
|
||
# 判断结果
|
||
issues_found=""
|
||
all_passed=true
|
||
|
||
# 检查MaxAuthTries
|
||
if [ -z "$max_auth_tries_value" ]; then
|
||
issues_found="${issues_found}MaxAuthTries: 未配置(要求: 3)\n"
|
||
all_passed=false
|
||
elif [ "$max_auth_tries_value" != "3" ]; then
|
||
issues_found="${issues_found}MaxAuthTries: ${max_auth_tries_value}(要求: 3)\n"
|
||
all_passed=false
|
||
else
|
||
issues_found="${issues_found}MaxAuthTries: ${max_auth_tries_value}(符合要求)\n"
|
||
fi
|
||
|
||
# 检查ClientAliveInterval
|
||
if [ -z "$client_alive_interval_value" ]; then
|
||
issues_found="${issues_found}ClientAliveInterval: 未配置(要求: 300秒)\n"
|
||
all_passed=false
|
||
elif [ "$client_alive_interval_value" != "300" ]; then
|
||
issues_found="${issues_found}ClientAliveInterval: ${client_alive_interval_value}秒(要求: 300秒)\n"
|
||
all_passed=false
|
||
else
|
||
issues_found="${issues_found}ClientAliveInterval: ${client_alive_interval_value}秒(符合要求)\n"
|
||
fi
|
||
|
||
# 检查ClientAliveCountMax
|
||
if [ -z "$client_alive_count_max_value" ]; then
|
||
issues_found="${issues_found}ClientAliveCountMax: 未配置(要求: 0)\n"
|
||
all_passed=false
|
||
elif [ "$client_alive_count_max_value" != "0" ]; then
|
||
issues_found="${issues_found}ClientAliveCountMax: ${client_alive_count_max_value}(要求: 0)\n"
|
||
all_passed=false
|
||
else
|
||
issues_found="${issues_found}ClientAliveCountMax: ${client_alive_count_max_value}(符合要求)\n"
|
||
fi
|
||
|
||
# 检查PermitEmptyPasswords
|
||
if [ -z "$permit_empty_passwords_value" ]; then
|
||
issues_found="${issues_found}PermitEmptyPasswords: 未配置(要求: no)\n"
|
||
all_passed=false
|
||
elif [ "$permit_empty_passwords_value" != "no" ]; then
|
||
issues_found="${issues_found}PermitEmptyPasswords: ${permit_empty_passwords_value}(要求: no)\n"
|
||
all_passed=false
|
||
else
|
||
issues_found="${issues_found}PermitEmptyPasswords: ${permit_empty_passwords_value}(符合要求)\n"
|
||
fi
|
||
|
||
# 检查访问控制(可选,但建议配置)
|
||
access_control_status=""
|
||
if [ -z "$access_control_config" ]; then
|
||
access_control_status="访问控制: 未配置AllowUsers或AllowGroups(建议配置以限制登录用户/组)\n"
|
||
else
|
||
access_control_status="访问控制: 已配置\n${access_control_config}\n"
|
||
fi
|
||
|
||
# 输出结果
|
||
if [ "$all_passed" = true ]; then
|
||
echo "PASS: SSH其他安全配置符合要求"
|
||
echo ""
|
||
echo "基础安全参数:"
|
||
echo -e "$issues_found"
|
||
echo "访问控制配置:"
|
||
echo -e "$access_control_status"
|
||
exit 0
|
||
else
|
||
echo "FAIL: SSH其他安全配置不符合要求"
|
||
echo ""
|
||
echo "基础安全参数:"
|
||
echo -e "$issues_found"
|
||
echo "访问控制配置:"
|
||
echo -e "$access_control_status"
|
||
echo ""
|
||
echo "建议: 编辑/etc/ssh/sshd_config文件,添加或修改以下配置项:"
|
||
echo " MaxAuthTries 3 # 限制最大认证尝试次数为3次"
|
||
echo " ClientAliveInterval 300 # 空闲会话5分钟(300秒)无操作则断开"
|
||
echo " ClientAliveCountMax 0 # 检测到空闲立即断开"
|
||
echo " PermitEmptyPasswords no # 禁用空密码用户登录"
|
||
echo ""
|
||
echo "访问控制(可选,但建议配置):"
|
||
echo " AllowUsers admin testuser # 允许指定用户登录"
|
||
echo " 或"
|
||
echo " AllowGroups sysadmin # 允许指定组登录"
|
||
echo ""
|
||
echo "注意: 修改配置前请确保已通过密钥认证测试登录正常,或已保留本地控制台访问方式"
|
||
exit 1
|
||
fi
|
||
fix_script: |
|
||
# 备份SSH配置文件(按照标准修复建议)
|
||
backup_file="/etc/ssh/sshd_config.backup.$(date +%Y%m%d)"
|
||
cp /etc/ssh/sshd_config "$backup_file"
|
||
echo "已备份配置文件至: $backup_file"
|
||
echo ""
|
||
echo "警告: 修改配置前,请确保已通过密钥认证测试登录正常,或已保留本地控制台访问方式,防止远程连接中断"
|
||
echo ""
|
||
echo "此问题需要人工干预,请根据检查结果执行以下操作:"
|
||
echo "1. 编辑SSH服务配置文件: vi /etc/ssh/sshd_config"
|
||
echo "2. 添加或修改基础安全配置项:"
|
||
echo " MaxAuthTries 3"
|
||
echo " ClientAliveInterval 300"
|
||
echo " ClientAliveCountMax 0"
|
||
echo " PermitEmptyPasswords no"
|
||
echo "3. (可选)配置访问控制:"
|
||
echo " AllowUsers admin testuser # 允许指定用户登录"
|
||
echo " 或"
|
||
echo " AllowGroups sysadmin # 允许指定组登录"
|
||
echo "4. 保存配置文件并重启SSH服务: systemctl restart sshd"
|
||
echo "5. 验证服务状态: systemctl status sshd"
|
||
echo "6. 验证配置效果: 使用未授权用户尝试登录,应提示'Permission denied'"
|
||
exit 1
|
||
|