1. 主體的標(biāo)志
在計算機(jī)安全領(lǐng)域,訪問發(fā)起者被稱為主體,訪問動作就是具體的操作,被訪問者被稱為客體。比如,進(jìn)程A 讀文件 a,進(jìn)程 A 是主體,讀是操作,文件 a 是客體。Linux的主體只能是進(jìn)程;操作只有讀、寫或者執(zhí)行;客體可以是目錄和文件{包括管道、設(shè)備、IPC(進(jìn)程間通信)、socket(套接字)、key(密鑰)}。備注:目錄的執(zhí)行是進(jìn)入,文件的執(zhí)行是運(yùn)行,只有普通文件可以執(zhí)行,管道等文件是不可以執(zhí)行的。
自主訪問控制的自主是指使用計算機(jī)的人可以決定訪問策略,比如規(guī)定某文件只能讀不能寫,制造出一種“只讀”文件,防止文件內(nèi)容被不小心更改。再比如,張三有個 mp3 文件,規(guī)定李四可以讀,但趙五不可以讀。Linux是通過uid和gid標(biāo)記一個進(jìn)程是誰在操作的,他們沒有直接記錄在task_struct結(jié)構(gòu)體中,而是記錄在task_struct結(jié)構(gòu)體中的ptracer_cred、real_cred、cred中:
struct task_struct {
...
/* Process credentials: */
/* Tracer's credentials at attach: *///調(diào)試使用的主體
const struct cred __rcu *ptracer_cred;
/* Objective and real subjective task credentials (COW): */
const struct cred __rcu *real_cred;
/* Effective (overridable) subjective task credentials (COW): */
const struct cred __rcu *cred;
...
}
從上面代碼可見,進(jìn)程的控制結(jié)構(gòu)中有三個cred :
- ptracer_cred適用于調(diào)試的,一般是該進(jìn)程被tracer控制著,記錄tracer進(jìn)程的身份和權(quán)限信息;
- real_cred存儲的是進(jìn)程初始時的身份和權(quán)限信息,為了安全性,任何時候都不能修改real_cred結(jié)構(gòu)體;
- cred,存儲的是進(jìn)程當(dāng)前的身份和權(quán)限信息,在大多數(shù)情況下,和real_cred的值是相同的,在某些情況下內(nèi)核代碼會修改當(dāng)前進(jìn)程的cred,以獲得某種訪問權(quán)限,待執(zhí)行完任務(wù)后再將主體憑證改回原值。
Linux內(nèi)核中的cred結(jié)構(gòu)體是用來存儲進(jìn)程的安全上下文,即用戶的身份信息和權(quán)限信息。cred數(shù)據(jù)結(jié)構(gòu)存儲了進(jìn)程的UID、GID、有效UID等信息,還包括一些標(biāo)志位,例如CAP_SYS_ADMIN等權(quán)限控制標(biāo)志。在Linux操作系統(tǒng)中,每個進(jìn)程都有自己的cred結(jié)構(gòu)體,用于描述它的身份和權(quán)限。當(dāng)一個進(jìn)程進(jìn)行系統(tǒng)調(diào)用或在內(nèi)核中執(zhí)行操作時,內(nèi)核會在cred結(jié)構(gòu)體中查找相應(yīng)的權(quán)限來確定該進(jìn)程是否有足夠的權(quán)限執(zhí)行該操作。這種方式可以幫助Linux操作系統(tǒng)實現(xiàn)細(xì)粒度的安全控制,例如限制用戶對關(guān)鍵系統(tǒng)資源的訪問。
struct cred {
atomic_t usage;
#ifdef CONFIG_DEBUG_CREDENTIALS
atomic_t subscribers; /* number of processes subscribed */
void *put_addr;
unsigned magic;
#define CRED_MAGIC 0x43736564
#define CRED_MAGIC_DEAD 0x44656144
#endif
kuid_t uid; /* real UID of the task */
kgid_t gid; /* real GID of the task */
kuid_t suid; /* saved UID of the task */
kgid_t sgid; /* saved GID of the task */
kuid_t euid; /* effective UID of the task */
kgid_t egid; /* effective GID of the task */
kuid_t fsuid; /* UID for VFS ops */
kgid_t fsgid; /* GID for VFS ops */
unsigned securebits; /* SUID-less security management */
kernel_cap_t cap_inheritable; /* caps our children can inherit */
kernel_cap_t cap_permitted; /* caps we're permitted */
kernel_cap_t cap_effective; /* caps we can actually use */
kernel_cap_t cap_bset; /* capability bounding set */
kernel_cap_t cap_ambient; /* Ambient capability set */
#ifdef CONFIG_KEYS
unsigned char jit_keyring; /* default keyring to attach requested
* keys to */
struct key *session_keyring; /* keyring inherited over fork */
struct key *process_keyring; /* keyring private to this process */
struct key *thread_keyring; /* keyring private to this thread */
struct key *request_key_auth; /* assumed request_key authority */
#endif
#ifdef CONFIG_SECURITY
void *security; /* subjective LSM security */
#endif
struct user_struct *user; /* real user ID subscription */
struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
struct group_info *group_info; /* supplementary groups for euid/fsgid */
/* RCU deletion */
union {
int non_rcu; /* Can we skip RCU deletion? */
struct rcu_head rcu; /* RCU deletion hook */
};
} __randomize_layout;
進(jìn)程憑證中多個 uid 機(jī)制的引入是為了在運(yùn)行時暫時授權(quán),各個uid和gid成員解析:
- uid和gid:進(jìn)程的真實用戶ID和組ID,在資源統(tǒng)計和資源分配中使用,比如限制某用戶擁有的進(jìn)程數(shù)量。
- euid和egid:進(jìn)程的有效用戶ID和組ID,在內(nèi)核做特權(quán)判斷時使用它。它的引入和提升權(quán)限有關(guān),內(nèi)核在做 ipc(進(jìn)程間通信)和 key(密鑰)的訪問控制時也使用 euid。
- suid和sgid:進(jìn)程的超級用戶ID和組ID,跟 euid 和特權(quán)有關(guān),當(dāng)euid需要為0的時候,進(jìn)程就具有了超級用戶的權(quán)限,為了讓進(jìn)程不要一直具有全部特權(quán),總能為所欲為,系統(tǒng)的設(shè)計者引入了 suid,用于暫存 euid 的值。euid 為 0 時做需要特權(quán)的操作,執(zhí)行完操作,將 0 賦予suid,euid 恢復(fù)為非 0 值,做普通的不需要特權(quán)的操作,需要特權(quán)時再將 suid 的值傳給 euid。
- fsuid和fsgid:進(jìn)程的文件系統(tǒng)用戶ID和組ID,用于在文件系統(tǒng)相關(guān)的訪問控制中判斷操作許可。比如進(jìn)程的uid 是 1000,fsuid 是 1001,進(jìn)程就具備了 1001 用戶的訪問文件的權(quán)限,但是僅僅是訪問,但不能刪除。
內(nèi)核提供了 proc 文件/proc/[pid]/status 來查看相關(guān)的信息。
2. 客體的標(biāo)記
Linux中進(jìn)程有多個 uid 和多個 gid,但是文件只有一個 uid 和一個 gid,分別稱為屬主和屬組。它們的含義是標(biāo)記文件屬于哪一個用戶,屬于哪一個用戶組。文件的標(biāo)記除了有一個 uid 和一個 gid,還有操作權(quán)限的允許位和acl權(quán)限,這些都放在內(nèi)核中 inode 結(jié)構(gòu)體:
struct inode {
umode_t i_mode;//文件的訪問權(quán)限
unsigned short i_opflags;//文件操作的狀態(tài)
kuid_t i_uid;//使用者id
kgid_t i_gid;//使用組id
unsigned int i_flags;//文件系統(tǒng)標(biāo)志
#ifdef CONFIG_FS_POSIX_ACL
//acl訪問控制相關(guān)屬性
struct posix_acl *i_acl;
struct posix_acl *i_default_acl;
#endif
const struct inode_operations *i_op;//索引節(jié)點操作方法函數(shù)
struct super_block *i_sb;//索引節(jié)點所屬超級塊
struct address_space *i_mapping;//相關(guān)地址映射(文件內(nèi)容映射)
#ifdef CONFIG_SECURITY
void *i_security;//安全模塊使用
#endif
...
} __randomize_layout;
上面是自主訪問控制用到的文件屬性,每一個成員的含義可以看注釋。
2.1 允許位
Linux采用了一種相對簡單的方式來管理操作許可,以文件為例:
- 在每個文件的屬性中存儲文件所屬的用戶(屬主)和所屬的用戶組(屬組)。
- 根據(jù)用戶的屬主和屬組將所有用戶分為三類:同主用戶、同組用戶、其他用戶。
- 在每個文件的屬性中為三類用戶分別存儲訪問許可。
內(nèi)核代碼采用一個 bit 來表示一個操作許可,對于文件就需要 9 個 bit 來表示文件的操作許可:同主讀、同主寫、同主執(zhí)行、同組讀、同組寫、同組執(zhí)行、其他讀、其他寫、其他執(zhí)行。這些表示操作許可的比特位合在一起就成為 permission bits,即允許位。其他的客體也類似,只有IPC和秘鑰是例外。IPC 只有兩個操作許可,所以只需要 6 個比特位。密鑰的操作許可是 6 個,它的允許位需要 18 個比特位。
2.2 設(shè)置位
Linux為文件分配了九個允許位,也為文件分配了三個設(shè)置位,:set-user-bit(又稱 set-user-id 或 setuid)、set-group-bit
(又稱 set-group-id 或 setgid)、set-other-bit(又稱 sticky bit);對應(yīng)三類用戶(同主、同組、其他)。引入這3個設(shè)置位更深層的目的是特權(quán)提升!
2.2.1 setuid
setuid 位僅對二進(jìn)制程序文件有效。進(jìn)程調(diào)用 execve 執(zhí)行了一個允許位 setuid 為 1 的文件后,進(jìn)程的 euid,還有Linux 特有的 fsuid,被改變?yōu)樗鶊?zhí)行文件的屬主 id。效果就是進(jìn)程執(zhí)行文件不僅將文件的內(nèi)容讀入進(jìn)程的代碼區(qū)內(nèi)存和數(shù)據(jù)區(qū)內(nèi)存,還將文件屬性中的部分?jǐn)?shù)據(jù)讀入進(jìn)程憑證。
如果普通用戶需要做一些特權(quán)操作,那么正規(guī)的做法是請求管理員代勞。但是,有的特權(quán)操作使用頻繁,又不會對系統(tǒng)帶來危害,比如探知網(wǎng)絡(luò)實體存在的 ping 命令,這種情況下總是請管理員做 ping 操作實在沒有必要,運(yùn)行 ping 的進(jìn)程具有特權(quán)就可以了。setuid的作用就是讓運(yùn)行 ping 的進(jìn)程具有特權(quán)。
實現(xiàn)流程:1.ping 文件的屬主是 root;2.ping 文件的 setuid 位被置位;3.ping 文件的允許位設(shè)置為所有人都可以執(zhí)行。這樣子,任何進(jìn)程運(yùn)行ping命令都可以運(yùn)行成功。如果setuid 位不被置位,運(yùn)行則會導(dǎo)致因為沒有root權(quán)限而運(yùn)行失敗。
修改和查看該權(quán)限位例子:
jian@ubuntu:/$ ls -l /usr/sbin/useradd
-rwxr-xr-x 1 root root 147160 Nov 29 19:53 /usr/sbin/useradd
jian@ubuntu:/$ sudo chmod u+s /usr/sbin/useradd
[sudo] password for jian:
jian@ubuntu:/$ useradd jkl
jian@ubuntu:/$ ls -l /usr/sbin/useradd
-rwsr-xr-x 1 root root 147160 Nov 29 19:53 /usr/sbin/useradd
我們可以看到user列的操作位從x變成了s。
2.2.2 setgid
setgid位的作用是,在此目錄下創(chuàng)建的文件和子目錄的屬組自動初始化為目錄的屬組。將目錄設(shè)置為SGID后,如果在該目錄下創(chuàng)建文件,都將與該目錄的所屬組保持一致。當(dāng)目錄設(shè)置了SGID位之后,任何用戶或進(jìn)程在訪問該文件或目錄時,都將具有該文件或目錄所屬的組的ID,而不是訪問者自己的組ID。例如在一個目錄中設(shè)置SGID位可以使得進(jìn)入該目錄的人員都擁有該目錄所屬組的訪問權(quán)限。在這種情況下,即使用戶擁有自己默認(rèn)組之外的其他組,他們也能夠訪問該目錄,并獲得該目錄所屬組的權(quán)限。
修改和查看該權(quán)限位例子:
jian@ubuntu:~/share/note/tt$ ls -l
drwxrwxr-x 2 jian jian 4096 Mar 30 14:58 a
jian@ubuntu:~/share/note/tt$ chmod g+s a
jian@ubuntu:~/share/note/tt$ ls -l
drwxrwsr-x 2 jian jian 4096 Mar 30 14:58 a
我們可以看到group列的操作位從x變成了s。
2.2.3 sticky
sticky 位僅對目錄有效,他的作用是在其下的文件/子目錄只能被該文件/子目錄的屬主刪除。普通用戶對該目錄擁有w和x權(quán)限,即普通用戶可以在此目錄中擁有寫入權(quán)限,如果沒有sticky 位,那么普通用戶擁有w權(quán)限,就可以刪除此目錄下的所有文件,包括其他用戶建立的文件。但是一旦被賦予了sticky 位,除了root可以刪除所有文件,普通用戶就算有w權(quán)限也只能刪除自己建立的文件,而不能刪除其他用戶建立的文件。典型的用法是將系統(tǒng)臨時目錄/tmp 的 sticky bit 置位,這樣子所有用戶都可以讀取到tmp下的文件,卻只有root或者文件屬主有權(quán)限刪除文件。
總結(jié)就是:
- 帶有sticky 位權(quán)限的目錄下的所有文件,誰都可以讀、寫 ;
- 帶有sticky 位權(quán)限的目錄下的文件只有屬主能刪除自己的文件,其他用戶無法刪除;
- 帶有sticky 位權(quán)限的目錄,只有root能刪除。
修改和查看該權(quán)限位例子:
jian@ubuntu:~/share/note/tt$ ls -l
total 4
drwxrwsr-x 2 jian jian 4096 Mar 30 14:58 a
jian@ubuntu:~/share/note/tt$ chmod o+t a
jian@ubuntu:~/share/note/tt$ ls -l
total 4
drwxrwsr-t 2 jian jian 4096 Mar 30 14:58 a
我們可以看到other列的操作位從x變成了t。
3. ACL(訪問控制列表)
從某個文件的角度看,Linux通過文件屬性中的屬主和屬組,把系統(tǒng)中的進(jìn)程分為三類:同主、同組、其他。UNIX 通過文件屬性中允許位的九個比特,使這三類進(jìn)程分別擁有自己的操作許可。Linux還可以通過 ACL訪問控制列表動態(tài)添加和刪除某主或者某組的進(jìn)程的操作權(quán)限。
訪問控制列表存儲在文件的擴(kuò)展屬性之中。在支持?jǐn)U展屬性的文件系統(tǒng)中,inode 和擴(kuò)展屬性在存儲設(shè)備上是分開存儲的,在 inode 中保留一個關(guān)聯(lián)到擴(kuò)展屬性的索引。擴(kuò)展屬性本身則被實現(xiàn)為一個數(shù)組,數(shù)組項又分為屬性名和屬性值兩部分。屬性名是一個字符串,屬性值可以是任意類型。屬性名字符串本身也是有格式的,它由“.”分割為若干域,比如“system.posix_acl_access”。其中第一個域必須是下列四個之一:user、system、trusted、security,表示它們分別用于應(yīng)用、系統(tǒng)、可信和安全。和訪問控制列表相關(guān)的擴(kuò)展屬性有兩個,屬性名分別是 system.posix_acl_access 和system.posix_acl_default。
前面我們看到inode結(jié)構(gòu)體的成員i_acl和i_default_acl是指向struct posix_acl的指針,我們看看struct posix_acl吧:
struct posix_acl {
refcount_t a_refcount;
struct rcu_head a_rcu;
unsigned int a_count;//entry的計數(shù)
struct posix_acl_entry a_entries[];//entry存放處
};
struct posix_acl_entry {
short e_tag;
unsigned short e_perm;//權(quán)限位
union {//ID的聯(lián)合體
kuid_t e_uid;
kgid_t e_gid;
};
};
訪問控制列表被實現(xiàn)為一個零長的數(shù)組。ACL entry 有三個重要成員:tag、id、permission-bits。我們先看tag的值可以有哪些:
tag | 含義 |
---|---|
ACL_USER_OBJ | ACL_USER_OBJ 規(guī)定文件屬主的操作許可。 |
ACL_GROUP_OBJ | ACL_GROUP_OBJ 規(guī)定文件屬組的操作許可。 |
ACL_USER | ACL_USER 為某一個用戶規(guī)定操作許可,id 存儲的是用戶id,當(dāng)進(jìn)程fsuid 與該項 id 相同時,進(jìn)程對文件的操作許可由此項 ACL entry中的 permission-bits 規(guī)定 |
ACL_GROUP | ACL_GROUP 為某一個組規(guī)定操作許可,id 存儲的是組 id,當(dāng)進(jìn)程 fsgid 與該項 id 相同時,進(jìn)程對文件的操作許可由此項 ACL entry中的 permission-bits 規(guī)定 |
ACL_OTHER | 當(dāng)一個進(jìn)程的 fsuid 和任何一項 ACL_USER 中規(guī)定的 id 都不匹配,fsgid 和任何一個ACL_GROUP 中規(guī)定的 id 都不匹配,fsuid 不等于文件的屬主,且 fsgid 不等于文件的屬組,此時進(jìn)程對文件的操作許可由此項中的 permission-bits 規(guī)定。 |
ACL_MASK | ACL_MASK 的引入是為了給規(guī)定的部分操作許可設(shè)置一個上限。進(jìn)程從 ACL_USER、ACL_GROUP、ACL_GROUP_OBJ 項獲得的操作許可如果不出現(xiàn)在ACL_MASK 項的permission-bits 中,該操作許可會被清除。 |
ACL 使管理的粒度變細(xì),相應(yīng)地,控制邏輯也變復(fù)雜了:
- 如果進(jìn)程的 fsuid 等于文件的屬主,則判斷進(jìn)程申請的操作是否在 ACL_USER_OBJ項的 permission-bits 中,若是,返回允許,否則返回拒絕。
- 如果進(jìn)程的 fsuid 等于文件的某一項 ACL_USER 中規(guī)定的 id,則判斷進(jìn)程申請的操作是否在該項的 permission-bits 和 ACL_MASK 項的 permission-bits 的交集中,若是,返回允許,否則返回拒絕。
- 如果進(jìn)程的 fsgid 或補(bǔ)充組中的任何一個 gid 等于文件的屬組或某一項 ACL_GROUP中規(guī)定的 id,則判斷進(jìn)程申請的操作是否在該項的 permission-bits 和ACL_MASK 項的 permission-bits 的交集中,若是,返回允許,否則返回拒絕。
- 如果進(jìn)程申請的操作出現(xiàn)在 ACL_OTHER 項的 permission-bits 中,返回允許,否則返回拒絕。
ACL和允許位的關(guān)系:
允許位分為三部分:三個比特位表示同主進(jìn)程的操作許可,三個比特位表示同組進(jìn)程的操作許可,三個比特位表示其他進(jìn)程的操作許可。這三部分很自然地和 ACL 中 ACL_USER_OBJ、ACL_GROUP_OBJ、ACL_OTHER 對應(yīng)。改允許位,ACL 跟著變動;改 ACL,允許位跟著變動。屬組部分的允許位有一個例外:當(dāng) ACCESS 型 ACL 有 ACL_MASK 項存在時,屬組部分允許位和 ACL_MASK 項的 permission-bits 對應(yīng)。反之,當(dāng) ACCESS 型 ACL 沒有 ACL_MASK項存在時,屬組部分允許位和 ACL_GROUP_OBJ 項的 permission-bits 對應(yīng)。文章來源:http://www.zghlxwxcb.cn/news/detail-735687.html
4. 能力控制
Linux 內(nèi)核的能力機(jī)制是為了解決傳統(tǒng)的 UNIX 內(nèi)核的特權(quán)判定過于簡單而產(chǎn)生的。Linux內(nèi)核的能力機(jī)制將傳統(tǒng)的特權(quán)進(jìn)行了分割,使得最小特權(quán)原則有可能實現(xiàn)。這是一個進(jìn)步。但是,由于能力機(jī)制的復(fù)雜和能力機(jī)制與原有基于用戶標(biāo)識機(jī)制的不兼容,能力機(jī)制沒有被廣泛
使用。而且由于能力機(jī)制的后向兼容可以做到讓舊有的應(yīng)用不需修改即可使用,廣大的應(yīng)用開發(fā)者甚至根本不知道 Linux 內(nèi)核能力機(jī)制的存在。我也是無意中看到,也不知道怎么用,但是還是在這里占個位吧。具體的能力可以看 include/uapi/linux/capability.h文件。文章來源地址http://www.zghlxwxcb.cn/news/detail-735687.html
到了這里,關(guān)于linux安全-自主訪問控制的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!