Website có thể bị compromise khi PHP-FPM chạy với quyền quá rộng và các thư mục quan trọng của WordPress bị cấp quyền ghi không cần thiết. Khi một request hoặc plugin vulnerability cho phép attacker ghi file vào vùng mà PHP có thể thực thi, sai lệch giữa ownership, write permission và execution boundary có thể biến một lỗi ứng dụng thành khả năng chạy mã trên server.
WordPress khuyến nghị core và plugin files chỉ nên writable bởi owner cần thiết, tránh world-writable permissions; PHP-FPM cũng cảnh báo rằng FastCGI endpoint bị expose có thể dẫn tới arbitrary code execution và nên được giới hạn bằng Unix socket hoặc danh sách client hợp lệ. Nguồn: WordPress Hardening và PHP Manual — FPM configuration.
Bối cảnh và dấu hiệu ban đầu
Giả sử một WordPress site chạy Nginx + PHP-FPM. Để “sửa lỗi upload”, một số thư mục từng được chmod quá rộng hoặc ownership bị đổi để web server user có thể ghi nhiều nơi hơn cần thiết. Sau đó xuất hiện file PHP mới trong theme/plugin hoặc một file cấu hình bị sửa ngoài maintenance window.
Điểm quan trọng là permission rộng tự nó chưa chứng minh compromise. Phải xác minh attacker thực sự có write path, file nào đã bị tạo/sửa, PHP-FPM có quyền đọc/thực thi file đó không và request/process nào dẫn tới thay đổi.
Những tín hiệu đáng chú ý
- Core/plugin/theme files writable bởi web server user dù không có nhu cầu vận hành.
- Directory hoặc file có mode quá rộng như group/world-writable ngoài change window.
- PHP file mới xuất hiện trong vùng upload/cache/tmp hoặc plugin/theme.
- Ownership thay đổi hàng loạt sau deploy hoặc thao tác control panel.
- PHP-FPM pool dùng chung user cho nhiều site không liên quan.
- FastCGI TCP socket mở rộng hoặc không giới hạn client phù hợp.
Investigation: tìm write path và execution boundary

Bước 1: kiểm tra ownership và permission thực tế
Đầu tiên cần kiểm kê owner, group và mode của WordPress root, wp-admin, wp-includes, wp-content/plugins, wp-content/themes, uploads và các thư mục cache/tmp. WordPress nêu rõ rằng root, admin, includes và plugin files nhìn chung chỉ nên writable bởi user account cần thiết; chỉ các vùng thật sự cần runtime write mới nên cấp quyền tương ứng.
Không nên áp một bộ chmod cố định cho mọi hosting. Mục tiêu là xác định process nào cần read/write ở đâu, rồi cấp quyền tối thiểu cho đúng owner/group thay vì dùng 777 hoặc recursive write rộng.
Bước 2: kiểm tra PHP-FPM pool và FastCGI exposure
PHP-FPM cho phép mỗi pool chạy bằng user/group riêng. Nếu nhiều site dùng chung một account hoặc cùng quyền ghi vào nhau, blast radius tăng đáng kể. Khi dùng Unix socket, listen.owner, listen.group và listen.mode kiểm soát quyền kết nối; khi dùng TCP socket, listen.allowed_clients cần giới hạn client hợp lệ.
PHP Manual cảnh báo trực tiếp rằng FastCGI endpoint bị expose có thể cho phép arbitrary code execution. Vì vậy cần xác minh socket/port có đang public, container có publish cổng FPM ra host hay không và web server có phải client duy nhất cần truy cập endpoint này không.
Bước 3: correlate file change với request và process
Nếu có file lạ, cần dựng timeline từ access log, PHP-FPM log, web server error log, file mtime/ctime, deployment history và process audit. Mục tiêu là xác định file được ghi bởi request path nào, user/process nào và sau đó có được thực thi hay không.
Tham khảo PHP-FPM Security, Server Audit Logging và Root Cause Analysis sau Security Incident để dựng chuỗi request → process → file change → execution.
Khi nào có thể xác nhận permission/PHP-FPM là nguyên nhân?
Không nên kết luận “bị hack vì chmod sai” chỉ vì thấy file writable. Cần chứng minh được write capability và execution path thực tế.
- Web/PHP process có quyền ghi vào vị trí không cần thiết.
- File độc hại hoặc trái phép được tạo/sửa trong chính vùng đó.
- Log/timeline cho thấy request hoặc process PHP-FPM liên quan đến thay đổi.
- File được web server/PHP thực thi hoặc tạo persistence/impact rõ ràng.
- Sau khi sửa ownership/permission và cô lập FPM pool, cùng attack path không còn tái hiện.
Remediation: thu hẹp write access và tách execution boundary
Containment khi đã có dấu hiệu compromise
- Bảo toàn file/log cần thiết trước khi cleanup.
- Remove hoặc isolate file độc hại sau khi xác minh impact.
- Revoke credential/session liên quan nếu có account compromise.
- Khóa write access không cần thiết khỏi web server/PHP user.
- Tạm chặn đường request đã dẫn tới file write nếu vẫn còn exploit path.
Không chỉ chmod file độc hại rồi coi incident đã kết thúc. Nếu entry point là plugin vulnerability, upload abuse hoặc exposed FastCGI, cần xử lý nguyên nhân gốc và hunt persistence còn lại.
Hardening ownership, permission và PHP-FPM
- Giữ core/plugin/theme files read-only đối với web server trừ khi thực sự cần runtime write.
- Chỉ cấp write cho uploads/cache/tmp hoặc path cụ thể theo nhu cầu.
- Tránh 777 và recursive write rộng để “sửa lỗi permission”.
- Dùng pool user/group riêng cho từng site hoặc trust boundary khi kiến trúc cho phép.
- Ưu tiên Unix socket cho PHP-FPM trên cùng host; nếu dùng TCP, giới hạn
listen.allowed_clients. - Giữ
security.limit_extensionsphù hợp để giảm rủi ro thực thi nhầm file extension.
WordPress khuyến nghị tránh world-writable directories và chỉ mở quyền tại đúng path cần thiết; PHP-FPM hỗ trợ isolation theo pool và socket access control. Xem thêm Server Security Baseline và Nginx Security Hardening.
Validation sau remediation
| Kiểm tra | Kết quả mong đợi |
|---|---|
| Core/plugin/theme ownership | Chỉ owner hợp lệ có quyền ghi |
| Uploads/cache/tmp | Chỉ path cần thiết writable |
| World-writable paths | Không còn nếu không có lý do hợp lệ |
| PHP-FPM pool | User/group và trust boundary đúng thiết kế |
| FPM socket/port | Không public ngoài client được phép |
| Unexpected PHP files | Không còn file lạ trong vùng writable |
| Functional test | Upload, update, cache và site flow hợp lệ vẫn PASS |
Bài học vận hành và bước tiếp theo
- Writable không đồng nghĩa vulnerable, nhưng write + execute cùng trust boundary làm tăng impact đáng kể.
- Permission phải theo nhu cầu process, không theo thói quen chmod rộng.
- PHP-FPM pool isolation giúp giảm blast radius giữa site/service.
- FastCGI không nên exposed ra network rộng hơn cần thiết.
- Cleanup file phải đi cùng xác minh entry point và persistence.
- Permission changes cần change control và post-change validation vì siết sai cũng có thể làm site lỗi.
