Webshell qua File Upload và PHP Execution trong WordPress

Webshell qua file upload và PHP execution trong WordPress

Một chức năng upload tưởng chỉ dùng cho ảnh hoặc tài liệu có thể trở thành đường đưa webshell vào server nếu application chấp nhận file nguy hiểm và web server/PHP vẫn thực thi code trong thư mục lưu upload. Đây là lỗi ở ranh giới giữa input validation, storage location và execution policy.

OWASP mô tả unrestricted file upload là rủi ro nghiêm trọng vì attacker có thể đưa code lên server rồi tìm cách kích hoạt code đó. Web Security Testing Guide nêu rõ webshell có thể dẫn tới command execution nếu file được đặt trong webroot và server được cấu hình để thực thi nó. OWASP File Upload Cheat Sheet khuyến nghị allowlist extension, không tin Content-Type từ client, đổi filename và ưu tiên lưu ngoài webroot. Nguồn: OWASP — Unrestricted File Upload, OWASP WSTG — Upload of Malicious Files và OWASP File Upload Cheat Sheet.

Bối cảnh: upload hợp lệ nhưng execution boundary bị sai

Giả sử một WordPress site có plugin cho phép upload file từ frontend. Business requirement chỉ cần ảnh và PDF, nhưng validation dựa chủ yếu vào extension hoặc MIME header do client gửi. File sau upload được lưu trực tiếp dưới webroot, trong một thư mục mà PHP handler vẫn có thể xử lý script.

Khi attacker vượt qua validation và đưa được một file PHP hoặc payload tương đương vào vùng đó, việc truy cập trực tiếp URL của file có thể biến upload flaw thành server-side code execution.

Những tín hiệu cần điều tra ngay

  • File script xuất hiện trong wp-content/uploads hoặc thư mục upload tùy biến.
  • Access log có request trực tiếp tới file upload đáng ngờ.
  • Process/webserver log cho thấy PHP handler xử lý file trong upload path.
  • File có extension kép, tên bất thường hoặc content không khớp loại file.
  • Upload endpoint cho phép anonymous hoặc low-privilege user sử dụng.
  • Upload directory vừa writable vừa executable.

Investigation: chứng minh upload path có dẫn tới code execution

Bước 1: xác định file đi vào hệ thống bằng đường nào

Cần map file đáng ngờ về upload endpoint, user/session, timestamp, request source và plugin/module xử lý upload. Không nên kết luận “plugin bị exploit” chỉ vì file nằm trong uploads; file cũng có thể đến từ compromised admin, SFTP, control panel hoặc một entry point khác.

OWASP lưu ý extension denylist riêng lẻ là biện pháp yếu vì có thể bị bypass bằng extension khác, double extension hoặc server parsing behavior. Do đó điều tra phải xem cả application validation lẫn web-server execution mapping.

Bước 2: xác minh server có thực thi file trong upload path không

Đây là điều kiện quyết định biến malicious upload thành webshell. Cần kiểm tra Apache/Nginx/FastCGI/PHP mapping, per-directory config, .htaccess, location block và handler rule. Nếu file PHP trong uploads được trả như static text/download thì impact khác hoàn toàn so với việc được gửi qua PHP-FPM để thực thi.

OWASP WSTG nêu rõ webshell attack cần file được upload vào vùng có thể truy cập và server được cấu hình để execute code đó. Vì vậy finding phải tách rõ “malicious file accepted” với “server-side execution confirmed”.

Bước 3: xác định webshell đã làm gì sau execution

Nếu access log hoặc runtime evidence xác nhận webshell đã được gọi, cần mở rộng scope sang command execution, file creation, credential access, database activity, outbound connection và persistence. Webshell chỉ là foothold; incident scope phụ thuộc hành vi sau đó.

Tham chiếu thêm case phát hiện backdoor bằng File Integrity Monitoring và case plugin WordPress có lỗ hổng dẫn tới compromise để tách entry point, persistence và impact.

Khi nào có thể xác nhận root cause là upload + PHP execution?

Không nên gọi mọi file PHP trong uploads là bằng chứng đủ của một upload exploit. Root cause mạnh khi nhiều lớp evidence khớp nhau.

  • Upload request tương ứng với thời điểm file xuất hiện.
  • Endpoint chấp nhận file ngoài business requirement hoặc validation bị bypass.
  • File nằm trong web-accessible path.
  • PHP/webserver thực sự execute file đó.
  • Log hoặc forensic evidence cho thấy command/action sau execution.

Remediation: tách upload storage khỏi execution

Sửa upload validation theo allowlist và content

  • Chỉ cho phép file type thật sự cần cho business.
  • Không tin Content-Type do client gửi.
  • Kiểm tra extension, signature/content và normalize filename.
  • Đổi tên file bằng giá trị do application sinh ra.
  • Giới hạn size, quyền upload và tần suất request.

OWASP khuyến nghị allowlist thay vì chỉ block extension nguy hiểm, đồng thời lưu file ngoài webroot nếu có thể. Với file public, application nên làm lớp mapping/serving thay vì để user quyết định path trực tiếp. Checklist triển khai thực tế có tại cách giới hạn upload file để giảm nguy cơ webshell và mã độc.

Chặn execution trong thư mục upload

Nếu bắt buộc lưu trong webroot, upload directory nên chỉ có quyền cần thiết cho storage và không được gắn script handler. OWASP khuyến nghị upload directory không có execute permission và loại bỏ script handlers. WordPress Hardening cũng nhấn mạnh wp-content là vùng writable nên permission phải theo least privilege, còn plugin/theme code không nên writable rộng hơn mức cần thiết.

Cấu hình cụ thể phụ thuộc Apache/Nginx/PHP-FPM và hosting stack; remediation phải kiểm tra read-back rằng request tới file script trong upload path không còn được thực thi.

Containment và cleanup nếu webshell đã được thực thi

Nếu có evidence code execution, chỉ xóa file webshell là chưa đủ. Cần coi đây là security incident và kiểm tra persistence, credential compromise và lateral actions.

  • Chặn hoặc cô lập upload endpoint bị khai thác.
  • Preserve log và artifact cần cho timeline trước cleanup.
  • Xóa/quarantine webshell sau khi evidence đã được lưu.
  • Review file changes, scheduled tasks, accounts và database persistence.
  • Rotate credential/token nếu webshell có thể đọc được secrets.
  • Patch hoặc disable component tạo upload flaw trước khi mở lại traffic.

Validation sau remediation

Kiểm traKết quả mong đợi
Allowed file typesChỉ còn loại file cần thiết cho business
Content validationKhông phụ thuộc MIME header từ client
Upload storageNgoài webroot hoặc execution disabled
Direct script requestKhông được PHP/webserver execute
PermissionsUpload path theo least privilege
IOC/persistence reviewKhông còn artifact trái phép đã biết
Regression testUpload hợp lệ của người dùng vẫn hoạt động

Bài học vận hành

  • File upload và code execution là hai control khác nhau; phá cả hai mới tạo webshell path hoàn chỉnh.
  • Denylist extension không đủ để bảo vệ upload feature.
  • Upload storage nên tách khỏi executable webroot khi có thể.
  • Không nên dùng client-supplied Content-Type như security boundary.
  • Xóa webshell không đồng nghĩa incident đã được eradicated.
  • Validation cuối phải kiểm tra cả security control lẫn business upload flow.

Nguồn tham khảo

◇
Cần hỗ trợ kiểm tra và xử lý website?Đội ngũ SecureWebOps sẵn sàng hỗ trợ theo phạm vi phù hợp.
Liên hệ ngay →
Đoàn Trình Dục
Về tác giả Đoàn Trình Dục TD Digital · Website Operations & Security

Đoàn Trình Dục là tác giả nội dung trên SecureWebOps. Các bài viết tập trung vào bảo mật WordPress, giám sát an ninh website, malware/backdoor, hardening, backup/recovery và Incident Response theo hướng thực hành, có bước kiểm tra, bằng chứng, validation và rollback khi phù hợp.

Xem hồ sơ tác giả →