SUID 的权限其实与程序的相关性非常的大!为什么呢?先来看看 SUID 的程序是如何被一般使用者执行,且具有什么特色呢?

  • SUID 权限仅对二进制程序(binary program)有效;
  • 执行者对于该程序需要具有 x 的可执行权限;
  • 本权限仅在执行该程序的过程中有效 (run-time);
  • 执行者将具有该程序拥有者 (owner) 的权限。
    所以说,整个 SUID 的权限会生效是由于“具有该权限的程序被触发”,而我们知道一个程序被触发会变成程序, 所以啰,执行者可以具有程序拥有者的权限就是在该程序变成程序的那个时候啦!第六章我们还没谈到程序的概念, 所以你或许那时候会觉得很奇怪,为啥执行了 passwd 后你就具有 root 的权限呢?不都是一般使用者执行的吗? 这是因为你在触发 passwd 后,会取得一个新的程序与 PID,该 PID 产生时通过 SUID 来给予该 PID 特殊的权限设置啦! 我们使用 dmtsai 登陆系统且执行 passwd 后,通过来理解一下!

从上表的结果我们可以发现,底线的部分是属于 dmtsai 这个一般帐号的权限,特殊字体的则是 root 的权限! 但你看到了, passwd 确实是由 bash 衍生出来的!不过就是权限不一样!通过这样的解析, 你也会比较清楚为何不同程序所产生的权限不同了吧!这是由于“SUID 程序运行过程中产生的程序”的关系啦!

那么既然 SUID/SGID 的权限是比较可怕的,您该如何查询整个系统的 SUID/SGID 的文件呢? 应该是还不会忘记吧?使用 find 即可啊!

其实,我们之前提到的所谓的程序都是在内存当中嘛!而内存当中的数据又都是写入到 /proc/* 这个目录下的,所以啰,我们当然可以直接观察 /proc 这个目录当中的文件啊! 如果你观察过 /proc 这个目录的话,应该会发现他有点像这样:

  1. dr-xr-xr-x. 8 root root 0 Aug 4 18:46 1
  2. dr-xr-xr-x. 8 root root 0 Aug 4 18:46 10
  3. dr-xr-xr-x. 8 root root 0 Aug 4 18:47 10548
  4. ....(中间省略)....
  5. -r--r--r--. 1 root root 0 Aug 5 17:48 uptime
  6. -r--r--r--. 1 root root 0 Aug 5 17:48 version
  7. -r--------. 1 root root 0 Aug 5 17:48 vmallocinfo
  8. -r--r--r--. 1 root root 0 Aug 5 17:48 vmstat
  9. -r--r--r--. 1 root root 0 Aug 5 17:48 zoneinfo

基本上,目前主机上面的各个程序的 PID 都是以目录的型态存在于 /proc 当中。 举例来说,我们开机所执行的第一支程序 systemd 他的 PID 是 1 , 这个 PID 的所有相关信息都写入在 /proc/1/* 当中!若我们直接观察 PID 为 1 的数据好了,他有点像这样:

  1. [root@study ~]# ll /proc/1
  2. dr-xr-xr-x. 2 root root 0 Aug 4 19:25 attr
  3. -rw-r--r--. 1 root root 0 Aug 4 19:25 autogroup
  4. -r--------. 1 root root 0 Aug 4 19:25 auxv
  5. -r--r--r--. 1 root root 0 Aug 4 18:46 cgroup
  6. --w-------. 1 root root 0 Aug 4 19:25 clear_refs
  7. -r--r--r--. 1 root root 0 Aug 4 18:46 cmdline <==就是指令串
  8. -r--------. 1 root root 0 Aug 4 18:46 environ <==一些环境变量
  9. lrwxrwxrwx. 1 root root 0 Aug 4 18:46 exe
  10. ....(以下省略)....
  • cmdline:这个程序被启动的指令串;
  • environ:这个程序的环境变量内容。
    很有趣吧!如果你查阅一下 cmdline 的话,就会发现:

就是这个指令、选项与参数启动 systemd 的啦!这还是跟某个特定的 PID 有关的内容呢,如果是针对整个 Linux 系统相关的参数呢?那就是在 /proc 目录下面的文件啦!相关的文件与对应的内容是这样的:

其实,上面这些文件鸟哥在此建议您可以使用 cat 去查阅看看,不必深入了解, 不过,观看过文件内容后,毕竟会比较有感觉啦!如果未来您想要自行撰写某些工具软件, 那么这个目录下面的相关文件可能会对您有点帮助的喔!

其实还有一些与程序相关的指令可以值得参考与应用的,我们来谈一谈:

  • fuser:借由文件(或文件系统)找出正在使用该文件的程序
    有的时候我想要知道我的程序到底在这次启动过程中打开了多少文件,可以利用 fuser 来观察啦! 举例来说,你如果卸载时发现系统通知:“ device is busy ”,那表示这个文件系统正在忙碌中, 表示有某支程序有利用到该文件系统啦!那么你就可以利用 fuser 来追踪啰!fuser 语法有点像这样:
  1. [root@study ~]# fuser [-umv] [-k [i] [-signal]] file/dir
  2. 选项与参数:
  3. -u :除了程序的 PID 之外,同时列出该程序的拥有者;
  4. -m :后面接的那个文件名会主动的上提到该文件系统的最顶层,对 umount 不成功很有效!
  5. -v :可以列出每个文件与程序还有指令的完整相关性!
  6. -k :找出使用该文件/目录的 PID ,并试图以 SIGKILL 这个讯号给予该 PID
  7. -i :必须与 -k 配合,在删除 PID 之前会先询问使用者意愿!
  8. -signal:例如 -1 -15 等等,若不加的话,默认是 SIGKILL (-9 啰!
  9. 范例一:找出目前所在目录的使用 PID/所属帐号/权限 为何?
  10. [root@study ~]# fuser -uv .
  11. USER PID ACCESS COMMAND
  12. /root: root 13888 ..c.. rootbash

看到输出的结果没?他说“.”下面有两个 PID 分别为 13888, 31743 的程序,该程序属于 root 且指令为 bash 。 比较有趣的是那个 ACCESS 的项目,那个项目代表的意义为:

  • c :此程序在当前的目录下(非次目录);
  • e :可被触发为执行状态;
  • f :是一个被打开的文件;
  • r :代表顶层目录 (root directory);
  • F :该文件被打开了,不过在等待回应中;
  • m :可能为分享的动态函数库;
    那如果你想要查阅某个文件系统下面有多少程序正在占用该文件系统时,那个 -m 的选项就很有帮助了! 让我们来做几个简单的测试,包括实体的文件系统挂载与 /proc 这个虚拟文件系统的内容, 看看有多少的程序对这些挂载点或其他目录的使用状态吧!
  1. 范例二:找到所有使用到 /proc 这个文件系统的程序吧!
  2. [root@study ~]# fuser -uv /proc
  3. /proc: root kernel mount root)/proc
  4. rtkit 768 .rc.. rtkitrtkit-daemon
  5. # 数据量还不会很多,虽然这个目录很繁忙~没关系!我们可以继续这样作,看看其他的程序!
  6. USER PID ACCESS COMMAND
  7. /proc: root kernel mount root)/proc
  8. root 1 f.... rootsystemd
  9. root 2 ...e. rootkthreadd
  10. .....(下面省略).....
  11. # 有这几支程序在进行 /proc 文件系统的存取喔!这样清楚了吗?
  12. 范例三:找到所有使用到 /home 这个文件系统的程序吧!
  13. [root@study ~]# echo $$
  14. 31743 # 先确认一下,自己的 bash PID 号码吧!
  15. [root@study ~]# cd /home
  16. [root@study home]# fuser -muv .
  17. USER PID ACCESS COMMAND
  18. /home: root kernel mount root)/home
  19. dmtsai 31535 ..c.. dmtsaibash
  20. root 31571 ..c.. rootpasswd
  21. root 31737 ..c.. rootsudo
  22. root 31743 ..c.. rootbash # 果然,自己的 PID 在啊!
  23. [root@study home]# cd ~
  24. [root@study ~]# umount /home
  25. umount: /home: target is busy.
  26. In some cases useful info about processes that use
  27. the device is found by lsof8 or fuser1))
  28. # 从 fuser 的结果可以知道,总共有五只 process 在该目录下运行,那即使 root 离开了 /home,
  29. # 当然还是无法 umount 的!那要怎办?哈哈!可以通过如下方法一个一个删除~
  30. [root@study ~]# fuser -mki /home
  31. /home: 31535c 31571c 31737c # 你会发现, PID 跟上面查到的相同!
  32. Kill process 31535 ? y/N # 这里会问你要不要删除!当然不要乱删除啦!通通取消!

既然可以针对整个文件系统,那么能不能仅针对单一文件啊?当然可以啰!看一下下面的案例先:

  • lsof :列出被程序所打开的文件文件名
    相对于 fuser 是由文件或者设备去找出使用该文件或设备的程序,反过来说,如何查出某个程序打开或者使用的文件与设备呢?呼呼!那就是使用 lsof 啰~
  1. [root@study ~]# lsof [-aUu] [+d]
  2. 选项与参数:
  3. -a :多项数据需要“同时成立”才显示出结果时!
  4. -u :后面接 username,列出该使用者相关程序所打开的文件;
  5. +d :后面接目录,亦即找出某个目录下面已经被打开的文件!
  6. 范例一:列出目前系统上面所有已经被打开的文件与设备:
  7. [root@study ~]# lsof
  8. COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME
  9. systemd 1 root cwd DIR 253,0 4096 128 /
  10. systemd 1 root txt REG 253,0 1230920 967763 /usr/lib/systemd/systemd
  11. ....(下面省略)....
  12. # 注意到了吗?是的,在默认的情况下, lsof 会将目前系统上面已经打开的
  13. # 文件全部列出来~所以,画面多的吓人啊!您可以注意到,第一个文件 systemd 执行的
  14. # 地方就在根目录,而根目录,嘿嘿!所在的 inode 也有显示出来喔!
  15. 范例二:仅列出关于 root 的所有程序打开的 socket 文件
  16. [root@study ~]# lsof -u root -a -U
  17. COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
  18. systemd 1 root 3u unix 0xffff8800b7756580 0t0 13715 socket
  19. systemd 1 root 7u unix 0xffff8800b7755a40 0t0 1902 @/org/freedesktop/systemd1/notify
  20. systemd 1 root 9u unix 0xffff8800b7756d00 0t0 1903 /run/systemd/private
  21. .....(中间省略).....
  22. Xorg 4496 root 1u unix 0xffff8800ab107480 0t0 25981 @/tmp/.X11-unix/X0
  23. Xorg 4496 root 3u unix 0xffff8800ab107840 0t0 25982 /tmp/.X11-unix/X0
  24. Xorg 4496 root 16u unix 0xffff8800b7754f00 0t0 25174 @/tmp/.X11-unix/X0
  25. .....(下面省略).....
  26. # 注意到那个 -a 吧!如果你分别输入 lsof -u root 及 lsof -U ,会有啥信息?
  27. # 使用 lsof -u root -U 及 lsof -u root -a -U ,呵呵!都不同啦!
  28. # -a 的用途就是在解决同时需要两个项目都成立时啊! ^_^
  29. 范例三:请列出目前系统上面所有的被启动的周边设备
  30. [root@study ~]# lsof +d /dev
  31. COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
  32. systemd 1 root 0u CHR 1,3 0t0 1028 /dev/null
  33. systemd 1 root 1u CHR 1,3 0t0 1028 /dev/null
  34. # 看吧!因为设备都在 /dev 里面嘛!所以啰,使用搜寻目录即可啊!
  35. 范例四:秀出属于 root bash 这支程序所打开的文件
  36. [root@study ~]# lsof -u root | grep bash
  37. ksmtuned 781 root txt REG 253,0 960384 33867220 /usr/bin/bash
  38. bash 13888 root cwd DIR 253,0 4096 50331777 /root
  39. bash 13888 root rtd DIR 253,0 4096 128 /
  40. bash 13888 root txt REG 253,0 960384 33867220 /usr/bin/bash
  41. bash 13888 root mem REG 253,0 106065056 17331169 /usr/lib/locale/locale-archive
  42. ....(下面省略)....

这个指令可以找出您想要知道的某个程序是否有启用哪些信息?例如上头提到的范例四的执行结果呢! ^_^

  • pidof :找出某支正在执行的程序的 PID

    范例一:列出目前系统上面 systemd 以及 rsyslogd 这两个程序的 PID
    [root@study ~]# pidof systemd rsyslogd
    1 742

    理论上,应该会有两个 PID 才对。上面的显示也是出现了两个 PID 喔。

    分别是 systemd 及 rsyslogd 这两支程序的 PID 啦。

    很简单的用法吧,通过这个 pidof 指令,并且配合 ps aux 与正则表达式,就可以很轻易的找到您所想要的程序内容了呢。 如果要找的是 bash ,那就 pidof bash ,立刻列出一堆 PID 号码了~

    原文: