浅聊SUID

admin 2023年12月10日08:43:53评论21 views字数 5067阅读16分53秒阅读模式

简介

SUID全称Set owner User ID up on execution,是Linux给可执行文件的一个属性,设置了s位的程序在运行时其Effective UID将会设置为这个程序的所有者。比如,/bin/ping这个程序的所有者是0(root),它设置了s位,那么普通用户在运行ping时其Effective UID就是0,等同于拥有了root权限。

➜  c ls -ldb $(which pkexec)-rwsr-xr-x 1 root root 30872 2023年 213日 /usr/bin/pkexec

SUID文件的出现是为了解决一些操作只能由root权限进行,但普通权限用户也需要能通过某种方式进行调用,比如passwd,/etc/shadow只有root可写,但用户自己显然需要可以修改密码,所以passwd被设置为SUID程序,使得普通用户能通过passwd临时获取到修改shadow文件的能力。

-rw-r----- 1 root shadow 1411 2023年 5月10日 /etc/shadow-rwsr-xr-x 1 root root 68248 2022年11月11日 /usr/bin/passwd


Linux中每个用户都有独一无二的ID,称为UserID。为进程定义了三个ID:

  • Real UserID

  • Effective UserID

  • Saved UserID

  1. Real UserID:对于一个进程,这个ID是启动这个进程的用户的用户ID,这个ID定义了这个进程有权访问哪些文件。

  2. Effective UserID:通常这个ID和Real UserID相同,但有时会不一样,来允许非特权用户访问只能由特权用户访问的文件。当非特权的用户运行此文件时,euid是文件所属的用户id,ruid才是当前用户的id

    -rwsr-xr-x 1 root root 68248 2022年11月11日 /usr/bin/passwd
    ┌──(chestnut㉿chestnut)-[/root/code/c]
    └─$ passwd
    为 chestnut 更改 STRESS 密码。
    ➜ c ps -eo pid,euid,ruid | grep 1692693
    1692693 0 1000
  3. Saved UserID,当进程以提升权限运行时,需要做一些非特权的操作,可以通过临时切换到非特权账户来实现。在执行低权限工作时,将Effective UID 更改为某个较低的权限值,并将 euid 保存到Saved userID(suid),以便在任务完成时用于切换回特权账户。

https://www.geeksforgeeks.org/real-effective-and-saved-userid-in-linux/


查找SUID程序

find / -perm -4000 -type f -exec ls -ldb {} ;-perm -4000 查找权限为4000-type f 只查找普通文件,过滤掉目录等其他类型-[/root/code/c/suid.c/root/code/c/CMakeLists.txt](vscode-remote://ssh-remote%2B192.168.59.211/root/code/c/suid.c)exec ls -ldb {} ; 对找到的文件执行ls -ldb命令,显示文件详细信息。{}表示find找到的文件名,会逐个代入。;表示-exec选项命令结束。; 的作用就是隔离 find 命令行和 -exec 指定的命令,避免解析错误。
-rwsr-xr-x 1 root root 30872 2023年 2月13日 /usr/bin/pkexec-rwsr-xr-x 1 root root 14888 2023年 1月 3日 /usr/bin/vmware-user-suid-wrapper-rwsr-xr-- 1 root kismet 146216 2022年12月27日 /usr/bin/kismet_cap_nxp_kw41z-rwsr-xr-- 1 root kismet 142120 2022年12月27日 /usr/bin/kismet_cap_nrf_51822-rwsr-xr-x 1 root root 59704 2023年 2月13日 /usr/bin/mount-rwsr-xr-- 1 root kismet 216392 2022年12月27日 /usr/bin/kismet_cap_linux_wifi-rwsr-xr-- 1 root kismet 142120 2022年12月27日 /usr/bin/kismet_cap_ubertooth_one-rwsr-xr-- 1 root kismet 146216 2022年12月27日 /usr/bin/kismet_cap_rz_killerbee-rwsr-xr-x 1 root root 68248 2022年11月11日 /usr/bin/passwd-rwsr-xr-- 1 root kismet 146216 2022年12月27日 /usr/bin/kismet_cap_nrf_mousejack-rwsr-xr-- 1 root kismet 142120 2022年12月27日 /usr/bin/kismet_cap_nrf_52840-rwsr-xr-x 1 root root 88496 2022年11月11日 /usr/bin/gpasswd-rwsr-xr-x 1 root root 35128 2023年 2月13日 /usr/bin/umount-rwsr-xr-- 1 root kismet 154408 2022年12月27日 /usr/bin/kismet_cap_linux_bluetooth-rwsr-xr-- 1 root kismet 146216 2022年12月27日 /usr/bin/kismet_cap_ti_cc_2531

shell中的SUID细节

在https://www.leavesongs.com/PENETRATION/linux-suid-privilege-escalation.html中提到Ubuntu对dash进行了patch。

找到patch地址为https://launchpadlibrarian.net/240241543/dash_0.5.8-2.1ubuntu2.diff.gz,代码如下,当on=1时会略过权限检查,当on不为1时,会通过geteuid和getegid获取当前进程的effective user ID和effective group ID,并与通过getuid和getgid获取的real user ID和real group ID进行比较。如果当前进程对应的可执行文件为SUID文件且当前运行这个文件的用户不是文件属主时,会重新通过setuid和setgid将当前进程的权限设置为real ID,即运行这个可执行文件的用户的权限。当文件不是SUID文件时rid和eid相等,不会进入if内,或者文件是SUID文件并且运行这个文件的用户是文件属主rid和eid也会相等,不会进入if内。

+diff -Naurp dash-0.5.7.ori/src/main.c dash-0.5.7/src/main.c+--- dash-0.5.7.ori/src/main.c  2015-06-03 10:45:22.766472281 -0400++++ dash-0.5.7/src/main.c  2015-06-03 10:58:56.484258181 -0400+@@ -97,11 +97,16 @@ main(int argc, char **argv)+   struct jmploc jmploc;+   struct stackmark smark;+   int login;++  uid_t uid;++  gid_t gid;++ #ifdef __GLIBC__+   dash_errno = __errno_location();+ #endif+++  uid = getuid();++  gid = getgid();

+diff -Naurp dash-0.5.7.ori/src/priv.c dash-0.5.7/src/priv.c+--- dash-0.5.7.ori/src/priv.c 1969-12-31 19:00:00.000000000 -0500++++ dash-0.5.7/src/priv.c 2015-06-03 11:00:31.097386153 -0400+@@ -0,0 +1,27 @@++#include <unistd.h>++++#include "priv.h"++#include "var.h"++++uid_t uid;++gid_t gid;++++void setprivileged(int on)++{++ static int is_privileged = 1;++ if (is_privileged == on)++ return;++++ is_privileged = on;++++ /*++ * To limit bogus system(3) or popen(3) calls in setuid binaries, require++ * -p flag to work in this situation.++ */++ if (!on && (uid != geteuid() || gid != getegid())) {++ setuid(uid);++ setgid(gid);++ /* PS1 might need to be changed accordingly. */++ choose_ps1();++ }++}

那么为什么要这样实现呢?为什么如果需要继承默认的effective user ID和effective group ID需要显式的使用-p参数呢?假设我们有如下suid程序,并且该程序由www-data用户启动:

#include <stdlib.h>#include <stdio.h>
int main(int argc, char *argv[]) { printf("%sn", argv[1]); return system(argv[1]);}

其中通过system函数执行用户传入的命令,system实现可以在这找到(https://codebrowser.dev/glibc/glibc/sysdeps/posix/system.c.html),可以看到实际执行的是/bin/sh -c command,加入攻击者传入恶意命令,尝试通过该程序以root权限执行命令,最终以/bin/sh -c command的形式执行命令。

#define  SHELL_PATH  "/bin/sh"  /* Path of the shell.  */#define  SHELL_NAME  "sh"    /* Name to give it.  */do_system (const char *line){  int status = -1;  int ret;  pid_t pid;  struct sigaction sa;#ifndef _LIBC_REENTRANT  struct sigaction intr, quit;#endif .....  __posix_spawnattr_init (&spawn_attr);  __posix_spawnattr_setsigmask (&spawn_attr, &omask);  __posix_spawnattr_setsigdefault (&spawn_attr, &reset);  __posix_spawnattr_setflags (&spawn_attr,            POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK);  ret = __posix_spawn (&pid, SHELL_PATH, 0, &spawn_attr,           (char *const[]){ (char *) SHELL_NAME,          (char *) "-c",          (char *) line, NULL },           __environ);


如果没有前面说的措施,那么攻击者可以成功以root权限执行恶意命令,但通过上面的措施,则会出现如下:因为进程的rid为www-data,eid为root,而通过system函数执行命令不能显式设置-p参数,导致在执行命令时,不能通过if判断,命令的权限会被降为www-data权限,从而一定程度上缓解了攻击。

参考资料

https://www.leavesongs.com/PENETRATION/linux-suid-privilege-escalation.html

原文始发于微信公众号(闲聊趣说):浅聊SUID

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年12月10日08:43:53
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   浅聊SUIDhttp://cn-sec.com/archives/2280257.html

发表评论

匿名网友 填写信息