Lỗ hổng Copy Fail và cách bảo vệ các container Podman không root
Bài viết phân tích lỗ hổng bảo mật CVE-2026-31431 (Copy Fail) và tác động của nó đối với các container Podman chạy ở chế độ không root (rootless). Chúng ta sẽ cùng xem xét cách khai thác lỗ hổng này và các biện pháp phòng thủ hiệu quả như giới hạn quyền hạn và cấu hình hệ thống tập tin chỉ đọc để giảm thiểu rủi ro.
Vào ngày 29 tháng 4, lỗ hổng bảo mật CVE-2026-31431, được đặt tên là Copy Fail, đã được công khai. Lỗ hổng này cho phép một người dùng cục bộ không có đặc quyền có thể lấy được shell root bằng cách chạy một đoạn mã Python do tác giả cung cấp.
Đây là một vấn đề đáng lo ngại vì các container Linux được sử dụng rộng rãi để chạy mọi thứ từ các dịch vụ công cộng, môi trường phát triển cho đến các tác vụ tích hợp liên tục (CI). Một container bị khai thác bởi Copy Fail có thể trở thành công cụ đắc lực cho nhiều loại tấn công khác nhau.
Tuy nhiên, điều thú vị nhất đối với tôi là cách lỗ hổng này hoạt động trong bối cảnh các container rootless (không có quyền root) của Podman — công cụ mà tôi đã chuyển sang sử dụng từ Docker cách đây một năm vì lý do bảo mật.
Tổng quan về container Rootless
Podman giúp việc chạy container dưới quyền người dùng không có đặc quyền trở nên cực kỳ đơn giản. Khác với Docker, nơi một daemon chạy dưới quyền root quản lý các tiến trình, Podman sử dụng mô hình fork/exec. Điều này có nghĩa là tiến trình container là một tiến trình con trực tiếp của lệnh podman run do người dùng khởi tạo.
Hãy xem xét một ví dụ về việc chạy máy chủ HTTP dưới quyền người dùng bar (UID 1001):
bar@debian:~$ podman run --rm -it --name http-server-1 -d -p 127.0.0.1:8000:8000/tcp localhost/http-server:latest
Khi kiểm tra tiến trình, chúng ta sẽ thấy python3 được sở hữu bởi người dùng bar trên máy chủ, mặc dù bên trong container nó có thể đang chạy dưới quyền root.
User Namespaces và quyền hạn
Podman sử dụng User Namespaces (không gian tên người dùng) cho các container rootless. Điều này cho phép các tiến trình có UID/GID khác nhau bên trong và bên ngoài container. Ví dụ, root bên trong container (UID 0) có thể được ánh xạ tới UID 1001 (người dùng bar) bên ngoài máy chủ.
Ngoài ra, Podman còn sử dụng Linux Capabilities (khả năng của Linux) để cấp các đặc quyền chi tiết cho tiến trình container. Chúng ta có thể loại bỏ (drop) hoặc thêm (add) các khả năng này khi xây dựng hình ảnh hoặc chạy container.
Kiểm tra lỗ hổng Copy Fail trên Podman
Để kiểm tra tác động của Copy Fail, tôi đã sử dụng một container chạy Python HTTP server và tải xuống đoạn mã khai thác (exploit) để xem liệu có thể leo thang đặc quyền hay không.
Rootless Rootful (Root trong container, User thường trên host)
Trong cấu hình này, tiến trình chạy dưới quyền root bên trong container nhưng là người dùng bar trên máy chủ. Khi chạy khai thác Copy Fail, chúng ta có thể lấy được shell root bên trong container. Tuy nhiên, phạm vi ảnh hưởng bị giới hạn bởi những gì người dùng bar có thể làm trên máy chủ.
Rootless Non-Root (User thường trong và ngoài container)
Đây là cấu hình an toàn hơn, nơi tiến trình container chạy dưới quyền một người dùng không có đặc quyền (ví dụ: foo) cả bên trong lẫn bên ngoài container.
Khi chạy khai thác Copy Fail trong cấu hình này, lỗ hổng vẫn hoạt động và cho phép chuyển đổi từ user foo sang root bên trong container. Điều này cho thấy container rootless không miễn nhiễm hoàn toàn với lỗ hổng này.
Các biện pháp giảm thiểu rủi ro
Mặc dù lỗ hổng có thể khai thác được, chúng ta vẫn có thể áp dụng nguyên tắc "phòng thủ theo chiều sâu" (defense in depth) để hạn chế tối đa thiệt hại.
Vô hiệu hóa việc cấp đặc quyền mới
Podman cho phép chạy container với tùy chọn --security-opt=no-new-privileges. Điều này ngăn chặn tiến trình container có được thêm bất kỳ đặc quyền nào so với ban đầu.
Khi áp dụng tùy chọn này và chạy lại khai thác, dù lỗ hổng vẫn thực thi, nhưng nó không thể chuyển đổi thành user root. Tiến trình vẫn nằm dưới quyền user foo mà không có bất kỳ khả năng (capabilities) nào.
Loại bỏ các Capabilities
Chúng ta cũng có thể sử dụng cờ --cap-drop=all để loại bỏ tất cả các quyền hạn của Linux khi khởi động container. Kết hợp với việc chạy dưới quyền user không có đặc quyền, biện pháp này ngăn chặn thành công việc leo thang lên root shell có đầy đủ quyền hạn.
Hệ thống tập tin chỉ đọc (Read-only)
Sử dụng cờ --read-only để gắn hệ thống tập tin root của container ở chế độ chỉ đọc là một cách tốt để ngăn chặn việc ghi dữ liệu độc hại vào hệ thống trong trường hợp bị tấn công. Tuy nhiên, bạn cần lưu ý rằng các thư mục tạm thời như /tmp vẫn có thể ghi được nếu không được cấu hình thêm.
Giới hạn tài nguyên và tệp tin thực thi
Sử dụng cgroups để giới hạn bộ nhớ, CPU và số lượng PID cho container. Ngoài ra, hãy sử dụng các hình ảnh (image) càng gọn nhẹ càng tốt (ví dụ: distroless hoặc Alpine) để giảm bề mặt tấn công, loại bỏ các trình bao (shell) hoặc trình quản lý gói không cần thiết.
Kết luận
Lỗ hổng Copy Fail là một ví dụ điển hình cho thấy tầm quan trọng của việc hiểu rõ cấu hình bảo mật của container. Mặc dù các container rootless của Podman cung cấp khả năng cô lập tốt hơn so với thiết lập mặc định của Docker, chúng không phải là "viên đạn bạc" giải quyết mọi vấn đề bảo mật.
Để bảo vệ hệ thống của bạn:
- Cập nhật kernel: Luôn áp dụng các bản vá bảo mật mới nhất cho kernel Linux.
- Chạy ở mức đặc quyền thấp nhất: Sử dụng user không có đặc quyền bên trong container và loại bỏ các capabilities không cần thiết.
- Áp dụng các biện pháp cứng hóa: Sử dụng
no-new-privileges, hệ thống tập tin chỉ đọc và giới hạn tài nguyên.
Hiểu rõ chi tiết về hình ảnh container, user chạy tiến trình và các quyền hạn cần thiết là chìa khóa để xây dựng một hệ thống container an toàn và vững chắc.
Bài viết liên quan
Phần mềm
Lo ngại về Bun: Liệu sự suy giảm của Claude Code có phải là điềm báo cho tương lai của runtime này?
04 tháng 5, 2026

Phần mềm
Google phát hành Chrome 148, vá 127 lỗ hổng bảo mật bao gồm các lỗi nghiêm trọng
07 tháng 5, 2026

Phần mềm
Tấn công chuỗi cung ứng WordPress: Kẻ tấn công mua 30 plugin trên Flippa và cài cửa sau
06 tháng 5, 2026
