she*_*lbc 6 security root setuid su
一些任意帐户和root
?之间的根本区别是什么?它只是UID
零以外的存在吗?
那么,su二进制文件究竟做了什么以及它如何将用户提升为 root 用户?我知道用户必须首先sudo
通过我们在/etc/sudoers
.
# 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
Run Code Online (Sandbox Code Playgroud)
查看su
可执行文件的权限,我们发现-rwsr-xr-x或4755(即已setuid
设置)。
是su二进制文件读取此配置文件并检查请求 root 权限的用户是否属于组sudo或admin?如果是这样,假设用户是预期组的一部分并且知道尝试替换的适当用户的密码(特别是 .例如root ),二进制文件是否会以 root 身份生成另一个 shell(考虑setuid位)?
tl;dr
特权提升行为是否依赖于su二进制文件中的setuid
位,或者是否有其他机制来更改当前进程的 UID?在前者的情况下,似乎只有 EUID 会改变而留下 UID != EUID。这有问题吗?
相关 如何在 Android 环境中模拟所有这些?据我所知,对 root 的访问已经完全被剥夺了——尽管进程仍然在这个特权级别运行。
如果我们删除sudo
,su
这是否足以防止权限提升或 Android 是否采取了进一步措施?
Gil*_*il' 12
关键是用户ID 0。内核中有很多地方会检查调用进程的用户ID,并且只有当用户ID 为0 时才授予执行某些操作的权限。
用户名无关紧要;内核甚至不知道用户名。
Android 的权限机制在内核层面是相同的,但在应用层面则完全不同。Android 有一个 root 用户(UID 0),就像任何其他基于 Linux 内核的系统一样。但是,Android 没有用户帐户,并且在大多数设置中不允许用户(如在人工操作和拥有设备中)以 root 用户身份执行操作。“root” Android 是允许设备所有者/用户以 root 身份执行操作的设置。
一的setuid可执行文件运行作为谁拥有可执行用户。例如,su
是 setuid 并且由 root 拥有,因此当任何用户运行它时,运行的进程都su
以 root 用户身份运行。的工作su
是验证调用它的用户是否可以使用 root 帐户,如果此验证成功,则运行指定的命令(如果未指定命令,则运行 shell),如果此验证失败则退出。例如,su
可能会要求用户证明他们知道 root 密码。
更详细地说,一个进程具有三个用户 ID:有效UID,用于安全检查;在真正的UID,这是在少数特权检查使用,但主要用作原始用户ID的备份和保存的用户ID,它允许一个进程的有效UID暂时切换到真实的用户ID,然后回去前一个有效的 UID(这很有用,例如当 setuid 程序需要以原始用户身份访问文件时)。运行 setuid 可执行文件将有效 UID 设置为可执行文件的所有者并保留真实 UID。
运行 setuid 可执行文件(以及类似的机制,例如 setgid)是提升进程权限的唯一方法。几乎所有其他事情都只能降低进程的权限。
到目前为止,我描述了传统的 Unix 系统。所有这些在现代 Linux 系统上都是正确的,但 Linux 带来了一些额外的复杂性。
Linux有能力系统。还记得我说过内核有很多检查,其中只允许以用户 ID 0 身份运行的进程吗?事实上,每个检查都有自己的能力(嗯,不完全是,一些检查使用相同的能力)。例如,有访问原始网络套接字的功能,以及用于重新启动系统的另一种功能。每个进程在其用户和组旁边都有一组功能。如果进程以用户 0 身份运行或者它具有与检查对应的能力,则该进程通过检查。需要特定权限的进程可以以非 root 用户身份运行,但具有必要的能力;如果进程有安全漏洞,这会限制影响。可执行文件可以设置为一个或多个功能:这类似于 setuid,但适用于进程的功能集而不是进程的用户 ID。CAP_NET_RAW
而不是 setuid root。
Linux 有几个安全模块,最著名的是SELinux。安全模块引入了额外的安全检查,甚至可以应用于以 root 身份运行的进程。例如,有可能(不容易!)设置 SELinux 以便以用户 ID 0 运行进程,但由于限制太多,它实际上无法执行任何操作。
Linux 有用户命名空间。在内核内部,用户实际上不仅仅是一个用户 ID,而是由用户 ID 和命名空间组成的一对。命名空间形成层次结构:子命名空间细化其父命名空间内的权限。全能用户是根命名空间中的用户 0。命名空间中的用户 0 仅在该命名空间内具有权力。例如,用户命名空间中的用户 0 可以模拟该命名空间的任何用户;但从外部来看,该命名空间中的所有进程都以同一用户身份运行。
在 Linux 中有 4 个 UID:RUID(真实)、EUID(有效)、SUID(已保存)、FSUID(文件系统)。
这些只不过是数字,是进程的属性,存储在内核进程表中的一个控制块中。
UID'0'
有一个特殊的特性,因为它表示用户root
,它通常具有不受限制的访问权限。
su
和sudo
是更改用户有效访问权限的程序,方法是启动一个新的子进程,通过 的 SetUID 位将 EUID 设置为新的 UID su
。这个 su 进程然后在一个新的子进程中再次产生一个新的 shell,将 4 个 UID 设置为新的 UID 值。
下面的例子应该证明这一点。假设用户rda
通过 ssh 终端登录。ps fax
将展示以下涉及的流程:
472 ? Ss 0:00 /usr/sbin/sshd -D
9151 ? Ss 0:00 \_ sshd: rda [priv]
9153 ? S 0:00 | \_ sshd: rda@pts/1
9154 pts/1 Ss+ 0:00 | \_ -bash
Run Code Online (Sandbox Code Playgroud)
4个进程,ssh守护进程,ssh会话(和终端?)的两个进程,最后一个进程是登录shell(用-
前面的a表示bash
)
ps faw -eo euser,ruser,suser,fuser,f,comm
将显示进程的 UID:
EUSER RUSER SUSER FUSER F COMMAND
...
root root root root 4 sshd
root root root root 4 \_ sshd
rda rda rda rda 5 | \_ sshd
rda rda rda rda 0 | \_ bash
Run Code Online (Sandbox Code Playgroud)
调用su
然后成功的身份验证将导致以下结果:
EUSER RUSER SUSER FUSER F COMMAND
...
root root root root 4 sshd
root root root root 4 \_ sshd
rda rda rda rda 5 | \_ sshd
rda rda rda rda 0 | \_ bash
root rda root root 4 | \_ su
root root root root 4 | \_ bash
Run Code Online (Sandbox Code Playgroud)
'bash' 进程启动一个新的 'su' 子进程,其 EUID 由 SetUID 位设置为'0'
(root),此时 RUID 仍设置为 rda 的 UID。'su' 进程再次使用新的 shell 启动一个新的子进程,授予用户 root 访问权限(RUID 现在设置为'0'
too)。用户保持在他的工作目录中,新 shell 将使用与父 shell 相同的环境,例如:
server:/home/rda# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
server:/home/rda# pwd
/home/rda
Run Code Online (Sandbox Code Playgroud)
外壳可以关闭,exit
用户将使用其原始访问权限在父外壳中。
如果使用连字符'-'
参数调用 'su',情况就不同了:
rda@server:~$ su -
Password:
server:~# echo $PATH
/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
server:~# pwd
/root
Run Code Online (Sandbox Code Playgroud)
shell 环境已经改变,因为新的 shell 是一个登录 shell,参见'-su'
,它执行一些额外的配置脚本:
9151 ? Ss 0:00 \_ sshd: rda [priv]
9153 ? S 0:00 | \_ sshd: rda@pts/1
9154 pts/1 Ss 0:00 | \_ -bash
9613 pts/1 S 0:00 | \_ su -
9614 pts/1 S+ 0:00 | \_ -su
Run Code Online (Sandbox Code Playgroud)
登录 shell 应该用logout
.
从理论上讲,我认为可以通过删除sudo
和su
不提供直接(通过终端、ssh 等)登录系统并且没有对设备的物理访问权限来阻止用户获得提升的权限。
更新:Android 上的生根过程
正如此处详细解释的,为 Android 设备生根的可能方法取决于引导加载程序和Android 系统属性 ro.secure
。
目标始终相同,安装su
二进制文件/system
并使其成为setuid(0)
.
具有解锁引导加载程序的设备:
dd
从设备中提取库存 ROM ,添加su
、重新打包(或下载此类修改后的 ROM),以闪存模式重新启动设备并刷新修改后的 ROM。
ro.secure=0 的设备:
此系统属性控制输入的命令adb shell
是作为 root ( ro.secure=0
) 还是作为非特权用户 ( ro.secure=1
) 运行。 的值ro.secure
是在引导时从目录中的default.prop
文件设置的,该root
目录只能由用户 root 访问,因此是安全的。
大多数情况下ro.secure
设置为1
,但有些制造商将其设置为0
。这可以通过getprop ro.secure
在设备上的终端模拟器或 adb shell 中运行命令来检查。如果设置为0
,生根很容易,将其连接到计算机,运行adb
,/system
以读写方式挂载,安装su
。
带有锁定引导加载程序的设备:
此类设备具有不允许闪存未由制造商签名的自定义 ROM 的恢复。在这种情况下获得 root 访问权限的唯一方法是利用以特权模式运行的正在运行的系统进程之一中的安全漏洞,并破解它以允许执行“任意代码”。此代码通常/system
会su
永久安装和安装。
归档时间: |
|
查看次数: |
2145 次 |
最近记录: |