Linux小白修炼日记 Day 07:用户、组与权限模型,一次搞懂为什么不能乱用chmod 777
- 一、为什么应用需要独立身份
- 二、用户、组与账号生命周期
- 2.1 Linux 身份模型
- 2.2 三个账号文件及字段
- /etc/passwd:账号基本信息
- /etc/shadow:密码状态和有效期
- /etc/group:组及附加组成员
- 2.3 新建组和用户
- 2.4 修改、锁定、过期与删除
- 2.5 身份切换与验证
- 三、Owner、Group、rwx 与 chmod
- 3.1 读懂所有权和权限串
- 3.2 文件与目录的 rwx
- 3.4 目录逐级权限
- 四、默认权限与特殊权限
- 4.1 umask 与默认权限
大家好,我是正在转行运维的小白。今天是我更新 Linux 学习日记的第七天。
前六天学会了装系统、命令模型、路径编辑、文件管理、日志分析。今天进入运维安全的核心一课:用户、组与权限。
这一课解决一个让我困惑很久的问题:为什么应用要用独立账号跑?为什么遇到 Permission denied 不能直接 chmod 777?
学完这篇,你会为若依后端创建一个受限运行账号,走完一次真实的权限故障排查。
一、为什么应用需要独立身份
一台 Linux 主机常同时运行 Nginx、Java 应用和数据库。如果它们都用 root,一个程序出现漏洞,就可能危及整台主机。
生产环境通常为每个服务准备独立账号,只授予业务必需的权限。
今天只回答两个问题:
1. 谁在访问:实际运行身份是谁,属于哪些组? 2. 能否访问:路径、Owner、Group 和 rwx 是否满足需求?⚠️遇到 Permission denied,不要直接执行
chmod 777。
先确认身份,再逐级检查路径权限,只修复缺少的权限。
二、用户、组与账号生命周期
先分清用户名、UID、主组和附加组。
| 名称 | 含义 | 作用 |
|---|---|---|
| User | 用户 | 表示登录人员或运行程序的身份 |
| UID | 用户标识号 | 内核识别用户的数字编号 |
| Group | 组 | 把多个用户纳入同一授权范围 |
| GID | 组标识号 | 内核识别组的数字编号 |
| Primary Group | 主组 | 用户必须有且只有一个,影响新文件默认属组 |
| Supplementary Group | 附加组 | 用户可加入多个,获得额外的组访问资格 |
2.1 Linux 身份模型
用户名方便人识别,Linux 内核主要使用数字身份判断资源归属。
whoamiidgroups在 Ubuntu 常见默认设置中:
| UID 范围 | 用途 |
|---|---|
| 0 | root |
| 1–999 | 系统和服务账号 |
| 1000 及以上 | 普通用户 |
⚠️ 这些范围可以通过系统配置调整,不要把它们当成所有 Linux 的固定规则。
2.2 三个账号文件及字段
/etc/passwd、/etc/shadow、/etc/group共同描述本地账号。账号管理命令会维护这些文件,日常查询优先使用getent、id、passwd -S和chage -l,不要直接编辑账号文件。
/etc/passwd:账号基本信息
一条记录使用冒号分隔七个字段:
cc:x:1000:1000:CC:/home/cc:/bin/bash ```| 字段 | 示例 | 含义 | |------|------|------| | 1 | cc | 用户名 | | 2 | x | 密码占位符,密码信息保存在 `/etc/shadow` | | 3 | 1000 | UID | | 4 | 1000 | 主组 GID | | 5 | CC | 描述信息 | | 6 | /home/cc | 家目录 | | 7 | /bin/bash | 登录 Shell |```bash getent passwd cc/etc/shadow:密码状态和有效期
sudogetent shadow ccsudopasswd-Sccsudochage-lcc
/etc/shadow保存密码哈希或锁定标记,以及密码修改、有效期和账号到期信息。
排查时优先看passwd -S和chage -l,不要求手工换算天数。
/etc/group:组及附加组成员
一条记录使用冒号分隔四个字段:
组名:密码占位符:GID:附加组成员列表| 字段 | 含义 |
|---|---|
| 1 | 组名 |
| 2 | 组密码占位符,通常为 x |
| 3 | GID |
| 4 | 附加组成员列表,多个用户名用逗号分隔 |
⚠️第四字段只记录附加组成员。用户的主组需要结合
/etc/passwd中的主 GID 判断。
查看完整组关系应使用id 用户名。
id 相关命令:
| 命令 | 查看内容 |
|---|---|
id -un | 当前用户名 |
id -u | 当前用户的 UID |
id -gn | 当前主组名 |
id -g | 当前主组的 GID |
id -Gn | 当前用户所属的全部组名 |
id-unid-uid-gnid-gid-Gngetent group"$(id-gn)"2.3 新建组和用户
Linux 账号和组名在生产环境中通常使用小写。部门名称可以写成 QA、HR,实际组名使用qa、hr,便于脚本和统一认证系统处理。
课程练习组:
| 组名 | 中文名称 | 课程用途 |
|---|---|---|
| rd | 研发组 | 应用研发 |
| qa | 质量保证组 | 软件测试 |
| devops | 开发与运维协作组 | 共享目录 |
| hr | 人力资源组 | 账号分组 |
创建四个练习组:
getent group rd>/dev/null||sudogroupaddrd getent group qa>/dev/null||sudogroupaddqa getent group devops>/dev/null||sudogroupadddevops getent group hr>/dev/null||sudogroupaddhr getent group rd getent group qa getent group devops getent group hr💡
||表示前一条查询失败时才执行创建命令。
创建三个练习用户:
getentpasswdtianyun>/dev/null||sudouseradd-m-s/bin/bash tianyun getentpasswdjinghui>/dev/null||sudouseradd-m-s/bin/bash jinghui getentpasswdalice>/dev/null||sudouseradd-m-s/bin/bash alicesudopasswd111sudopasswd222
-m创建家目录,-s指定登录 Shell。Ubuntu 默认创建同名私有组。
后面的若依服务账号再使用-r、-M、-g。
查看新用户在三个账号文件中的记录:
getentpasswdtianyunsudogetent shadow tianyun getent group rdidtianyun
useradd创建账号后,基本信息出现在/etc/passwd,密码状态出现在/etc/shadow,主组通过 GID 与/etc/group关联。
2.4 修改、锁定、过期与删除
追加附加组时必须使用-aG:
sudousermod-aGrd,devops tianyunsudousermod-aGqa,devops jinghuisudousermod-aGhr aliceidtianyunidjinghuiidalice getent group devops⚠️单独使用
-G会重设附加组列表;-aG才是在现有列表上追加。
已登录的会话可能仍保留旧组列表,需要重新登录后验证。
锁定、恢复和设置过期日:
sudousermod-Ltianyunsudopasswd-Stianyunsudousermod-Utianyunsudousermod-e2026-12-31 tianyunsudochage-ltianyunsudousermod-e''tianyun⚠️密码锁定不会终止已经运行的进程。真实停用场景还要检查 SSH 密钥、计划任务和运行进程。
使用 alice 演示删除账号:
pgrep-a-ualicesudouserdel-ralice getentpasswdalice⚠️生产环境删除账号前还要归档并移交文件。
tianyun和jinghui暂时保留,后面的目录权限与特殊权限实验继续使用。
2.5 身份切换与验证
新开 tianyun 用户终端:
su-111whoamiidpwdmkdir-p~/day07-user-checktouch~/day07-user-check/111.txtls-l~/day07-user-check再开 jinghui 用户终端:
su-222whoamiidpwdcat/etc/hosts保留这两个用户终端。管理命令仍在原来的 cc 终端执行。
三、Owner、Group、rwx 与 chmod
⚠️权限排障不仅要看文件,还要看文件所在的每一级目录。
3.1 读懂所有权和权限串
权限串依次表示:文件类型、Owner、Group、Other。
Linux 只选择与当前身份匹配的一类传统权限,不会把 Owner、Group、Other 三组权限相加。
chown修改属主或属组,chgrp只修改属组:
mkdir-p~/ccvm/CCvm/day07echo'server.port=8080'>~/ccvm/CCvm/day07/application.confls-l~/ccvm/magedu/day07/application.confstat-c'%A %a %U:%G %n'~/ccvm/CCvm/day07/application.confsudochownroot:devops ~/ccvm/CCvm/day07/application.confsudochgrpqa ~/ccvm/CCvm/day07/application.confls-l~/ccvm/CCvm/day07/application.confsudochowncc:cc ~/ccvm/CCvm/day07/application.conf⚠️递归修改前应先用 find 预览明确目录,不能在不确定的路径上直接使用
chown -R。
3.2 文件与目录的 rwx
| 权限 | 普通文件 | 目录 |
|---|---|---|
| r | 读取文件内容 | 列出目录项名称 |
| w | 修改文件内容 | 创建、删除、重命名目录项(通常还需 x) |
| x | 把文件作为程序执行 | 穿越目录并访问内部对象 |
💡删除一个文件主要取决于父目录的 w+x,不是目标文件本身有没有 w。
验证普通文件的执行权限:```bash
echo ‘#!/bin/bash’ > ~/ccvm/CCvm/day07/check.sh
echo ‘echo 111’ >> ~/ccvm/CCvm/day07/check.sh
chmod 0644 ~/ccvm/CCvm/day07/check.sh
~/ccvm/CCvm/day07/check.sh # 失败:Permission denied
chmod u+x ~/ccvm/CCvm/day07/check.sh
~/ccvm/CCvm/day07/check.sh # 输出 111
**验证目录只有 r、没有 x 时的效果:** ```bash sudo mkdir -p /srv/day07-lab/dir-lab echo 'secret' | sudo tee /srv/day07-lab/dir-lab/data.txt >/dev/null sudo chmod 0644 /srv/day07-lab/dir-lab/data.txt sudo chmod 0744 /srv/day07-lab/dir-lab ``` **tianyun 用户终端:** ```bash ls /srv/day07-lab/dir-lab # 能看到文件名 cat /srv/day07-lab/dir-lab/data.txt # 不能读取 touch /srv/day07-lab/dir-lab/file2.txt # 不能创建 mkdir /srv/day07-lab/dir-lab/dir2 # 不能创建 ``` **增加目录 x:** ```bash sudo chmod 0755 /srv/day07-lab/dir-lab ``` **tianyun 用户终端:** ```bash cat /srv/day07-lab/dir-lab/data.txt # 可以读取 touch /srv/day07-lab/dir-lab/file2.txt # 仍然失败,Other 只有 r+x ``` ### 3.3 chmod 的符号方式与数字方式 **符号方式 = 对象 + 操作 + 权限:**```bash chmod u+x ~/ccvm/CCvm/day07/check.sh chmod g-r ~/ccvm/CCvm/day07/application.conf chmod o= ~/ccvm/CCvm/day07/application.conf chmod u=rw,g=r,o= ~/ccvm/CCvm/day07/application.conf ```| ```bash chmod u+x ~/cc/CCvm/day07/check.sh chmod g-r ~/cc/CCvm/day07/application.conf chmod o= ~/cc/CCvm/day07/application.conf chmod u=rw,g=r,o= ~/cc/CCvm/day07/application.conf ``` **数字方式:`r=4`、`w=2`、`x=1`,每一组按位组合:** | 数字 | 权限 | 含义 | |------|------|------| | 7 | rwx | 完整读写执行 | | 6 | rw- | 读写 | | 5 | r-x | 读取与执行或穿越 | | 4 | r-- | 只读 | | 0 | --- | 无权限 |```bash chmod 0640 ~/ccvm/magedu/day07/application.conf sudo chmod 0750 /srv/day07-lab/dir-lab stat -c '%A %a %n' ~/ccvm/magedu/day07/application.conf /srv/day07-lab/dir-lab💡数字方式表达明确的目标状态;符号方式适合在当前状态上增加或删除某一项权限。
3.4 目录逐级权限
访问若依配置文件时,需要穿过/、/srv、/srv/ruoyi和/srv/ruoyi/shared。任何一级目录缺少 x,即使最终文件可读也无法到达。
namei-l/etc/passwdls-ld/ /etcls-l/etc/passwd
namei可以把一条路径逐级拆开,-l同时显示每一级对象的类型、权限、Owner 和 Group。
排障时从根目录开始,定位第一处不满足项,不要只盯着最后一个文件。
四、默认权限与特殊权限
4.1 umask 与默认权限
新文件从 666 的候选权限开始,新目录从 777 开始,再由 umask 屏蔽相应权限位。普通文件默认不会增加执行位```bash
mkdir -p ~/ccvm/CCvm/day07/umask-lab
umask 0027
touch ~/ccvm/CCvm/day07/umask-lab/file-027
mkdir ~/ccvm/CCvm/day07/umask-lab/dir-027
stat -c ‘%A %a %n’ ~/ccvm/CCvm/day07/umask-lab/*
**实验:** ```bash mkdir -p ~/cc/CCvm/day07/umask-lab umask 0027 touch ~/cc/CCvm/day07/umask-lab/file-027 mkdir ~/cc/CCvm/day07/umask-lab/dir-027 stat -c '%A %a %n' ~/cc/CCvm/day07/umask-lab/* ``` **预期文件为 640,目录为 750。实验结束后恢复原来的 umask。** ```bash umask 0022 # 恢复实验前的值 ``` > ⚠️ **不要把 umask 简单理解成十进制减法,应把它理解为按位屏蔽。** ### 4.2 SUID、SGID 与 Sticky Bit | 特殊权限 | 数字位 | 字母显示位置 | 常见对象 | 核心作用 | |---------|--------|-------------|---------|---------| | SUID | 4000 | Owner 的 x 位置显示 `s` | 可执行文件 | 执行时临时取得文件 Owner 的有效身份 | | SGID | 2000 | Group 的 x 位置显示 `s` | 共享目录 | 新对象继承目录的 Group | | Sticky Bit | 1000 | Other 的 x 位置显示 `t` | 公共可写目录 | 限制用户删除或改名他人拥有的目录项 | > 💡 小写 `s` 或 `t` 表示**特殊权限与对应的执行权限同时存在**; > 大写 `S` 或 `T` 表示**设置了特殊权限,但对应位置没有执行权限**,通常需要继续检查。 #### 4.2.1 SUID:临时使用属主身份 **把 SUID 想成「尚方宝剑」:钦差拿到宝剑,可以临时代表皇帝办事,但他并没有变成皇帝。** | 故事中的角色 | Linux 中的对应对象 | |-------------|-------------------| | 皇帝 | 文件 Owner,例如 root | | 尚方宝剑 | 设置了 SUID 的可执行程序,例如 `passwd` | | 持剑执行任务的钦差 | 启动程序的普通用户 | **典型系统示例:** ```bash command -v passwd ls -l /usr/bin/passwd stat -c '%A %a %U:%G %n' /usr/bin/passwd ls -l /etc/shadow ``` 典型结果中,`/usr/bin/passwd` 的 Owner 执行位显示为 `s`,数字权限包含 4 开头(如 4755)。 **普通用户不能直接写 `/etc/shadow`,但可以通过 passwd 修改自己的密码**;passwd 只在受控代码路径中使用所需的 root 权限。 > ⚠️ **SUID 会扩大程序漏洞的影响范围。** 这里只观察系统已有的 `/usr/bin/passwd`,**不要给 cat、rm、Shell 或自行编写的练习脚本添加 SUID。** #### 4.2.2 SGID:继承目录属组 **多人共同维护一个目录时,如果新文件总是使用创建者的主组,其他成员可能无法继续协作。** 目录上的 SGID 可以让**新文件和新目录继承父目录的 Group**。 ```bash sudo mkdir -p /srv/day07-lab/sgid-share sudo chown root:devops /srv/day07-lab/sgid-share sudo chmod 2775 /srv/day07-lab/sgid-share stat -c '%A %a %U:%G %n' /srv/day07-lab/sgid-share ``` **tianyun 用户终端:** ```bash touch /srv/day07-lab/sgid-share/file1.txt stat -c '%A %a %U:%G %n' /srv/day07-lab/sgid-share/file1.txt ``` > 目录的 Group 执行位显示为 `s`,数字权限为 2775。 > **tianyun 的主组与用户名相同,但 file1.txt 的 Group 应继承为 devops。** **暂时取消 SGID:** ```bash sudo chmod 0775 /srv/day07-lab/sgid-share ``` **tianyun 用户终端:** ```bash touch /srv/day07-lab/sgid-share/file2.txt stat -c '%A %a %U:%G %n' /srv/day07-lab/sgid-share/file1.txt /srv/day07-lab/sgid-share/file2.txt ``` > 没有 SGID 时,file2.txt 通常使用创建者的主组 tianyun。 ```bash sudo chmod 2775 /srv/day07-lab/sgid-share ``` > **SGID 只决定所属组继承,实际能否读写仍受 rwx、umask 和 ACL 共同影响。** #### 4.2.3 Sticky Bit:限制删除他人文件 > ⚠️ **删除文件主要取决于所在目录的 w+x,不是只看文件本身的 w。** **先观察 /tmp:** ```bash stat -c '%A %a %U:%G %n' /tmp ``` 典型结果为 `drwxrwxrwt` 和 `1777`,最后一位 `t` 就是 Sticky Bit。 **对比 0777 与 1777:** ```bash sudo mkdir -p /srv/day07-lab/public sudo chmod 0777 /srv/day07-lab/public whoami echo 111 > /srv/day07-lab/public/file1.txt ls -l /srv/day07-lab/public/file1.txt ``` **jinghui 用户终端:** ```bash whoami rm /srv/day07-lab/public/file1.txt ``` > jinghui 不是文件 Owner,**但因为对目录拥有 w+x,仍能删除 file1.txt。** **增加 Sticky Bit:** ```bash sudo chmod 1777 /srv/day07-lab/public stat -c '%A %a %U:%G %n' /srv/day07-lab/public ``` **jinghui 用户终端:** ```bash echo 222 > /srv/day07-lab/public/file2.txt ls -l /srv/day07-lab/public/file2.txt rm /srv/day07-lab/public/file2.txt # 应提示不允许操作 ``` **yangge 管理终端:** ```bash rm /srv/day07-lab/public/file2.txt # 文件 Owner 可以删除 ``` > **Sticky Bit 不会取消公共目录的写权限,它只把删除和改名限制在文件 Owner、目录 Owner 或 root。** --- ## 五、若依最小权限与故障处理 **为若依配置最小运行权限,并模拟一次日志写入故障。** > **若依账号可以读取程序和配置、写入日志,但不能修改发布程序。** ### 5.1 先设计,再授权 | 对象 | 若依需要的能力 | 权限设计 | |------|--------------|---------| | 发布目录 | 进入目录并读取程序 | root:ruoyi 0750 | | JAR 文件 | 被 Java 读取 | root:ruoyi 0640 | | 共享配置目录 | 进入目录并读取配置 | root:ruoyi 0750 | | 配置文件 | 读取配置内容 | root:ruoyi 0640 | | 日志目录 | 创建并追加日志 | ruoyi:ruoyi 0750 | | Other | 没有业务需求 | 不授权 | > **最小权限并非权限越少越好,而是「刚好满足业务,并且没有多余授权」。** ### 5.2 创建服务账号和目录 **服务账号不需要交互登录,也不设置可用密码:** ```bash getent group ruoyi >/dev/null || sudo groupadd --system ruoyi getent passwd ruoyi >/dev/null || sudo useradd -r -M -g ruoyi -d /srv/ruoyi -s /usr/sbin/nologin ruoyi getent passwd ruoyi id ruoyi ``` **建立程序、配置和日志目录:** ```bash sudo mkdir -p \ /srv/ruoyi/releases \ /srv/ruoyi/shared \ /var/log/ruoyi sudo chown root:ruoyi \ /srv/ruoyi \ /srv/ruoyi/releases \ /srv/ruoyi/shared sudo chmod 0750 \ /srv/ruoyi \ /srv/ruoyi/releases \ /srv/ruoyi/shared sudo chown ruoyi:ruoyi /var/log/ruoyi sudo chmod 0750 /var/log/ruoyi ``` **创建权限实验占位文件:** ```bash echo 'RuoYi application placeholder' | sudo tee /srv/ruoyi/releases/ruoyi-app.jar >/dev/null echo 'server:' | sudo tee /srv/ruoyi/shared/application.yml >/dev/null echo ' port: 8080' | sudo tee -a /srv/ruoyi/shared/application.yml >/dev/null sudo chown root:ruoyi \ /srv/ruoyi/releases/ruoyi-app.jar \ /srv/ruoyi/shared/application.yml sudo chmod 0640 \ /srv/ruoyi/releases/ruoyi-app.jar \ /srv/ruoyi/shared/application.yml ``` > 💡 这里的 JAR 是普通占位文件,不是可运行程序。**`java -jar` 读取 JAR 内容,不要求 JAR 文件自身具有 x 权限。** ### 5.3 使用服务身份检查 ruoyi 使用 nologin,**不能执行 `su - ruoyi`**。新开验证终端: ```bash sudo -u ruoyi -s whoami id cat /srv/ruoyi/releases/ruoyi-app.jar cat /srv/ruoyi/shared/application.yml mkdir /var/log/ruoyi/runtime touch /var/log/ruoyi/runtime/startup.ok echo "startup permission ok" >> /var/log/ruoyi/application.log ls -l /var/log/ruoyi /var/log/ruoyi/runtime echo "tamper" >> /srv/ruoyi/releases/ruoyi-app.jar # 应提示 Permission denied ``` **yangge 管理终端:** ```bash stat -c '%A %a %U:%G %n' \ /srv/ruoyi \ /srv/ruoyi/releases \ /srv/ruoyi/releases/ruoyi-app.jar \ /srv/ruoyi/shared \ /srv/ruoyi/shared/application.yml \ /var/log/ruoyi \ /var/log/ruoyi/application.log ``` > **读取和写日志应成功;修改程序应提示 Permission denied。** ### 5.4 故障演练:应用无法写日志 **ruoyi 验证终端:** ```bash touch /var/log/ruoyi/before-fault.log ls -l /var/log/ruoyi/before-fault.log ``` **yangge 管理终端模拟故障:** ```bash sudo rm -f /var/log/ruoyi/fault.log sudo chmod 0550 /var/log/ruoyi stat -c '%A %a %U:%G %n' /var/log/ruoyi ``` **ruoyi 验证终端:** ```bash echo "new line" > /var/log/ruoyi/fault.log # Permission denied ``` > ⚠️ **不要执行 777。** **回到管理终端收集证据:** ```bash id ruoyi namei -l /var/log/ruoyi stat -c '%A %a %U:%G %n' /var/log/ruoyi ``` **恢复最小权限:** ```bash sudo chmod 0750 /var/log/ruoyi ``` **ruoyi 验证终端复测:** ```bash echo "recovered" > /var/log/ruoyi/fault.log cat /var/log/ruoyi/fault.log exit ``` **权限故障检查顺序:** ```text 1. 使用 ps、id 或服务配置确认实际运行身份 2. 使用 namei -l 或 ls -ld 检查路径中的每一级目录 3. 使用 stat 检查类型、Owner、Group 和 rwx 4. 必要时使用 getfacl 检查 ACL 5. 使用应用身份完成最小读写测试和业务复测 ``` ### 5.5 检查危险权限 > ⚠️ **`chmod 777` 会允许所有本机用户读、写并进入目录,既扩大修改和删除风险,也会掩盖真实故障原因。** **find -perm 有三种匹配方式:** | 写法 | 匹配方式 | 说明 | |------|---------|------| | `-perm 0755` | 精确匹配 | 权限必须正好是 0755 | | `-perm -0755` | 全部包含 | 0755 中列出的权限必须全部存在,允许有额外权限 | | `-perm /0755` | 任意命中 | 0755 中任意一个权限位存在就会命中 | **建立四个权限不同的测试文件:** ```bash sudo mkdir -p /srv/day07-lab/find-perm sudo touch \ /srv/day07-lab/find-perm/exact-0755 \ /srv/day07-lab/find-perm/extra-0775 \ /srv/day07-lab/find-perm/normal-0644 \ /srv/day07-lab/find-perm/none-0000 sudo chmod 0755 /srv/day07-lab/find-perm/exact-0755 sudo chmod 0775 /srv/day07-lab/find-perm/extra-0775 sudo chmod 0644 /srv/day07-lab/find-perm/normal-0644 sudo chmod 0000 /srv/day07-lab/find-perm/none-0000 find /srv/day07-lab/find-perm -maxdepth 1 -type f -perm 0755 -exec ls -ld {} + find /srv/day07-lab/find-perm -maxdepth 1 -type f -perm -0755 -exec ls -ld {} + find /srv/day07-lab/find-perm -maxdepth 1 -type f -perm /0755 -exec ls -ld {} + ``` > 第一条只显示 exact-0755;第二条增加 extra-0775;第三条还会命中 normal-0644。 > **`-perm /0755` 不是「查找 0755」,而是「任意权限位匹配」。** **风险检查使用任意命中方式:** ```bash find /srv/ruoyi /var/log/ruoyi -perm /0002 -exec ls -ld {} + find /srv/ruoyi /var/log/ruoyi -perm /6000 -exec ls -ld {} + ``` | 条件 | 本节含义 | |------|---------| | `-perm /0002` | 对象具有 Other 写权限 | | `-perm /6000` | 命中 SUID 或 SGID 中的任意一项 | > **正常设计中不应出现对 Other 可写的对象,也不应出现 SUID 或 SGID 可执行文件。** > 发现风险项后要先确认用途,再按最小权限整改。 --- ## 六、检查结果与回顾 ### 6.1 若依权限检查表 ```text 主机名:cc-vm 执行用户:cc 服务账号:ruoyi 服务账号 UID/GID: 登录 Shell: 程序目录权限: 程序文件权限: 配置目录权限: 配置文件权限: 日志目录权限: 读取程序验证: 读取配置验证: 写入日志验证: 修改程序验证: 故障原因: 恢复与复测证据: ``` ### 6.2 复盘问题 1. 主组和附加组有什么区别? 2. 文件与目录的 rwx 分别控制什么? 3. 文件是 640 时,为什么仍可能无法读取? 4. SUID、SGID 和 Sticky Bit 分别改变什么规则? 5. 为什么若依日志目录不能设置为 777? 6. 遇到 Permission denied 时,应该按什么顺序检查? > Day 08 将在当前 ruoyi 服务身份基础上**安装并检查应用运行环境**。保留虚拟机、目录权限与故障记录。 --- ## 七、附录:进阶内容【拓展】 ### 7.1 ACL 识别与检查 **ACL 可以为指定用户或组增加更细的授权。`ls -l` 权限串末尾出现 `+` 时,说明对象可能存在扩展 ACL。** ```bash ls -ld /srv/day07-lab/dir-lab command -v getfacl getfacl /srv/day07-lab/dir-lab ``` > ACL 中的 mask 可能限制所属组、命名用户和命名组的有效权限。**这里先会识别和检查,ACL 配置留到后面的权限专题。** ### 7.2 使用圆括号临时改变环境 **圆括号中的命令会在一个子 Shell 中运行。子 Shell 结束后,其中修改的 umask 不会影响当前 Shell。** ```bash mkdir -p ~/cc/CCvm/day07/umask-lab umask ( umask 0027 touch ~/cc/CCvm/day07/umask-lab/tianyun.txt umask ) umask stat -c '%A %a %n' ~/cc/CCvm/day07/umask-lab/tianyun.txt ``` > 括号内应显示 0027,括号结束后的 umask 应恢复为实验前的值。**tianyun.txt 的权限应为 640。** ### 7.3 /etc/shadow 完整字段 `/etc/shadow` 每行使用冒号分隔九个字段: | 字段 | 含义 | |------|------| | 1 | 用户名 | | 2 | 密码哈希或锁定标记 | | 3 | 最近修改密码的日期 | | 4 | 两次修改密码之间的最少天数 | | 5 | 密码最长有效天数 | | 6 | 密码到期前的警告天数 | | 7 | 密码到期后的宽限天数 | | 8 | 账号到期日期 | | 9 | 保留字段 | > 日期字段以 1970-01-01 之后的天数记录,空字段表示没有单独设置。 --- ## 八、写在最后 今天最大的三点收获: 1. **权限排障的第一步不是 chmod,而是"我是谁"。** 用 `ps`、`id` 或服务配置确认实际运行身份,再用 `namei -l` 逐级检查路径权限。**只修复缺的那一项,不要整片重设。** 2. **`chmod 777` 是最常见的错误操作。** 它不仅扩大攻击面,还会掩盖真实的故障原因。**正确做法是确认缺失权限,精确补齐。** 3. **最小权限原则不是"权限越少越好",而是"刚好满足业务,没有多余授权"。** 若依的服务账号不能登录、不能改程序、只能写日志,这才是好设计。 明天继续**在 ruoyi 服务身份基础上安装并检查应用运行环境**。 **如果这篇对你有帮助,点个赞让我知道,我会每天更新。有问题评论区见,一起从小白变熟手。** --- *本文为个人学习笔记,命令均在 Ubuntu 26.04.1 Desktop + VMware Workstation 25H2 环境实测。不同版本界面可能略有差异,按选项含义操作即可。*