- File Upload Vulnerability là gì?
- RCE (Remote Code Execution) là gì?
- Vì sao File Upload → RCE đặc biệt nguy hiểm?
- Ví dụ lỗi upload file trong WordPress
- 1. Kiểm tra extension quá đơn giản
- 2. Không kiểm tra MIME type
- 3. Upload vào thư mục có thể thực thi
- Cách hacker vượt bypass validation upload
- Cách phòng chống File Upload → RCE trong WordPress
- 1. Luôn sử dụng wp_handle_upload()
- 2. Chỉ cho phép loại file cụ thể
- 3. Không bao giờ cho phép upload file PHP (và “anh em họ” của nó)
- 4. Luôn đổi tên file khi upload
- 5. Upload vào thư mục không thể thực thi
- Cho Apache
- Cho NGINX
- 6. Kiểm tra MIME thật từ file, không phải từ header
- 7. Chặn SVG nếu bạn không thật sự cần
- 8. Không dùng form upload mà không có nonce
- 9. Kiểm tra capability trước khi upload
- 10. Log lại mọi file upload
- Chuỗi tấn công File Upload → RCE phổ biến
- Checklist chống File Upload → RCE
- Kết luận
Trong WordPress, rất nhiều plugin cho phép upload file: form liên hệ, gallery, membership, eCommerce, LMS… và chỉ một lỗi nhỏ ở validation là đủ để hacker phá tan nát hệ thống.
File Upload Vulnerability là gì?
Đây là lỗ hổng xảy ra khi ứng dụng cho phép upload file mà không kiểm tra đúng cách:
- Kiểm tra file không đúng chuẩn
- Chỉ kiểm tra extension nhưng không kiểm tra MIME
- Không giới hạn loại file upload
- Không chặn file PHP/PHTML/PHAR
- Không đổi tên file khi lưu
- Không upload vào thư mục đã bị khóa thực thi
Kết quả? Hacker upload file PHP → thực thi mã độc → chiếm server.
RCE (Remote Code Execution) là gì?
RCE xảy ra khi attacker có thể chạy mã tùy ý trên server của bạn. Trong WordPress, RCE thường đến từ upload file:
<?php
system($_GET['cmd']);
Chỉ cần uploader không filter đúng cách, hacker có thể gọi:
https://example.com/wp-content/uploads/shell.php?cmd=cat+wp-config.php
→ Toàn bộ site coi như xong.
Vì sao File Upload → RCE đặc biệt nguy hiểm?
- Hacker có thể đọc wp-config.php → lấy DB pass → takeover site
- Upload webshell (WSO, B374K…) để kiểm soát server
- Chèn mã độc vào mọi file
- Thay đổi mật khẩu admin
- Backdoor cả server, không chỉ website
Đa số case WordPress bị hack nặng đều đến từ upload file.
Ví dụ lỗi upload file trong WordPress
1. Kiểm tra extension quá đơn giản
<?php
if ( substr( $_FILES['file']['name'], -4 ) === '.jpg' ) {
move_uploaded_file( $_FILES['file']['tmp_name'], $path );
}
→ Hacker upload shell.php.jpg và server vẫn thực thi PHP nếu config sai.
2. Không kiểm tra MIME type
Content-Type: image/jpeg
<?php system($_GET['c']); ?>
→ Chỉ cần fake HTTP header.
3. Upload vào thư mục có thể thực thi
Ví dụ upload vào:
/wp-content/uploads/
Nếu server allow PHP execution → RCE chắc chắn xảy ra.
Cách hacker vượt bypass validation upload
- Double extension:
file.php.jpg - Null byte:
file.php%00.jpg - PHAR upload
- SVG chứa mã JS độc
- HTACCESS upload → bật thực thi PHP toàn thư mục
- Overwriting file .php qua symbolic link (symlink attack)
Cách phòng chống File Upload → RCE trong WordPress
1. Luôn sử dụng wp_handle_upload()
WordPress có hệ thống upload an toàn hơn tự code:
$uploaded = wp_handle_upload( $_FILES['my_file'], array( 'test_form' => false ) );
Hàm này đã kiểm tra:
- MIME type
- Extension
- Path traversal
2. Chỉ cho phép loại file cụ thể
function allow_only_images( $types ) {
return array(
'jpg' => 'image/jpeg',
'png' => 'image/png',
);
}
add_filter( 'upload_mimes', 'allow_only_images' );
3. Không bao giờ cho phép upload file PHP (và “anh em họ” của nó)
Các extension cần block hoàn toàn:
- .php
- .phtml
- .phar
- .php7
- .php5
4. Luôn đổi tên file khi upload
$new_name = md5( time() . rand() ) . '.jpg';
Không dùng tên user upload.
5. Upload vào thư mục không thể thực thi
Nên disable PHP execution trong thư mục uploads.
Cho Apache:
<Files *.php>
deny from all
</Files>
Cho NGINX:
location ~* /wp-content/uploads/.*\.php$ {
deny all;
}
6. Kiểm tra MIME thật từ file, không phải từ header
$finfo = finfo_open( FILEINFO_MIME_TYPE );
$mime = finfo_file( $finfo, $_FILES['file']['tmp_name'] );
if ( $mime !== 'image/jpeg' ) {
die('Invalid file');
}
7. Chặn SVG nếu bạn không thật sự cần
SVG có thể chứa JavaScript → XSS → RCE chain.
8. Không dùng form upload mà không có nonce
Chống CSRF upload:
<?php wp_nonce_field( 'file_upload_action', 'file_upload_nonce' ); ?>
9. Kiểm tra capability trước khi upload
if ( ! current_user_can( 'upload_files' ) ) {
wp_die( 'No permission.' );
}
10. Log lại mọi file upload
Dễ phát hiện upload độc.
Chuỗi tấn công File Upload → RCE phổ biến
- Upload PHP shell → chạy command → takeover hosting
- Upload .htaccess để bật thực thi PHP → upload thêm shell
- Upload PHAR → deserialize → RCE
- Upload SVG chứa script → XSS chain
- Upload ZIP → Zip Slip → ghi đè file hệ thống
Checklist chống File Upload → RCE
- Không upload vào thư mục có thể thực thi
- Dùng wp_handle_upload() thay vì tự viết uploader
- Check extension + MIME thật từ file
- Đổi tên file random khi upload
- Chặn file PHP, PHAR, PHTML, SVG
- Có nonce + capability check
- Disable PHP execution trong uploads
Kết luận
File Upload → RCE là lỗ hổng cực kỳ nguy hiểm và xảy ra rất thường xuyên trong plugin/theme WordPress. Chỉ cần một uploader thiếu kiểm tra MIME hoặc upload vào thư mục có thể chạy PHP, hacker có thể dễ dàng chiếm quyền toàn bộ website. Bằng cách sử dụng đúng API WordPress, giới hạn loại file, bật bảo vệ server-level và luôn kiểm tra quyền, bạn có thể giảm 99% nguy cơ upload → RCE.
Bình luận