- systemd cung cấp khả năng quản lý dịch vụ mạnh mẽ, nhưng cấu hình mặc định được tối ưu cho tính tiện dụng hơn là bảo mật, nên cần áp dụng thêm các tùy chọn hardening riêng
- Có thể dùng lệnh
systemd-analyze security để phân tích chỉ số mức độ phơi lộ bảo mật của toàn bộ dịch vụ hoặc một dịch vụ cụ thể, từ đó xác định thứ tự ưu tiên
- Có nhiều tùy chọn bảo mật có thể áp dụng ở cấp độ đơn vị dịch vụ, và có thể chỉnh riêng qua
/etc/systemd/system/ServiceName.service.d/override.conf
- Các tùy chọn chính gồm
ProtectSystem, PrivateTmp, NoNewPrivileges, SystemCallFilter, MemoryDenyWriteExecute... nhằm giới hạn quyền tiến trình và truy cập tài nguyên
- Thay vì nhắm tới bảo mật tuyệt đối, nên ưu tiên hardening cho các dịch vụ công khai ra bên ngoài để giảm rủi ro; cách này cũng rất hiệu quả trong môi trường self-hosting
Tổng quan về systemd
- systemd cung cấp một phương thức quản lý dịch vụ rất hoàn thiện và vững chắc
- Tuy nhiên, vì ưu tiên khả năng dùng ngay hơn là bảo mật nên cấu hình mặc định khá nới lỏng
- Tài liệu này giới thiệu nhiều tùy chọn tăng cường bảo mật có thể áp dụng cho unit dịch vụ systemd và podman quadlet nhằm giảm khả năng bị xâm phạm, đồng thời thu hẹp phạm vi thiệt hại nếu sự cố xảy ra
- Đây không phải hướng dẫn áp dụng đồng loạt cho mọi dịch vụ; cần thử nghiệm riêng, kiểm tra log và điều chỉnh theo đặc tính cũng như yêu cầu chức năng của từng dịch vụ
- Trách nhiệm bảo mật hạ tầng hoàn toàn thuộc về người vận hành, và tài liệu này chỉ là công cụ tham khảo
Phân tích bảo mật systemd
- Có thể dùng lệnh
systemd-analyze security để kiểm tra trạng thái bảo mật của toàn bộ dịch vụ hoặc phân tích cấu hình chi tiết của một dịch vụ cụ thể (ví dụ: sshd.service)
- Kết quả đầu ra gồm trạng thái kiểm tra, tên tính năng, mô tả và điểm Exposure; Exposure càng cao thì rủi ro càng lớn
- Có thể thêm cấu hình tùy chọn bảo mật vào phần
[Service] (systemd) hoặc [Container] (podman quadlet)
- Khuyến nghị dùng
systemctl edit ServiceName.service để tạo file override; nếu gặp lỗi, cần kiểm tra quyền cần thiết rồi điều chỉnh
Các tùy chọn bảo mật dịch vụ
- systemd cung cấp nhiều từ khóa tùy chọn bảo mật, có thể tra cứu qua
man systemd.exec 5, man capabilities 7...
- Một số tùy chọn bảo mật tiêu biểu
ProtectSystem → tùy chọn giới hạn hệ thống tệp ở chế độ chỉ đọc
ProtectHome → tùy chọn chặn truy cập /home, /root, /run/user
PrivateDevices → tùy chọn chặn truy cập thiết bị vật lý, chỉ cho phép thiết bị ảo như /dev/null
ProtectKernelTunables, ProtectKernelModules, ProtectKernelLogs → tùy chọn chặn truy cập tài nguyên kernel
NoNewPrivileges → tùy chọn ngăn giành thêm đặc quyền mới qua setuid/setgid...
MemoryDenyWriteExecute → chặn việc dùng đồng thời bộ nhớ có thể ghi và thực thi; có thể gây vấn đề với một số ngôn ngữ JIT
SystemCallFilter → tùy chọn giới hạn các system call được phép; khi vi phạm có thể kết thúc tiến trình hoặc trả về EPERM
Giải thích từng tùy chọn
- ProtectSystem: khi đặt
strict, toàn bộ hệ thống tệp được mount chỉ đọc; /dev, /proc, /sys cần thêm tùy chọn bảo vệ riêng
- ReadWritePaths: chỉ cho phép ghi lại trên một số đường dẫn nhất định
- ProtectHome: chặn truy cập
/home, /root, /run/user
- PrivateDevices: vô hiệu hóa truy cập thiết bị vật lý, chỉ cho phép thiết bị pseudo như
/dev/null
- ProtectKernelTunables: đặt
/proc, /sys ở chế độ chỉ đọc
- ProtectControlGroups: chỉ cho phép truy cập cgroup ở chế độ chỉ đọc
- ProtectKernelModules: cấm nạp kernel module một cách tường minh
- ProtectKernelLogs: giới hạn truy cập bộ đệm log kernel
- ProtectProc: khi đặt
invisible, sẽ ẩn các tiến trình thuộc người dùng khác khỏi /proc/
- ProcSubset: chặn nội dung trong
/proc ngoài các mục liên quan tới PID cụ thể
- NoNewPrivileges: chặn leo thang đặc quyền mới qua setuid, setgid, hoặc capability của hệ thống tệp
- ProtectClock: chặn ghi vào đồng hồ hệ thống/phần cứng
- SystemCallArchitectures: khi đặt
native, chỉ cho phép syscall native như x86-64
- RestrictNamespaces: giới hạn namespace chuyên biệt cho container
- RestrictSUIDSGID: chặn thiết lập bit setuid, setgid cho tệp
- LockPersonality: ngăn thay đổi execution domain (chỉ cần cho một số ứng dụng cũ)
- RestrictRealtime: giới hạn lập lịch thời gian thực (chỉ cần cho một số dịch vụ mục đích đặc biệt)
- RestrictAddressFamilies: giới hạn các socket address family được phép (ví dụ: AF_INET, AF_INET6, AF_UNIX...)
- MemoryDenyWriteExecute: chặn việc tạo thêm vùng nhớ vừa ghi vừa thực thi (dịch vụ dùng JIT cần lưu ý)
- ProtectHostname: cấm sử dụng syscall sethostname, setdomainname
- SystemCallFilter: cấu hình cho phép/chặn syscall theo từng dịch vụ, có thể lọc rất chi tiết
- Có thể điều chỉnh theo nhóm, syscall riêng lẻ, cũng như cách thức allow/deny
- Khi vi phạm, cũng hỗ trợ cấu hình trả về mã lỗi như EPERM thay vì kết thúc tiến trình
- Có thể xem toàn bộ danh sách qua
systemd-analyze syscall-filter hoặc man systemd.exec(5)
- Có thể phủ định toàn bộ danh sách bằng tiền tố
~ (ví dụ: CapabilityBoundingSet=~CAP_SETUID...)
Quy trình điều chỉnh giới hạn SystemCallFilter
- Có thể dùng
auditd để kiểm tra trong log syscall nào đã bị chặn khi dịch vụ thất bại
- Chạy
sudo ausearch -i -m SECCOMP -ts recent, rồi kiểm tra giá trị syscall
- Thêm syscall tương ứng hoặc nhóm liên quan vào
SystemCallFilter để xử lý sự cố theo từng bước
Thứ tự ưu tiên áp dụng hardening và mẹo vận hành
- Không cần áp dụng tất cả cho mọi dịch vụ
- Mô hình đe dọa và quản trị rủi ro là cốt lõi; đặc biệt các dịch vụ phơi ra bên ngoài (httpd, nginx, ssh...) cần được cân nhắc bắt buộc
- Các lệnh tùy biến, timer unit (thay thế cron kiểu cũ) cũng rất hiệu quả nếu áp dụng sớm
- Dịch vụ càng ít phức tạp thì khả năng tinh chỉnh chi tiết càng cao
Checklist: tổ hợp tùy chọn bảo mật khuyến nghị (ưu tiên áp dụng ban đầu)
ProtectSystem=strict
PrivateTmp=yes
ProtectHome=yes hoặc ProtectHome=tmpfs
ProtectClock=yes, ProtectKernelLogs=yes, ProtectKernelModules=yes
RestrictSUIDGUID=yes
UMask=0077
LockPersonality=yes
RestrictRealtime=yes
MemoryDenyWriteExecute=yes
DynamicUser=yes hoặc chỉ định User là một người dùng cụ thể không phải root
- Các mục trên nhìn chung là tổ hợp có thể dùng cho dịch vụ mà hầu như không gây ảnh hưởng lớn
- Nếu muốn áp dụng thêm lọc syscall (
SystemCallFilter) thì cần kiểm thử chi tiết
Ví dụ cấu hình Traefik
- Đây là ví dụ chạy dịch vụ Traefik dạng container bằng systemd quadlet và áp dụng nhiều tùy chọn bảo mật
- Áp dụng
ProtectSystem=full, ProtectHome=yes, SystemCallFilter=@system-service @mount @privileged...
- Loại bỏ một số quyền bằng
CapabilityBoundingSet=~CAP_SETUID CAP_SETPCAP
- Áp dụng giới hạn truy cập mạng như
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK
Kết luận
- Các tùy chọn tăng cường bảo mật của systemd là một phương tiện thực dụng đáng có trong hộp công cụ của quản trị viên hệ Unix
- Đây không phải biện pháp bảo mật hoàn hảo mà nên được dùng như công cụ giảm rủi ro; không cần áp dụng cấu hình bảo mật một cách bừa bãi cho mọi dịch vụ
- Đặc biệt với quản trị viên trong môi trường self-hosting, chúng có thể giúp nâng cao mức độ bảo mật rất đáng kể
- Hãy ưu tiên "tính thực dụng hơn sự hoàn hảo" và khuyến nghị áp dụng từng phần trong phạm vi phù hợp với công việc và môi trường
Chưa có bình luận nào.