sudo
是一个用于在Linux和类Unix系统中以超级用户(root)或其他用户身份执行命令的程序。它的全称是 “superuser do”,允许普通用户以更高权限运行命令。
sudo 命令的工作原理是通过suid
权限来实现的。具体来说,它的工作过程可以简要概述如下:
设置 setuid 权限:sudo 程序本身被设置了 setuid 属性,这意味着当任何用户执行这个程序时,它会以程序拥有者(通常是 root)的权限运行。
执行权限继承:当用户执行 sudo 后面跟随的命令时,这个命令会继承 sudo 的权限。在这种情况下,虽然用户是普通用户,但由于 sudo 在以 root 用户的身份执行,随后的命令则也可以在 root 权限下运行。
权限验证:在执行命令之前,sudo 会检查用户在/etc/sudoers
文件中的配置,确保该用户被授权运行指定的命令。如果用户没有权限,则会被拒绝执行。
审计和日志:sudo 还会记录所有使用 sudo 的命令,这样管理员可以审计用户的行为,以确保系统安全。
总体流程可以用以下流程来表示:
用户执行 sudo command 命令
↓
└── 检查用户权限(/etc/sudoers)
↓
└── command 继承 root 权限执行命令
基本用法
sudo [选项] 命令
-u 用户
:以指定用户身份执行命令(默认root)-l
:列出当前用户的sudo
权限*****************GPT生成***************
在 Linux 系统中,sudoers
文件用于定义哪些用户或用户组可以使用 sudo
命令,并在使用时可以执行哪些命令。通过对 sudoers
文件的配置,管理员能够为用户提供特定的权限控制。
编辑 sudoers
文件
要安全地编辑 sudoers
文件,推荐使用 visudo
命令,因其会进行语法检查,防止语法错误导致的安全风险。
打开终端输入以下命令:
sudo visudo
这将打开 sudoers
文件,通常使用 vi
或者 nano
编辑器。
基本配置格式
sudorers
文件的权限配置基本格式如下:
user host = (runas) command
用户/组 主机=(目标用户:目标组) [NOPASSWD:] 命令
user
:指定用户或用户组。host
:允许执行命令的主机(通常使用 ALL
表示所有主机)。(runas)
:指定用户在执行该命令时可以以哪个用户身份运行(使用 ALL
表示以所有用户身份运行),即限定用户执行命令时的身份切换范围:
-u
参数切换到的用户身份-g
参数切换到的用户组身份command
:允许用户执行的命令,可以使用 ALL
表示所有命令,也可以指定具体的命令路径。示例配置
允许用户 alice
执行所有命令:
alice ALL=(ALL) ALL
允许用户组 admin
以任何用户身份运行所有命令:
%admin ALL=(ALL) ALL
允许用户 bob
在不需要密码的情况下执行 /usr/bin/systemctl
命令:
bob ALL=(ALL) NOPASSWD: /usr/bin/systemctl
只允许用户 charlie
执行 /usr/bin/apt
和 /usr/bin/dpkg
命令:
charlie ALL=(ALL) /usr/bin/apt, /usr/bin/dpkg
其他常用选项
NOPASSWD
:用户可以不输入密码执行特定命令。Defaults
:用于设置默认行为,例如锁定 sudo
命令的执行超时等。Defaults timestamp_timeout=15
保存和退出
在编辑结束后:
vi
:按 Esc
,输入 :wq
,然后按 Enter
保存并退出。nano
:按 Ctrl+X
,然后根据提示选择 Y
来确认保存。注意事项
visudo
:始终通过 visudo
编辑 sudoers
文件,以避免语法错误。sudoers
文件。sudo cp /etc/sudoers /etc/sudoers.bak
sudo
权限配置不当,如果这些可执行文件本身又可以调用其他可执行文件,或者可以更改系统的一些配置选项,就可以达到提权的目的。
使用sudo -l
查看当前sudo配置,看当前用户可以使用sudo执行的命令。 一些可用于执程序的命令可直接用于提权。
路径 | 提权命令 | 路径 | 提权命令 |
---|---|---|---|
/usr/bin/bash | bash -p | /usr/bin/find | find /etc/passwd -exec bash -p |
/usr/bin/csh | csh -p | /usr/bin/awk | awk ‘BEGIN {system(“/bin/bash”)}’ |
/usr/bin/sh | sh -p | /usr/bin/man | !/bin/bash |
/usr/bin/ksh | ksh -p | /usr/bin/more | !/bin/bash |
/usr/bin/zsh | zsh -p | /usr/bin/less | !/bin/bash |
管理员将某个shell脚本设置为sudo免密执行,且低权限用户对其可写,那么可将后门程序或反弹shell的代码写入该脚本,完成提权。
回到2.2
中的脚本,在无权限修改脚本内容时,可以通过阅读脚本代码来判断此脚本是否允许带入参数执行。如果脚本允许带参数执行且该参数可控,也可以进行提权。
管理员在配置sudoers文件时使用了通配符,可利用这种情况执行命令或读取敏感文件。
LD_PRELOAD 是 Linux 系统中一个强大的环境变量,允许用户在程序启动时强制优先加载自定义的共享库(.so 文件),从而覆盖或修改程序原本调用的系统库函数。说白了就是可以让我们自定义调用动态链接库,那么我们就可以写一个带后门的库文件,在使用sudo执行命令的时候指定后门的路径即可执行后门进行提取。
[1] 《权限提升技术-攻防实战与技巧》
[2] Linux SUID提权
[3] sudo官网
环境变量(Environment Variables) 是操作系统中用于存储动态值的全局变量,能够影响程序或进程的行为。它们在以下方面发挥作用:
配置程序行为
PATH
:定义可执行文件的搜索路径。LANG
:设置系统语言和区域。HOME
:指定用户的家目录路径。HTTP_PROXY
:配置网络代理地址。传递信息
程序运行时可通过环境变量读取配置,无需硬编码在代码中(如数据库地址、API 密钥)。
作用范围
.bashrc
、.zshrc
)设置,仅对当前用户生效。/etc/environment
或 /etc/profile
中,对所有用户生效。sudo
可以重置环境变量?sudo
重置环境变量是出于安全性设计,主要原因如下:
PATH
变量,将 ls
指向恶意脚本。LD_PRELOAD
加载恶意库,劫持特权进程。sudo
的防御机制:env_reset
选项,清除非安全的环境变量,仅保留白名单变量(如 TERM
、LANG
)。DEBUG=1
)。sudo
以 root
身份运行时,需确保环境干净,避免用户变量干扰系统级操作。sudo
保证命令在不同用户或主机上行为一致(例如固定 PATH
为安全路径)。sudo
如何管理环境变量?env_reset
:sudo
会重置环境变量,仅保留以下安全变量:LANG, LANGUAGE, LC_*, TERM, USER, SUDO_*, COLORS, MAIL, LOGNAME
secure_path
:PATH
,设置为安全路径(如 /usr/local/sbin:/usr/bin
),防止路径劫持。通过 /etc/sudoers
的 Defaults
指令配置:
Defaults env_keep += "HTTP_PROXY JAVA_HOME"
Defaults env_delete += "GOPATH DEBUG"
使用 -E
选项临时继承当前用户的所有环境变量(需配置允许):
sudo -E command
sudo
的环境变量重置?PATH
未被继承,导致 sudo
执行时找不到命令。docker-compose
、npm
)在 sudo
下无法正常工作。env_keep
:/etc/sudoers
中显式保留必要变量:Defaults env_keep += "PATH HTTP_PROXY"
sudo /usr/local/bin/myapp
)。sudo -i
或 sudo su -
启动一个完整的 root
Shell(继承 root
的环境)。场景 | 安全优先 | 便利优先 |
---|---|---|
生产服务器 | 严格限制环境变量,仅保留必要项 | 避免修改,使用默认配置 |
开发环境 | 按需保留 JAVA_HOME 等变量 |
允许临时 -E 继承变量 |
敏感操作 | 禁用 -E ,强制 env_reset |
仅在可信场景下放宽限制 |
sudo
重置环境变量是安全机制的核心设计,防止恶意利用和配置污染。/etc/sudoers
的 Defaults
指令,可以精细控制环境变量继承,兼顾安全性与功能需求。环境变量的“全局性”容易让人误解为整个操作系统共享同一份变量,但实际上其作用域和生命周期与进程密切相关。以下是详细解析:
示例:
用户终端中设置的 PATH
变量仅影响该终端及其启动的子进程(如 bash
→ ls
)。
sudo
启动的新进程(如以 root
运行的命令)会创建独立的环境变量副本。setenv()
、putenv()
)动态修改自身环境变量。
sudo
在启动子进程前,会主动重置或过滤环境变量。sudo
默认重置环境变量,仅保留必要项(如 TERM
),防止用户通过变量注入攻击(如劫持 PATH
或 LD_PRELOAD
)。sudo
重置环境变量的具体过程sudo
进程启动时,默认继承当前 Shell 的环境变量。env_reset
:LANG
, TERM
)。secure_path
:PATH
为安全路径(如 /usr/bin:/sbin
)。/etc/sudoers
中的 env_keep
配置,添加允许保留的变量(如 HTTP_PROXY
)。sudo
如何重置 PATH
PATH=$HOME/bin:/usr/local/bin:$PATH
sudo
执行时:PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$HOME/bin
路径被移除,防止恶意程序劫持。HTTP_PROXY
)。/etc/sudoers
的 Defaults
指令,管理员可精细控制保留或删除的变量。sudo
重置环境变量是安全机制:通过进程隔离和动态清理,防止用户环境干扰特权操作。在 Linux 系统中:
fork()
+ exec()
创建子进程时,环境变量会通过 execve()
系统调用传递,并复制到子进程的用户空间内存中。// 内存布局示例(低地址 → 高地址)
+-------------------+
| 程序代码(text) |
| 静态数据(data/bss)|
| 堆(heap) |
| ... |
| 栈(stack) |
| 命令行参数(argv) |
| 环境变量(envp) | ← 栈的顶部
+-------------------+