WordPress hiện đang chiếm hơn 43% website toàn cầu, nhưng cũng là mục tiêu hàng đầu của hacker. Mỗi ngày có hàng nghìn site WordPress bị hack vì cấu hình yếu, plugin lỗi thời hoặc lộ thông tin nhạy cảm. Là một full stack developer, mình đã maintain hàng chục site WP và thấy rằng bảo mật không phải là “làm cho đẹp” mà là “làm để sống sót”.
Dưới đây là danh sách các bước bảo mật thiết yếu mà mọi site WordPress (cá nhân, doanh nghiệp, bán hàng WooCommerce) nên triển khai ngay trong năm 2026. Mình sắp xếp theo thứ tự ưu tiên từ dễ làm đến nâng cao.
1. TẮT HOÀN TOÀN XML-RPC
Cách 1 – Chặn bằng PHP (an toàn nhất)
Thêm vào functions.php hoặc plugin riêng:
// Disable XML-RPC completely
add_filter('xmlrpc_enabled', '__return_false');
// Block direct access to xmlrpc.php
add_action('init', function () {
if (strpos($_SERVER['REQUEST_URI'], 'xmlrpc.php') !== false) {
status_header(403);
exit('XML-RPC is disabled.');
}
});
Cách 2 – Chặn bằng .htaccess (rất mạnh)
Trong .htaccess:
<Files xmlrpc.php>
Order Deny,Allow
Deny from all
</Files>
2. CHẶN HOÀN TOÀN USER ENUMERATION QUA REST API
Chỉ cho admin đăng nhập mới được gọi API users
Thêm vào functions.php:
// Block REST API user enumeration
add_filter('rest_endpoints', function ($endpoints) {
if (isset($endpoints['/wp/v2/users'])) {
unset($endpoints['/wp/v2/users']);
}
if (isset($endpoints['/wp/v2/users/(?P<id>[\\d]+)'])) {
unset($endpoints['/wp/v2/users/(?P<id>[\\d]+)']);
}
return $endpoints;
});
Hoặc cách chặt hơn:
add_filter('rest_pre_dispatch', function ($result, $server, $request) {
if (strpos($request->get_route(), '/wp/v2/users') !== false) {
if (!is_user_logged_in() || !current_user_can('list_users')) {
return new WP_Error(
'rest_forbidden',
'User endpoint is disabled',
array('status' => 403)
);
}
}
return $result;
}, 10, 3);
3 Cấu hình file .htaccess tăng cường bảo mật đến 80%
# ===============================
# WordPress Security Hardening
# ===============================
Options -Indexes
# Block sensitive files
<FilesMatch "(^\.|wp-config\.php|\.env|composer\.(json|lock)|package\.json|readme\.html|license\.txt|phpunit\.xml)">
Require all denied
</FilesMatch>
# Disable XML-RPC
<Files xmlrpc.php>
Require all denied
</Files>
# Block author enumeration
RewriteCond %{QUERY_STRING} author=\d+ [NC]
RewriteRule .* - [F,L]
# Protect wp-includes
RewriteRule ^wp-includes/.*\.php$ - [F,L]
# Disable PHP in uploads
RewriteRule ^wp-content/uploads/.*\.php$ - [F,L]
# Block backup & temp files
<FilesMatch "\.(bak|old|orig|save|swp|sql|log|zip|tar|gz)$">
Require all denied
</FilesMatch>
# Hide server signature
ServerSignature Off
# Remove X-Powered-By
Header unset X-Powered-By
Header always unset X-Powered-By
4. Bảo mật header security headers
Thêm vào functions.php
function add_klamed_security_headers() {
// Chỉ add cho frontend, tránh conflict admin
if ( ! is_admin() && ! is_customize_preview() ) {
// X-Content-Type-Options: Đã có, nhưng add lại cho chắc
header( 'X-Content-Type-Options: nosniff' );
// X-Frame-Options: Đã có SAMEORIGIN, giữ nguyên hoặc thay bằng CSP frame-ancestors
header( 'X-Frame-Options: SAMEORIGIN' );
// Referrer-Policy: Bảo vệ referrer (strict-origin-when-cross-origin là chuẩn 2026)
header( 'Referrer-Policy: strict-origin-when-cross-origin' );
// Permissions-Policy: Tắt feature không cần (cụ chỉnh nếu site dùng camera/geolocation)
header( 'Permissions-Policy: geolocation=(), microphone=(), camera=(), payment=(), usb=(), fullscreen=(self), interest-cohort=()' );
// Strict-Transport-Security (HSTS): Buộc HTTPS, max-age 1 năm + preload (sau khi test ổn thì submit hstspreload.org)
if ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] === 'on' ) {
header( 'Strict-Transport-Security: max-age=31536000; includeSubDomains; preload' );
}
// Content-Security-Policy: Cái quan trọng nhất, bắt đầu loose vì Woo + plugin thường inline script/style
// Dùng 'unsafe-inline' + 'unsafe-eval' tạm thời để site không trắng, sau tighten dần
$csp = "default-src 'self' https:; " .
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https: blob:; " . // 'unsafe-eval' cho một số JS động Woo/Flatsome
"style-src 'self' 'unsafe-inline' https:; " .
"img-src 'self' data: https: blob:; " .
"font-src 'self' data: https:; " .
"connect-src 'self' https: wss:; " . // cho AJAX, WebSocket nếu có
"frame-ancestors 'self'; " . // Thay X-Frame-Options
"form-action 'self' https:; " .
"base-uri 'self';";
header( "Content-Security-Policy: $csp" );
}
}
add_action( 'send_headers', 'add_klamed_security_headers', 999 ); // Priority cao để override nếu có plugin khác
5. Nếu server nginx thì thêm cấu hình block sau
# ===============================
# WordPress Security Hardening
# ===============================
autoindex off;
server_tokens off;
# Hide headers
fastcgi_hide_header X-Powered-By;
proxy_hide_header X-Powered-By;
# Block sensitive files
location ~* (^\.|wp-config\.php|\.env|composer\.(json|lock)|package\.json|readme\.html|license\.txt|phpunit\.xml) {
deny all;
access_log off;
log_not_found off;
}
# Disable XML-RPC
location = /xmlrpc.php {
deny all;
access_log off;
log_not_found off;
}
# Block author enumeration
if ($query_string ~* "author=\d+") {
return 403;
}
# Protect wp-includes
location ~* ^/wp-includes/.*\.php$ {
deny all;
}
# Disable PHP in uploads
location ~* ^/wp-content/uploads/.*\.php$ {
deny all;
}
# Block backup & temp files
location ~* \.(bak|old|orig|save|swp|sql|log|zip|tar|gz)$ {
deny all;
}



