Cách giới hạn upload file để giảm nguy cơ webshell và mã độc

Hướng dẫn giới hạn file upload theo defense-in-depth: allowlist extension, MIME/signature, đổi tên, storage ngoài webroot, chặn thực thi, quota và scanning.

Giới hạn upload file an toàn để giảm nguy cơ webshell và mã độc

File upload là một trong những đường tấn công nguy hiểm nhất nếu website cho phép người dùng đưa nội dung lên server mà thiếu validation và runtime isolation. Mục tiêu của hardening upload không phải “nhận diện hoàn hảo file xấu”, mà là tạo nhiều lớp độc lập để một lỗi validation không tự động biến thành webshell, malware hosting hoặc code execution.

OWASP khuyến nghị dùng allowlist extension, không tin Content-Type từ client, đổi filename, giới hạn size, kiểm quyền upload, lưu ngoài webroot khi có thể và dùng antivirus/sandbox/CDR phù hợp.

1. Bắt đầu từ business requirement

Chỉ cho phép những định dạng thật sự cần. Nếu website chỉ cần ảnh đại diện thì không có lý do chấp nhận ZIP, SVG, HTML, PHP hay executable formats.

Ví dụ policy:

  • Avatar: JPG, PNG, WebP.
  • Tài liệu tuyển dụng: PDF.
  • Không cho phép archive nếu không có business need.
  • Không cho phép script/executable format qua user upload.

Allowlist dễ kiểm soát hơn blacklist vì blacklist luôn có nguy cơ bỏ sót extension biến thể hoặc parser behavior khác nhau.

2. Validate extension sau khi normalize filename

Không kiểm extension trên raw filename rồi lưu nguyên tên. Trước tiên phải normalize representation và xử lý:

  • double extension;
  • mixed case;
  • trailing dot/space;
  • encoded separator;
  • path traversal;
  • tên file đặc biệt của filesystem.

Thay vì giữ tên do user gửi, nên tạo tên ngẫu nhiên phía server và lưu original filename chỉ như metadata nếu thật sự cần.

3. Không tin Content-Type từ trình duyệt

Content-Type trong multipart upload do client gửi và có thể bị giả mạo. Nó có thể dùng làm signal phụ nhưng không nên là security gate duy nhất. OWASP nói rõ cần kiểm type độc lập với header do client khai báo.

Với PHP, có thể dùng Fileinfo hoặc cơ chế tương đương để suy đoán content type phía server. Tuy nhiên MIME detection cũng chỉ là heuristic, không phải bằng chứng file vô hại.

4. Kiểm file signature/magic bytes như lớp bổ sung

Magic bytes giúp xác nhận file có vẻ phù hợp với format được khai báo. Nhưng không nên dùng riêng lẻ: một file có header hợp lệ vẫn có thể chứa content nguy hiểm hoặc được parser khác diễn giải theo cách không mong muốn.

Phân tích sâu hơn về extension, MIME và magic bytes nằm tại File Upload Security: Extension, MIME và Magic Bytes chứng minh được gì?.

5. Lưu file ngoài webroot khi có thể

Đây là một trong những control có giá trị lớn nhất. Nếu file do user upload không cần được web server truy cập trực tiếp, hãy lưu ngoài document root và phục vụ qua application handler.

Nếu bắt buộc phải lưu trong webroot:

  • tách riêng upload directory;
  • disable script execution ở directory đó;
  • không cho phép handler PHP/CGI/SSI chạy;
  • dùng permission tối thiểu;
  • không để user kiểm soát path thực tế.

Mục tiêu là tạo boundary: kể cả validation sai, payload vẫn không được runtime thực thi như code.

6. Tách ingestion khỏi delivery

Security không dừng ở lúc upload. Khi file được phục vụ lại cho browser, cần kiểm:

  • Content-Type chính xác;
  • Content-Disposition phù hợp;
  • X-Content-Type-Options: nosniff khi cần;
  • không render active content inline nếu không cần;
  • authorization cho file private;
  • không để đoán ID/path dễ dàng nếu file nhạy cảm.

7. Giới hạn kích thước, số lượng và tần suất

Upload security còn liên quan availability. Cần đặt:

  • maximum file size;
  • quota theo user/session;
  • rate limit cho upload endpoint;
  • timeout xử lý;
  • giới hạn decompressed size nếu cho phép archive.

ZIP bomb, decompression bomb hoặc hàng nghìn file nhỏ cũng có thể gây DoS dù không chứa malware.

8. Kiểm quyền trước upload

Không phải ai truy cập endpoint cũng được upload. Kiểm authentication, authorization và CSRF protection theo flow thực tế. Nếu chức năng chỉ dành cho admin/editor, đừng để unauthenticated endpoint nhận file rồi dựa vào validation format.

9. Antivirus, sandbox và CDR

Với PDF, DOCX hoặc file có risk cao, có thể thêm anti-malware, sandbox hoặc Content Disarm & Reconstruct. Nhưng kết quả “clean” không phải zero-risk guarantee; engine có detection scope và thời điểm cập nhật riêng.

10. WordPress cần kiểm cả plugin upload path

WordPress core có upload_mimes và wp_check_filetype_and_ext(), nhưng plugin/theme/custom endpoint có thể tự triển khai upload handler. Audit phải tìm actual code path, không chỉ kiểm Media Library.

Với WordPress production, nên rà soát:

  • plugin nào cho phép upload;
  • role/capability nào được phép;
  • allowed MIME có bị mở rộng không;
  • upload directory có executable không;
  • REST/AJAX endpoint có nonce/capability check không;
  • file được rename và sanitize như thế nào.

Checklist triển khai nhanh

  • Chỉ allowlist format cần thiết.
  • Normalize filename trước extension validation.
  • Không tin client Content-Type.
  • Dùng server-side MIME/signature check như lớp bổ sung.
  • Generate filename phía server.
  • Giới hạn size, quota và rate.
  • Ưu tiên lưu ngoài webroot.
  • Disable execution ở upload directory.
  • Kiểm authentication/authorization/CSRF.
  • Scan/CDR nếu threat model yêu cầu.
  • Kiểm delivery headers và private access.
  • Log upload failures và suspicious patterns.

Ví dụ failure chain cần tránh

Một webshell thành công thường cần nhiều điều kiện nối tiếp: upload endpoint chấp nhận file → filename/type bypass → file nằm trong executable path → attacker biết URL/path → runtime execute file. Mỗi control tốt nên cắt ít nhất một mắt xích trong chain này.

Case Study liên quan: Webshell qua File Upload và PHP Execution trong WordPress.

Kết luận

Giới hạn upload hiệu quả là defense-in-depth, không phải một regex kiểm extension. Control mạnh nhất thường đến từ việc kết hợp allowlist + server-side validation + non-executable storage + controlled delivery + monitoring.

Nếu cần triển khai hardening rộng hơn, xem Website Hardening.

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ả →