File Permission & Ownership trên Web Server là bài toán về filesystem access: object/path nào được user, group hoặc process đọc, ghi, traverse hay execute. Bài này không sở hữu việc thiết kế sudo/root privilege; nếu cần trả lời “identity nào có thể nâng quyền?”, xem Root, sudo & Least Privilege.
Mục tiêu không phải áp một bộ số chmod cố định cho mọi server. Một application an toàn cần owner/group đúng, writable path đúng và permission phản ánh workload thật. Vì vậy owner task ở đây là path → purpose → owner/group → mode/ACL → writable by → validation.
Permission model và ownership fundamentals
1. Đọc permission đúng cách
ls -ld /var/www/example
ls -l /var/www/example
stat /var/www/example
Permission cơ bản được chia cho owner, group và other:
| Bit | File | Directory |
|---|---|---|
| r | Đọc nội dung | Đọc tên entry khi điều kiện phù hợp |
| w | Sửa nội dung | Tạo/xóa/đổi tên entry |
| x | Thực thi file | Traverse directory |
Directory permission rất quan trọng: user có thể không sửa file trực tiếp nhưng vẫn replace/xóa file nếu có quyền ghi trên parent directory.
2. Numeric mode không phải security policy cố định
Read=4, write=2, execute=1. Ví dụ phổ biến:
644: owner read/write, group/other read.755: owner read/write/execute, group/other read/execute.600: chỉ owner read/write.700: chỉ owner có full access.
Những mode này chỉ là notation. Config có secret có thể cần chặt hơn; shared runtime path có thể cần group write; executable bit chỉ nên tồn tại khi file cần thực thi.
3. Vì sao chmod 777 thường là dấu hiệu xấu?
777 mở read/write/execute cho owner, group và other. Trên web server, world-writable source/config làm tăng nguy cơ process hoặc local account không liên quan sửa code hoặc tạo persistence.
Không dùng chmod -R 777 để chữa lỗi upload/cache. Hãy tìm đúng nguyên nhân: sai owner/group, runtime cần ghi một path cụ thể, ACL/umask sai hoặc deployment đang dùng identity không phù hợp.
4. Ownership phải đọc cùng permission
chmod 640 config.php chưa đủ nếu owner/group sai. Kiểm tra:
stat /path/to/file
ls -ln /path/to/file
chown thay owner/group:
sudo chown deploy:web /var/www/example/config.php
GNU Coreutils hiện tài liệu hóa rõ recursive traversal và symbolic-link behavior của chown -R; vì vậy không chạy recursive ownership change trên production nếu chưa hiểu symlink, mount và generated files.
Thiết kế writable paths và inheritance
5. Tách source tree khỏi writable runtime paths
Filesystem owner chính của bài này không phải “deploy user có sudo gì”, mà là path nào ai được ghi. Một model thường gặp:
| Path | Filesystem intent | Writable by |
|---|---|---|
| Application source | Code/release | Deploy process; runtime thường chỉ đọc |
| Uploads | User-generated content | Runtime/app group |
| Cache/session | Runtime data | Runtime |
| Config/secret | Application configuration | Minimal writers; runtime read khi cần |
| Logs | Operational evidence | Service/logging path |
Framework khác nhau có writable paths khác nhau; không đoán chỉ từ tên directory.
6. Symbolic chmod giúp thay đổi có chủ đích
chmod g+w storage
chmod o-rwx secret.env
chmod u+x deploy.sh
Symbolic notation có thể dễ review hơn khi chỉ muốn thay một nhóm bit. Sau thay đổi vẫn phải read-back bằng stat hoặc ls -l.
7. umask ảnh hưởng file mới tạo
umask loại bỏ permission khỏi mode mặc định khi process tạo file/directory:
umask
systemctl show your-service -p UMask
Nếu application liên tục tạo file “sai permission”, tìm source tạo file và umask/default mode thay vì chạy cron chmod sửa hậu quả.
8. setgid directory và group inheritance
Với shared directory, setgid có thể giúp file/directory con kế thừa group của parent:
chmod g+s /path/to/shared-dir
GNU Coreutils mô tả set-group-ID trên directory là cơ chế để file mới kế thừa group theo filesystem behavior phổ biến. Nhưng group membership và write scope vẫn phải được review riêng.
9. ACL dùng khi owner/group/other không đủ biểu đạt
POSIX ACL hữu ích khi nhiều identity cần access khác nhau:
getfacl /path/to/file
getfacl /path/to/directory
Nếu dùng ACL, đội vận hành không nên chỉ nhìn ls -l. Backup/deploy/restore tooling cũng phải giữ ACL đúng.
Audit, recursive changes và validation
10. Symlink và recursive chmod/chown
Recursive change có thể:
- Đụng upload/cache không intended.
- Đi qua symlink/mount tùy command/options.
- Phá executable bit cần thiết.
- Thay owner của generated files ngoài release model.
Trước mass change, inventory phạm vi và snapshot current state. Không dùng recursive command để “sửa toàn bộ” khi chưa có rollback.
11. Tìm world-writable paths
find /var/www -xdev -type f -perm -0002 -print
find /var/www -xdev -type d -perm -0002 -print
Kết quả cần context. Runtime directory có thể intentionally writable, nhưng world-writable source/config thường cần ưu tiên review. Không auto-chmod toàn bộ output.
12. Tìm orphan owner/group
find /var/www/example -xdev \( -nouser -o -nogroup \) -print
Orphan UID/GID có thể xuất hiện sau migration, restore hoặc account removal. Đây là signal cần gắn owner trước khi sửa.
13. Permission và secret
Environment file, private key, backup config và credential cần access tối thiểu. Nhưng permission không thay secret lifecycle. Secret nằm trong public web root vẫn có thể bị lộ nếu web server phục vụ file đó.
Rotation/revocation secret thuộc Server Secrets Management.
14. Permission và upload path
Upload directory thường cần runtime write, nhưng không nên mặc định executable hoặc được web server parse như code. File permission chỉ là một lớp; application validation và web-server serving policy vẫn cần riêng.
15. Snapshot trước mass permission change
find /var/www/example -xdev -printf '%m %u %g %p\n' > permission-before.txt
Snapshot này là evidence before-state, không phải lệnh restore tự động. File tree có thể thay đổi sau snapshot nên rollback cần review.
16. Validation sau chmod/chown
- Read-back owner/group/mode hoặc ACL.
- Test deploy.
- Test web request.
- Test upload/cache/session nếu relevant.
- Kiểm tra process user.
- Review application error log.
- Xác nhận source/config ngoài unintended writable paths.
HTTP 200 không đủ nếu upload, cron, queue hoặc deploy đã hỏng.
Filesystem Access Matrix
Artifact này chỉ ghi filesystem state; privilege escalation ở identity level thuộc bài 332.
| Path | Purpose | Owner | Group | Mode/ACL | Writable by | Expected |
|---|---|---|---|---|---|---|
| Source tree | Application code | Deploy | Read group | Observed | Deploy only | Runtime read-only |
| Uploads | User content | Runtime/shared | App group | Observed | Runtime | No code execution |
| Config secret | Config/credential | Restricted owner | Restricted group | Observed | Minimal writers | Not public |
Checklist File Permission & Ownership
- Map path → purpose.
- Read owner/group/mode.
- Review parent-directory permission.
- Không dùng 777 như fix mặc định.
- Source tree không writable bởi runtime nếu không cần.
- Writable runtime paths được giới hạn.
- Review umask.
- Review setgid/ACL nếu dùng.
- Review world-writable paths.
- Review orphan UID/GID.
- Cẩn trọng symlink/recursive change.
- Snapshot trước mass change.
- Read-back sau write.
- Functional test deploy/runtime/upload/cache.
Nguồn kỹ thuật tham khảo
- GNU Coreutils — file permissions, chmod, chown
- Ubuntu Manpages — chown
- Ubuntu Server — users, groups and permissions
Kết luận
Owner của bài này là filesystem access: WHICH path/object can be READ, WRITE, EXECUTE or TRAVERSED by which owner/group/process.
Root/sudo privilege paths thuộc 332; SSH authentication thuộc 331. Tách owner như vậy giúp File Permission tập trung đúng vào chmod/chown/umask/ACL và writable paths thay vì lặp lại toàn bộ least-privilege model.
