一

一键去除/还原重要文件suid和sgid权限脚本

Captain Linux 2021-10-16

脚本带交互式菜单,运行前会显示当前权限状态,执行前需确认,防止误操作。
新建一个suid_sgid_manager.sh文件,将下面的代码完整写入保存后上传到服务器并赋予执行权限,以root权限运行:

chmod +x suid_sgid_manager.sh

2. 运行(root权限)

sudo ./suid_sgid_manager.sh

完整代码

#!/bin/bash
# ======== suid_sgid_manager.sh ============================
# =============== by laitai.top ============================
# SUID / SGID 权限一键管理脚本
# 作用:批量去除 / 恢复系统指定文件的 SUID / SGID 特殊权限
# 目标文件清单:
#   /usr/bin/gpasswd   (SUID root)
#   /usr/bin/chfn      (SUID root)
#   /usr/bin/chsh      (SUID root)
#   /usr/bin/newgrp    (SUID root)
#   /bin/mount         (SUID root)
#   /bin/umount        (SUID root)
#   /usr/bin/chage     (SGID shadow)
# ============================================================

# ---------- 目标文件与默认权限定义 ----------
# SUID 文件列表(u+s)
SUID_FILES=(
    "/usr/bin/gpasswd"
    "/usr/bin/chfn"
    "/usr/bin/chsh"
    "/usr/bin/newgrp"
    "/bin/mount"
    "/bin/umount"
)

# SGID 文件列表(g+s)
SGID_FILES=(
    "/usr/bin/chage"
)

# ---------- 颜色定义 ----------
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# ---------- 函数:打印分隔线 ----------
print_line() {
    echo "------------------------------------------------------------"
}

# ---------- 函数:检查 root 权限 ----------
check_root() {
    if [ "$(id -u)" -ne 0 ]; then
        echo -e "${RED}[错误] 请使用 root 用户或 sudo 运行此脚本!${NC}"
        exit 1
    fi
}

# ---------- 函数:显示当前权限状态 ----------
show_status() {
    echo -e "${BLUE}【当前权限状态】${NC}"
    print_line
    echo -e "文件路径                  | 当前权限  | 特殊位"
    print_line
    for f in "${SUID_FILES[@]}" "${SGID_FILES[@]}"; do
        if [ -e "$f" ]; then
            perms=$(stat -c "%a" "$f")
            special=$(ls -l "$f" | awk '{print $1}' | cut -c4)
            if [ "$special" = "s" ]; then
                special_tag="${YELLOW}s${NC}"
            else
                special_tag="-"
            fi
            printf "%-26s | %-8s | %s\n" "$f" "$perms" "$special_tag"
        else
            echo -e "${RED}$f 不存在!${NC}"
        fi
    done
    print_line
}

# ---------- 函数:选项1 - 去除 SUID/SGID ----------
remove_special() {
    echo -e "${YELLOW}【即将执行:批量去除 SUID / SGID 权限】${NC}"
    echo "影响文件:"
    for f in "${SUID_FILES[@]}" "${SGID_FILES[@]}"; do
        echo "  - $f"
    done
    echo ""
    read -p "确认执行?(y/N): " confirm
    if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
        echo -e "${RED}已取消操作。${NC}"
        return
    fi

    echo ""
    echo -e "${GREEN}>>> 开始去除 SUID ...${NC}"
    for f in "${SUID_FILES[@]}"; do
        if [ -e "$f" ]; then
            chmod u-s "$f" && echo -e "  ${GREEN}[OK]${NC} $f 已去除 SUID"
        else
            echo -e "  ${RED}[跳过]${NC} $f 不存在"
        fi
    done

    echo ""
    echo -e "${GREEN}>>> 开始去除 SGID ...${NC}"
    for f in "${SGID_FILES[@]}"; do
        if [ -e "$f" ]; then
            chmod g-s "$f" && echo -e "  ${GREEN}[OK]${NC} $f 已去除 SGID"
        else
            echo -e "  ${RED}[跳过]${NC} $f 不存在"
        fi
    done

    echo ""
    echo -e "${GREEN}=====================================${NC}"
    echo -e "${GREEN}  去除操作完成!${NC}"
    echo -e "${GREEN}=====================================${NC}"
}

# ---------- 函数:选项2 - 回滚恢复默认权限 ----------
restore_default() {
    echo -e "${YELLOW}【即将执行:恢复 SUID / SGID 默认权限】${NC}"
    echo "影响文件:"
    for f in "${SUID_FILES[@]}"; do
        echo "  - $f  (恢复 u+s)"
    done
    for f in "${SGID_FILES[@]}"; do
        echo "  - $f  (恢复 g+s)"
    done
    echo ""
    read -p "确认执行?(y/N): " confirm
    if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
        echo -e "${RED}已取消操作。${NC}"
        return
    fi

    echo ""
    echo -e "${GREEN}>>> 恢复 SUID ...${NC}"
    for f in "${SUID_FILES[@]}"; do
        if [ -e "$f" ]; then
            chmod u+s "$f" && echo -e "  ${GREEN}[OK]${NC} $f 已恢复 SUID"
        else
            echo -e "  ${RED}[跳过]${NC} $f 不存在"
        fi
    done

    echo ""
    echo -e "${GREEN}>>> 恢复 SGID ...${NC}"
    for f in "${SGID_FILES[@]}"; do
        if [ -e "$f" ]; then
            chmod g+s "$f" && echo -e "  ${GREEN}[OK]${NC} $f 已恢复 SGID"
        else
            echo -e "  ${RED}[跳过]${NC} $f 不存在"
        fi
    done

    echo ""
    echo -e "${GREEN}=====================================${NC}"
    echo -e "${GREEN}  回滚恢复完成!${NC}"
    echo -e "${GREEN}=====================================${NC}"
}

# ---------- 主菜单 ----------
main_menu() {
    clear
    echo -e "${BLUE}╔═══════════════════════════════════════════════════╗${NC}"
    echo -e "${BLUE}║     SUID / SGID 权限一键管理工具 by Laitai.top      ║${NC}"
    echo -e "${BLUE}╚═══════════════════════════════════════════════════╝${NC}"
    echo ""

    show_status

    echo ""
    echo -e "${YELLOW}请选择操作:${NC}"
    echo "  1. 一键去除 SUID / SGID 权限"
    echo "  2. 一键回滚恢复默认权限"
    echo "  3. 刷新查看当前状态"
    echo "  0. 退出"
    echo ""
    read -p "请输入选项 [0-3]: " choice

    case $choice in
        1)
            echo ""
            remove_special
            echo ""
            read -p "按回车键返回主菜单..."
            main_menu
            ;;
        2)
            echo ""
            restore_default
            echo ""
            read -p "按回车键返回主菜单..."
            main_menu
            ;;
        3)
            echo ""
            read -p "按回车键返回主菜单..."
            main_menu
            ;;
        0)
            echo -e "${GREEN}再见!${NC}"
            exit 0
            ;;
        *)
            echo -e "${RED}无效选项,请重新输入!${NC}"
            sleep 1
            main_menu
            ;;
    esac
}

# ---------- 脚本入口 ----------
check_root
main_menu

3. 菜单说明

选项功能
1一键去除:对 6 个 SUID 文件执行 chmod u-s,对 1 个 SGID 文件执行 chmod g-s
2一键回滚:恢复所有文件的默认 SUID/SGID 权限
3刷新查看当前各文件权限状态
0退出

安全设计

  • 运行前先检查 root 权限,非 root 直接退出
  • 每次执行操作前列出影响文件并要求输入 y 确认
  • 顶部实时显示每个文件当前权限和特殊位状态
  • 文件不存在时自动跳过,不报错中断

包含的文件清单

SUID 去除 / 恢复(u+s):

  • /usr/bin/gpasswd
  • /usr/bin/chfn
  • /usr/bin/chsh
  • /usr/bin/newgrp
  • /bin/mount
  • /bin/umount

SGID 去除 / 恢复(g+s):

  • /usr/bin/chage

说明

命令原本权限作用去掉特殊位之后的后果
/usr/bin/gpasswdSUID root普通用户可以修改组密码、管理用户附属组普通用户无法再修改组密码,无法管理附属组;root 本身不受影响
/usr/bin/chfnSUID root普通用户修改自己的 finger 信息(个人备注)普通用户不能修改自己的 GECOS 信息,root 仍可操作
/usr/bin/chshSUID root普通用户修改自己的登录 shell普通用户无法更换自己的 shell,root 不受影响
/usr/bin/newgrpSUID root普通用户临时切换有效用户组普通用户不能执行 newgrp 切换组
/bin/mountSUID root/etc/fstab里标记user选项的分区,允许普通用户挂载普通用户再也不能挂载 fstab 中 user 标记的分区,root 依旧可以 mount
/bin/umountSUID root/etc/fstab中user挂载的分区,普通用户卸载普通用户无法卸载自己挂载的分区,root 不受影响
/usr/bin/chageSGID shadowchage 需要读取/etc/shadow(shadow 组权限)普通用户无法查看密码过期信息;root 执行 chage 不受影响
PREV:Windows Server安全设置:SynAttackProtect保护机制 - 服务器SYN洪水攻击原理和防御办法
NEXT:一张图告诉你如何选择电视尺寸