Chapter 1 Linux 系统安全基础¶
1 Users and Groups¶
1. 1 Users¶
Linux 为每个用户分配一个唯一的 UID(User ID),系统通过 UID 识别用户,而不是只依赖用户名。
- 用户信息保存在
/etc/passwd中 root用户的特殊 UID 是0,系统通常依据 UID 判断其权限,因此 UID 为0的账户具有 root 级别权限- 用户的主组由
/etc/passwd中的 GID 字段指定
使用 id 查看当前用户的 UID、GID 和所属用户组
seed@VM:~$ id
uid=1000(seed) gid=1000(seed) groups=1000(seed)
root@VM:~# id
uid=0(root) gid=0(root) groups=0(root)
添加用户有两种方式:
- 直接修改
/etc/passwd,但还需要同时处理用户组、主目录、密码和登录 shell 等信息 - 使用
adduser命令,由系统完成用户创建相关工作
切换到其他用户
seed@VM:~$ su bob
Password:
bob@VM:/home/seed$
1. 2 Groups¶
Group(用户组) 表示一组用户,主要用于按照组分配访问权限。一个用户可以属于多个用户组。用户的主组(primary group)记录在 /etc/passwd 的 GID 字段中,其他附加组通常记录在 /etc/group 中。
Which group does a user belong to?
可以使用 groups、id 或查询 /etc/group:
seed@VM:~$ groups
seed adm sudo plugdev lpadmin lxd docker
seed@VM:~$ id
uid=1000(seed) gid=1000(seed) groups=1000(seed),4(adm),27(sudo),46(plugdev),120(lpadmin),131(lxd),136(docker)
seed@VM:~$ grep seed /etc/group
adm:x:4:syslog,seed
sudo:x:27:seed
plugdev:x:46:seed
lpadmin:x:120:seed
lxd:x:131:seed
seed:x:1000:
docker:x:136:seed
创建用户组并把用户加入用户组
$ sudo groupadd alpha
$ sudo usermod -a -G alpha seed
$ sudo usermod -a -G alpha bob
-a表示 append,和-G一起使用时追加用户组,省略-a可能覆盖用户原有的附加组
2 Permissions and Access Control¶
| 文件权限 | 目录权限 | |
|---|---|---|
r(read) |
查看文件内容 | 列出目录内容,例如使用 ls |
w(write) |
修改文件内容 | 在目录中创建文件和子目录 |
x(execute) |
执行或运行文件 | 进入目录,例如使用 cd |
2. 1 File Permissions¶

权限也可以用八进制表示
权限位 r、w、x、- 对应的数值依次为 4、2、1、0,每三个权限位对应一个八进制数字,例如 rwxr-xr-x = 755。
使用 chmod 修改权限
chmod u+x file # 为 owner 增加执行权限
chmod g-w file # 删除 group 的写权限
chmod o-r file # 删除 other 的读权限
chmod 755 file # 直接使用八进制设置权限
2. 2 Default File Permissions¶
umask 决定新建文件或目录的默认权限,新建对象的最终权限由初始权限和 umask 共同决定。
普通文件的初始权限通常为 0666,不包含执行权限,目录的初始权限通常为 0777。umask 中为 1 的位会屏蔽对应的默认权限。
示例
$ umask
0002
$ touch t1
$ umask 0022
$ touch t2
$ umask 0777
$ touch t3
对普通文件,初始权限为 0666:
Initial (0666) rw- rw- rw-
110 110 110
umask (0022) 000 010 010
--------------------------------
Final 110 100 100
rw- r-- r--
最终结果:
$ ls -l t*
-rw-rw-r-- 1 seed seed 0 Feb 6 16:23 t1
-rw-r--r-- 1 seed seed 0 Feb 6 16:24 t2
---------- 1 seed seed 0 Feb 6 16:24 t3
2. 3 Access Control List¶
ACL(Access Control List,访问控制列表) 提供比传统 owner-group-other 模型更细粒度的权限控制,可以为单独的用户或用户组分配权限,也可以与传统权限模型共存,适合需要对多个特定用户或用户组单独授权的场景。
getfacl 命令查看 ACL 权限
$ getfacl example
# file: example
# owner: seed
# group: seed
user::rw-
group::rw-
other::r--
setfacl 命令设置 ACL 权限
setfacl {-m, -x} {u, g}:<name>:[r, w, x] <file, directory>
-m(modify):添加或修改 ACL 条目-x(remove):删除 ACL 条目u:<name>:指定用户g:<name>:指定用户组
示例
$ setfacl -m u:alice:r-- example
$ setfacl -m g:faculty:rw- example
$ getfacl example
# file: example
# owner: seed
# group: seed
user::rw-
user:alice:r--
group::rw-
group:faculty:rw-
mask::rw-
other::r--
mask表示 ACL 中命名用户、命名用户组以及文件拥有组能够获得的最大有效权限- 文件拥有者和
other不受mask限制 - 文件具有扩展 ACL 时,
ls -l的权限字段末尾会出现+
-rw-rw-r--+ 1 seed seed 1050 Feb 7 10:57 example
3 Running Commands with Privilege¶
Why Need Privilege Mechanisms?
Linux 中有些操作需要超级用户权限,常见的三种机制是:
sudo:以授权方式运行需要特权的命令。- set-uid programs:通过程序文件的 SUID 位临时使用文件拥有者身份。
- POSIX capabilities:把超级用户权限拆分为更细粒度的能力集合。
3. 1 Using sudo¶
sudo 是 Super-user Do 的缩写,用于以超级用户身份运行命令:
sudo <command>
用户必须先获得授权,授权规则通常写在 /etc/sudoers 中。Ubuntu 中的典型配置为:
In /etc/sudoers
%sudo ALL=(ALL:ALL) ALL
其中 %sudo 表示 sudo 用户组,而不是名为 sudo 的单个用户。该规则允许 sudo 组中的用户以其他用户和用户组身份运行命令。
用户是否属于 sudo 组可以在 /etc/group 中看到:
In /etc/group
sudo:x:27:seed
这里表示 seed 属于 GID 为 27 的 sudo 组,因此可以使用 sudo。
3. 2 Getting Root Shell¶
在 Ubuntu 20.04 中,root 用户账户默认被锁定,不能直接登录 root 账户。
通过已有的 sudo 权限获得 root shell
sudo -s
sudo bash
sudo su
不建议长期使用 root shell
root shell 中执行的每条命令都具有最高权限,出错或误操作的影响范围很大。通常应当只对需要特权的单条命令使用 sudo,而不是进入 root shell 后一直工作。
3. 3 Running Command Using Another User¶
sudo 默认以 root 身份执行命令,也可以通过 -u 指定其他用户。
以 bob 身份运行 id
$ sudo -u bob id
uid=1001(bob) gid=1001(bob) groups=1001(bob),1004(alpha)
4 Authentication¶
4. 1 Authentication Methods¶
Authentication(认证) 是验证用户身份的过程,即确认发起请求的主体确实是其声称的用户。
| 常见认证因素类型 | 含义 | 示例 |
|---|---|---|
| Something you know | 用户知道的信息 | password |
| Something you have | 用户持有的物品 | ID card |
| Something you are or do | 用户的生物特征或行为特征 | fingerprint |
多因素认证(Multi-factor authentication) 同时使用两种或更多不同类型的认证因素,例如密码加身份证明设备,不能只把同一种因素重复使用当作多因素认证。
4. 2 The Password File¶
Linux 的 /etc/passwd 文件保存每个用户账户的基本信息。/etc/passwd 每行对应一个账户,字段格式为:
username:password:UID:GID:GECOS:home directory:login shell
各字段含义
| 字段 | 含义 |
|---|---|
username |
用户名 |
x |
密码占位符,实际密码信息保存在 |
UID |
用户 ID,一般新建普通用户 uid 从 1000 开始 |
GID |
用户的主组 ID |
GECOS |
用户描述、姓名等信息 |
home directory |
用户的主目录 |
login shell |
登录后启动的 shell |
示例
root:x:0:0:root:/root:/bin/bash
seed:x:1000:1000:SEED,,,:/home/seed:/bin/bash
bob:x:1001:1001:Bob,,,:/home/bob:/bin/bash
alice:x:1002:1003:Alice,,,:/home/alice:/bin/bash
4. 3 First Command After Login¶
登录成功后,登录程序会执行 /etc/passwd 每行最后一个字段指定的 shell。这个 shell 通常是用户登录后执行的第一个命令程序,例如 /bin/bash。
系统账户通常不允许交互式登录,会把登录 shell 设置为特殊程序,例如 /usr/sbin/nologin 和 /bin/false。
示例
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,,:/var/lib/tpm:/bin/false
gdm:x:125:130:Gnome Display Manager:/var/lib/gdm3:/bin/false
当目标用户的 shell 是 /usr/sbin/nologin 或 /bin/false 时,切换到该用户会失败:
$ sudo su bin
This account is currently not available.
4. 4 The Shadow File¶
Why not use /etc/password anymore?
/etc/passwd 通常需要对所有用户可读。如果把密码哈希放在这里,任何普通用户都可以收集哈希并进行离线破解。
/etc/shadow 每行的基本结构为:
login:encrypted password:last change:min:max:warn:inactive:expire:reserved
各字段含义
| 字段 | 含义 |
|---|---|
login |
用户名 |
encrypted password |
密码哈希及其算法、salt |
last change |
上次修改密码的日期,通常表示为自 1970-01-01 起的天数 |
min |
修改密码后至少经过多少天才能再次修改 |
max |
密码最多有效多少天 |
warn |
密码过期前提前警告的天数 |
inactive |
密码过期后账户保持可用的天数 |
expire |
账户过期日期 |
reserved |
保留字段 |

4. 5 The Purpose of Salt¶
密码字段通常包含 $6$<salt>$<password hash> 的结构,其中 salt 可以提高暴力破解的成本、增加字典攻击的难度、破坏预先计算的 rainbow table,使使用同一个密码的不同账户得到不同的密码哈希。
示例
seed:$6$n8DimvsbIgUO0xbD$YZ0h1EA...(omitted)...wFd0:18590:0:
alice:$6$.1CMC.../8Qzl$QhfhId...(omitted)...Sga.:18664:0:
bob:$6$NOLhqomO3yNwYFsZ$K.Q1/KnP...(omitted)...b8v.:18664:0:
$6$表示所使用的哈希算法标识,在常见 Linux 配置中代表 SHA-512salt是为该账户随机生成的盐值- 最后一段是使用 salt 计算得到的密码哈希
4. 6 Locking Account¶
可以在密码字段放入无效值来锁定账户。例如:
root:!:18590:0:99999:7:::
密码字段中的 ! 不是有效的密码哈希,因此通过密码认证无法登录该账户。
在 Ubuntu 中,root 账户默认处于锁定状态,用户不能直接用 root 密码登录,但已授权的普通用户仍然可以通过 sudo 执行需要 root 权限的命令。