SELinux:capabilities{dac_override}

来源:互联网 发布:美发教学软件 编辑:程序博客网 时间:2024/05/16 08:45

http://dragon.leanote.com/post/SELinux%EF%BC%9Acapabilities%7Bdac_override%7D

Linux支持Capability的主要目的是细化root的特权,使一个进程能够以“最小权限原则”去执行任务。比如拿ping程序来说,它需要使用原始套接字(raw_sockets),如果没有Capability,那么它就需要使用root特权才能运行;如果有了Capability机制,由于该程序只需要一个CAP_NET_RAW的Capability即可运行,那么根据最小权限原则,该程序运行时可以丢弃所有多余的Capability,以防止被误用或被攻击。所以,Capability机制可以将root特权进行很好的细分,当前kernel(2.6.18)已支持30多种不同的Capability。注意在之前的kernel实现中,Capability只能由root进程持有,非root进程是不能保持任何Capability的。但是在2.6.24及以上的kernel版本中一个普通用户进程也将可以持有capability。

capabilities安全模型用来管理 root进程的权限集,防止root用户的任意妄为。而现在的capabilities 实际上是基于selinux LSM。因此,selinux 中class capability对应于Linux中的capabilities。

而dac_override ,则用来容许进程旁路的所有DAC权限:uid,gid,ACL 等等。

注意:capabilities 和 ACL (access control lists) 实际上是非常对称的两种权限控制模型:在capabilities,授权信息 绑定到主体,基于行(row);在ACL中,授权信息绑定到客体,基于列(column)。

定义

  1. #Used to manage the Linux capabilities granted to root processes.
  2. #Taken from the header file: /usr/include/linux/capability.h
  3. class capability
  4. {
  5. ...
  6. #Overrides all DAC including ACL execute access.
  7. dac_override
  8. ...
  9. }

在man capabilities中,该权限的对应描述是:

CAP_DAC_OVERRIDE:Bypass file read, write, and execute permission checks. (DAC is an abbreviation of “discretionary access control”.)

HOOK函数

  1. //kernel/fs/namei
  2. /**
  3. * generic_permission - check for access rights on a Posix-like filesystem
  4. * @inode: inode to check access rights for
  5. * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC, ...)
  6. *
  7. * Used to check for read/write/execute permissions on a file.
  8. * We use "fsuid" for this, letting us set arbitrary permissions
  9. * for filesystem access without changing the "normal" uids which
  10. * are used for other things.
  11. *
  12. * generic_permission is rcu-walk aware. It returns -ECHILD in case an rcu-walk
  13. * generic_permission is rcu-walk aware. It returns -ECHILD in case an rcu-walk
  14. * request cannot be satisfied (eg. requires blocking or too much complexity).
  15. * It would then be called again in ref-walk mode.
  16. */
  17. int generic_permission(struct inode *inode, int mask)
  18. {
  19. int ret;
  20. /*
  21. * Do the basic permission checks.
  22. */
  23. ret = acl_permission_check(inode, mask);
  24. if (ret != -EACCES)
  25. return ret;
  26. if (S_ISDIR(inode->i_mode)) {
  27. /* DACs are overridable for directories */
  28. if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE))
  29. return 0;
  30. if (!(mask & MAY_WRITE))
  31. if (capable_wrt_inode_uidgid(inode,
  32. CAP_DAC_READ_SEARCH))
  33. return 0;
  34. return -EACCES;
  35. }
  36. /*
  37. * Read/write DACs are always overridable.
  38. * Executable DACs are overridable when there is
  39. * at least one exec bit set.
  40. */
  41. if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO))
  42. if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE))
  43. return 0;
  44. /*
  45. * Searching includes executable on directories, else just read.
  46. */
  47. mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
  48. if (mask == MAY_READ)
  49. if (capable_wrt_inode_uidgid(inode, CAP_DAC_READ_SEARCH))
  50. return 0;
  51. return -EACCES;
  52. }
  53. /**
  54. * may_follow_link - Check symlink following for unsafe situations
  55. * @link: The path of the symlink
  56. * @nd: nameidata pathwalk data
  57. *
  58. * In the case of the sysctl_protected_symlinks sysctl being enabled,
  59. * CAP_DAC_OVERRIDE needs to be specifically ignored if the symlink is
  60. * in a sticky world-writable directory. This is to protect privileged
  61. * processes from failing races against path names that may change out
  62. * from under them by way of other users creating malicious symlinks.
  63. * It will permit symlinks to be followed only when outside a sticky
  64. * world-writable directory, or when the uid of the symlink and follower
  65. * match, or when the directory owner matches the symlink's owner.
  66. *
  67. * Returns 0 if following the symlink is allowed, -ve on error.
  68. */

应用

通常,非root程序的capabilities的有效集为空。如果程序没有setuid属性,但是需要某些root特权才能工作,这就是capabilities大显身手的地方了。

下面使用cap_dac_override对于普通程序的例子,测试环境为ubuntu: 
1)首先,将系统setuid-root程序beep做一个拷贝,然后去除特权。现在,beep2就是一个非root进程,这样执行时就会因为权限不足而失败。

  1. $ ls -l /usr/bin/beep
  2. -rwsr-xr-x 1 root audio 10392 Jun 11 2012 /usr/bin/beep
  3. $ cp /usr/bin/beep beep2
  4. $ chmod a-s ./beep2
  5. $ ./beep2
  6. Could not open /dev/tty0 or /dev/vc/0 for writing
  7. open: No such file or directory

2) 然后调用setcap给beep授予赋予cap_dac_override和cap_sys_tty_config:

  1. $ sudo setcap cap_dac_override,cap_sys_tty_config+ep ./beep2
  2. $ ./beep2

3)我们可以看看beep和beep2的capability有什么不同。

  1. $getcap ./beep2
  2. ./beep = cap_dac_override,cap_sys_tty_config+ep
  3. $ getcap /usr/bin/beep
  4. --nothing--

我们可以发现beep的有效集和许可集都为空。

关于setcap cap_dac_override,cap_sys_tty_config+ep的解释:

  • + 增加
  • e 代表有效集
  • p 代表许可集
  • cap_dac_override 对应于 CAP_DAC_OVERRIDE
  • cap_sys_tty_config 对应于 CAP_SYS_TTY_CONFIG 在虚拟终端上,执行各种特权ioctl操作。

Android

在AndroidL中,分析sepolicy,具有dac_override权限的系统服务主要包括:

  • ueventd.te(7):allow ueventd self:capability { chown mknod net_admin setgid fsetid sys_rawio dac_override fowner };
  • zygote.te(7):allow zygote self:capability { dac_override setgid setuid fowner chown };
  • netd.te(44):allow netd self:capability { dac_override chown fowner };
  • runas.te(14):dontaudit runas self:capability dac_override;
  • vold.te(20):allow vold self:capability { net_admin dac_override mknod sys_admin chown fowner fsetid };
  • installd.te(6):allow installd self:capability { chown dac_override fowner fsetid setgid setuid };
  • tee.te(9):allow tee self:capability { dac_override };

tip: class capability 仅作用于进程自身,这就是上述规则中的客体都是self的原因。

需要注意的是,在AndroidL中,即使是root进程,在使用到capability时,也需要显式申请。

我会在另外一篇文章中详细探讨。


参考文献

  1. Comparing ACLs and Capabilities
  2. Passing capabilities through exec
  3. CAP_DAC_OVERRIDE - ArchWiki
  4. Exploiting capabilities
0 0
原创粉丝点击