NỘI DUNG
Trong bối cảnh các website ngày càng trở thành mục tiêu của nhiều hình thức tấn công tinh vi, việc bảo vệ các cơ chế xác thực và xử lý request là yếu tố then chốt. Một trong những điểm thường bị khai thác trên các website WordPress là tham số _wpnonce — vốn được thiết kế để chống lại các cuộc tấn công giả mạo yêu cầu (CSRF). Tuy nhiên, nếu triển khai không đúng cách hoặc bị lộ logic xử lý, _wpnonce có thể trở thành điểm yếu nghiêm trọng. Vì vậy, hiểu rõ cách hoạt động và áp dụng các biện pháp bảo vệ phù hợp là bước quan trọng để đảm bảo an toàn cho hệ thống.

1. wpnonce là gì?
Định nghĩa
_wpnonce (WordPress Nonce) là viết tắt của “Number used ONCE” – một mã token bảo mật do WordPress tự động tạo ra để:
- Xác thực request đến từ người dùng hợp lệ
- Chống tấn công CSRF (Cross-Site Request Forgery)
- Bảo vệ các hành động quan trọng: thêm vào giỏ hàng, xóa sản phẩm, cập nhật thông tin…
Cách hoạt động hợp lệ
// WordPress tạo nonce
$nonce = wp_create_nonce('add_to_cart');
// Kết quả: e3b212970d
// Khi user click "Thêm vào giỏ"
// WordPress gửi request kèm nonce để xác thực
POST /wp-admin/admin-ajax.php
action=add_to_cart&product_id=123&_wpnonce=e3b212970d
// Server kiểm tra
if (wp_verify_nonce($_POST['_wpnonce'], 'add_to_cart')) {
// Hợp lệ → thực hiện
} else {
// Không hợp lệ → từ chối
}Ví dụ URL hợp lệ
# Admin action (hợp lệ)
/wp-admin/admin-ajax.php?action=remove_item&_wpnonce=abc123
# WooCommerce wishlist (hợp lệ)
/wishlist/?add_to_wishlist=456&_wpnonce=def4562. Tại sao website bị tấn công qua _wpnonce?
2.1. Phân tích log tấn công thực tế
Như ảnh ở đầu bài, tôi có một website tiếp nhận của khách đang bị lợi dụng tấn công dạng này, bạn hãy xem qua log
45.180.216.135 - [02/May/2026:09:38:51] "GET /product-tag/computers/page/537/?_wpnonce=14c503d51d&add_to_wishlist=26980 HTTP/1.1" 200 31731
123.25.147.12 - [02/May/2026:09:38:51] "GET /product-tag/computers/page/1/?_wpnonce=e3b212970d&add_to_wishlist=20351 HTTP/1.1" 499 0
73.9.10.255 - [02/May/2026:09:38:51] "GET /cart/?remove_item=82ee6f&_wpnonce=67f98b87bb HTTP/1.1" 200 46778
31.215.8.172 - [02/May/2026:09:38:52] "GET /product-tag/medical/page/6/?_wpnonce=cfe2631afb&add_to_wishlist=106354 HTTP/1.1" 499 02.2. Dấu hiệu nhận biết tấn công
| Tiêu chí | Request hợp lệ | Bot tấn công |
|---|---|---|
| Phương thức | POST (qua AJAX) | GET (URL trực tiếp) |
| Cookie/Session | Có đầy đủ | Không có hoặc fake |
| Tần suất | Bình thường | Hàng trăm/ngàn request/giây |
| IP | Ổn định | Nhiều IP khác nhau |
| Page number | 1-5 | 100, 500, 1000+ |
| Status code | 200 | 499, 444, 503 |
| User-Agent | Thật | Fake hoặc bot |
2.3. Mục đích của kẻ tấn công
DDoS – Từ chối dịch vụ:
- Gửi hàng triệu request làm quá tải server
- Tốn băng thông, CPU, RAM
- Website chậm hoặc crash
Database Overload:
- Mỗi request tạo query vào MySQL
- Database bị phình to:
wp_usermeta,wp_woocommerce_sessions - Làm chậm toàn bộ website
Quét lỗ hổng bảo mật:
- Thử bypass nonce validation
- Tìm plugin/theme có lỗi
- Thu thập thông tin hệ thống
SEO Attack:
- Tạo hàng ngàn trang fake
- Spam Google với duplicate content
3. Nhận biết dấu hiệu tấn công
3.1. Kiểm tra log trên Linux/Unix
# Xem số lượng request có _wpnonce
grep "_wpnonce" /var/log/nginx/access.log | wc -l
# Xem 20 IP tấn công nhiều nhất
grep "_wpnonce" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20
# Kết quả:
# 5432 45.180.216.135
# 4891 123.25.147.12
# 3456 73.9.10.255
# Xem pattern URL bị tấn công
grep "_wpnonce" /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -10
# Xem request theo giờ
grep "_wpnonce" /var/log/nginx/access.log | awk '{print $4}' | cut -d: -f1-2 | sort | uniq -c
# Lọc theo status code
grep "_wpnonce" /var/log/nginx/access.log | grep " 499 " | wc -l3.2. Kiểm tra trên cPanel
- Đăng nhập cPanel → Metrics → Raw Access Logs
- Download file log về máy
- Mở bằng text editor, tìm kiếm
_wpnonce - Đếm số dòng chứa
_wpnonce
Hoặc xem trực tiếp Visitors trên cPanel
3.3. Kiểm tra Database (MySQL)
-- Kiểm tra số lượng session
SELECT COUNT(*) FROM wp_woocommerce_sessions;
-- Kiểm tra wishlist spam
SELECT COUNT(*) FROM wp_usermeta WHERE meta_key LIKE '%wishlist%';
-- Xem các session lớn bất thường
SELECT session_key, LENGTH(session_value) as size
FROM wp_woocommerce_sessions
ORDER BY size DESC
LIMIT 20;4. Cách chặn bằng Nginx
4.1. Chặn cơ bản – Khuyến nghị cho mọi website
server {
# ... cấu hình khác ...
# ========================================
# CHẶN _wpnonce TRONG GET REQUEST
# ========================================
# Chặn tất cả request có _wpnonce trong query string
# An toàn vì người dùng thật dùng POST, không phải GET
if ($args ~* "_wpnonce=") {
return 444; # Đóng kết nối ngay lập tức
}
# ========================================
# CHẶN CÁC PARAMETER ĐI KÈM
# ========================================
# Thường xuất hiện cùng _wpnonce trong tấn công
if ($args ~* "(add_to_wishlist=|remove_item=)") {
return 444;
}
}Status code giải thích:
444– Nginx đóng kết nối, không trả response (tiết kiệm tài nguyên nhất)403– Forbidden (có ghi log)503– Service Unavailable
4.2. Chặn nâng cao – Với Rate Limiting
# ========================================
# ĐẶT NGOÀI BLOCK SERVER (TRONG HTTP BLOCK)
# ========================================
# Tạo zone giới hạn request theo IP
limit_req_zone $binary_remote_addr zone=wpnonce_zone:10m rate=5r/m;
# Tạo zone chặn burst request
limit_conn_zone $binary_remote_addr zone=wpnonce_conn:10m;
server {
# ... cấu hình khác ...
# ========================================
# GIỚI HẠN TỐC ĐỘ CHO REQUEST CÓ _wpnonce
# ========================================
location / {
# Nếu có _wpnonce, áp dụng rate limit
if ($args ~* "_wpnonce=") {
set $wpnonce_limit 1;
}
# Rate limit: 5 request/phút/IP, cho phép burst 2
if ($wpnonce_limit) {
limit_req zone=wpnonce_zone burst=2 nodelay;
limit_conn wpnonce_conn 3;
}
# ... config khác ...
}
}4.3. Chặn theo pattern cụ thể
server {
# ========================================
# CHẶN PRODUCT-TAG VỚI TRANG SỐ CAO
# ========================================
# Bot thường quét /page/100, /page/500...
# Người dùng thật chỉ xem trang 1-5
location ~ "^/product-tag/.*/page/[0-9]{2,}/" {
if ($args ~* "_wpnonce=") {
return 444;
}
}
# ========================================
# CHẶN SAMPLE-PAGE (TRANG DEMO)
# ========================================
location ~* ^/sample-page/ {
return 444;
}
# ========================================
# CHẶN CART ACTION ĐÁNG NGỜ
# ========================================
location = /cart/ {
# Cho phép GET bình thường
# Nhưng chặn GET với _wpnonce (action phải dùng POST)
if ($args ~* "_wpnonce=") {
return 444;
}
}
}4.4. Sử dụng Map (Hiệu năng cao nhất)
# ========================================
# ĐẶT TRONG HTTP BLOCK (NGOÀI SERVER)
# ========================================
map $args $block_wpnonce {
default 0;
"~*_wpnonce=" 1;
"~*add_to_wishlist=" 1;
"~*remove_item=" 1;
}
map $request_uri $block_sample_page {
default 0;
"~*^/sample-page/" 1;
"~*^/product-tag/.*/page/[0-9]{3,}/" 1;
}
server {
# ========================================
# ÁP DỤNG CHẶN
# ========================================
if ($block_wpnonce) {
return 444;
}
if ($block_sample_page) {
return 444;
}
}5. Cách chặn bằng .htaccess (Apache, LiteSpeed)
5.1. Chặn cơ bản
# ============================================================================
# .htaccess - Chặn tấn công _wpnonce
# Đặt file này ở thư mục root của WordPress
# ============================================================================
# Bật Rewrite Engine
<IfModule mod_rewrite.c>
RewriteEngine On
# ========================================
# CHẶN _wpnonce TRONG QUERY STRING
# ========================================
# Nếu URL chứa _wpnonce, từ chối ngay
RewriteCond %{QUERY_STRING} _wpnonce= [NC]
RewriteRule ^.*$ - [F,L]
# ========================================
# CHẶN CÁC PARAMETER ĐÁG NGỜ KÈM THEO
# ========================================
RewriteCond %{QUERY_STRING} add_to_wishlist= [NC,OR]
RewriteCond %{QUERY_STRING} remove_item= [NC]
RewriteRule ^.*$ - [F,L]
</IfModule>Flags giải thích:
[NC]– No Case (không phân biệt hoa/thường)[OR]– Hoặc (kết hợp nhiều điều kiện)[F]– Forbidden (403)[L]– Last (dừng xử lý rule)
5.2. Chặn với status code tùy chỉnh
<IfModule mod_rewrite.c>
RewriteEngine On
# ========================================
# TRẢ VỀ 410 GONE (GOOGLE SẼ XÓA KHỎI INDEX)
# ========================================
RewriteCond %{QUERY_STRING} _wpnonce= [NC]
RewriteRule ^.*$ - [G,L]
# ========================================
# HOẶC TRẢ VỀ 503 SERVICE UNAVAILABLE
# ========================================
# RewriteCond %{QUERY_STRING} _wpnonce= [NC]
# RewriteRule ^.*$ - [R=503,L]
</IfModule>5.3. Chặn theo pattern URL cụ thể
<IfModule mod_rewrite.c>
RewriteEngine On
# ========================================
# CHẶN PRODUCT-TAG VỚI TRANG SỐ CAO
# ========================================
# Ví dụ: /product-tag/computers/page/537/
RewriteCond %{REQUEST_URI} ^/product-tag/.*/page/[0-9]{3,}/ [NC]
RewriteCond %{QUERY_STRING} _wpnonce= [NC]
RewriteRule ^.*$ - [F,L]
# ========================================
# CHẶN SAMPLE-PAGE
# ========================================
RewriteCond %{REQUEST_URI} ^/sample-page/ [NC]
RewriteRule ^.*$ - [F,L]
# ========================================
# CHẶN CART ACTION VỚI _wpnonce
# ========================================
RewriteCond %{REQUEST_URI} ^/cart/ [NC]
RewriteCond %{QUERY_STRING} _wpnonce= [NC]
RewriteRule ^.*$ - [F,L]
</IfModule>5.4. Rate Limiting với mod_evasive
# ============================================================================
# Cài đặt mod_evasive trước
# Ubuntu/Debian: apt-get install libapache2-mod-evasive
# CentOS/RHEL: yum install mod_evasive
# ============================================================================
<IfModule mod_evasive20.c>
# Số request tối đa trên 1 trang trong 1 giây
DOSPageCount 5
# Số request tối đa trên toàn site trong 1 giây
DOSSiteCount 50
# Thời gian chặn IP (giây)
DOSBlockingPeriod 10
# Khoảng thời gian tính request
DOSPageInterval 1
DOSSiteInterval 1
# Whitelist IP của bạn
DOSWhitelist 123.45.67.89
# Email nhận cảnh báo
DOSEmailNotify [email protected]
# Log file
DOSLogDir /var/log/apache2/mod_evasive
</IfModule>5.5. Chặn theo User-Agent
<IfModule mod_rewrite.c>
RewriteEngine On
# ========================================
# CHẶN BOT XẤU
# ========================================
RewriteCond %{HTTP_USER_AGENT} (python-requests|curl|wget|Go-http-client|GPTBot) [NC,OR]
RewriteCond %{HTTP_USER_AGENT} (SemrushBot|AhrefsBot|MJ12bot|DotBot) [NC]
RewriteRule ^.*$ - [F,L]
# ========================================
# CHẶN USER-AGENT TRỐNG
# ========================================
RewriteCond %{HTTP_USER_AGENT} ^$ [OR]
RewriteCond %{HTTP_USER_AGENT} ^- [OR]
RewriteCond %{HTTP_USER_AGENT} ^\s*$
RewriteRule ^.*$ - [F,L]
</IfModule>5.6. Whitelist IP quan trọng
<IfModule mod_rewrite.c>
RewriteEngine On
# ========================================
# WHITELIST IP (BỎ QUA TẤT CẢ RULE)
# ========================================
# IP của bạn
RewriteCond %{REMOTE_ADDR} ^123\.45\.67\.89$ [OR]
# IP văn phòng
RewriteCond %{REMOTE_ADDR} ^111\.222\.333\.444$
RewriteRule ^.*$ - [S=999]
# ========================================
# CÁC RULE CHẶN (CHỈ ÁP DỤNG CHO IP KHÁC)
# ========================================
RewriteCond %{QUERY_STRING} _wpnonce= [NC]
RewriteRule ^.*$ - [F,L]
</IfModule>5.7. Config hoàn chỉnh .htaccess
# ============================================================================
# .htaccess - Anti _wpnonce Attack
# Cập nhật: 02/05/2026
# ============================================================================
# ========================================
# 1. BẬT REWRITE ENGINE
# ========================================
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# ========================================
# 2. WHITELIST IP (BỎ QUA TẤT CẢ RULE)
# ========================================
# Thay YOUR_IP bằng IP thật của bạn
RewriteCond %{REMOTE_ADDR} ^YOUR_IP$
RewriteRule ^.*$ - [S=999]
# ========================================
# 3. CHẶN BOT XẤU
# ========================================
RewriteCond %{HTTP_USER_AGENT} (python-requests|curl|wget|Go-http-client|GPTBot|ClaudeBot) [NC,OR]
RewriteCond %{HTTP_USER_AGENT} (SemrushBot|AhrefsBot|MJ12bot|DotBot|Bytespider) [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^$ [OR]
RewriteCond %{HTTP_USER_AGENT} ^-
RewriteRule ^.*$ - [F,L]
# ========================================
# 4. CHẶN _wpnonce TRONG GET REQUEST
# ========================================
RewriteCond %{QUERY_STRING} _wpnonce= [NC]
RewriteRule ^.*$ - [F,L]
# ========================================
# 5. CHẶN PARAMETER ĐÁG NGỜ
# ========================================
RewriteCond %{QUERY_STRING} add_to_wishlist= [NC,OR]
RewriteCond %{QUERY_STRING} remove_item= [NC,OR]
RewriteCond %{QUERY_STRING} add-to-cart= [NC]
RewriteRule ^.*$ - [F,L]
# ========================================
# 6. CHẶN PRODUCT-TAG VỚI TRANG CAO
# ========================================
RewriteCond %{REQUEST_URI} ^/product-tag/.*/page/[0-9]{3,}/ [NC]
RewriteRule ^.*$ - [F,L]
# ========================================
# 7. CHẶN SAMPLE-PAGE
# ========================================
RewriteCond %{REQUEST_URI} ^/sample-page/ [NC]
RewriteRule ^.*$ - [F,L]
# ========================================
# 8. CHẶN REQUEST METHOD KHÔNG HỢP LỆ
# ========================================
RewriteCond %{REQUEST_METHOD} ^(TRACE|DELETE|TRACK) [NC]
RewriteRule ^.*$ - [F,L]
</IfModule>
# ========================================
# 9. BẢO MẬT FILE QUAN TRỌNG
# ========================================
<FilesMatch "^(wp-config\.php|xmlrpc\.php|php\.ini|readme\.html)$">
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order allow,deny
Deny from all
</IfModule>
</FilesMatch>
# ========================================
# 10. RATE LIMITING (NẾU CÓ mod_evasive)
# ========================================
<IfModule mod_evasive20.c>
DOSPageCount 10
DOSSiteCount 100
DOSBlockingPeriod 60
DOSPageInterval 1
DOSSiteInterval 1
</IfModule>
# ========================================
# 11. HEADERS BẢO MẬT
# ========================================
<IfModule mod_headers.c>
Header set X-Content-Type-Options "nosniff"
Header set X-Frame-Options "SAMEORIGIN"
Header set X-XSS-Protection "1; mode=block"
Header set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
# ========================================
# KẾT THÚC .htaccess
# ========================================6. Cách chặn bằng Cloudflare
6.1. Firewall Rules – Chặn cơ bản
Bước 1: Đăng nhập Cloudflare → Chọn domain → Security → WAF → Create rule
Rule 1: Chặn _wpnonce trong Query String
Rule name: Block wpnonce attacks
Field: URI Query String
Operator: contains
Value: _wpnonce=
Action: BlockRule 2: Chặn kết hợp nhiều pattern
Rule name: Block wpnonce combined
Expression builder:
(http.request.uri.query contains "_wpnonce=") or
(http.request.uri.query contains "add_to_wishlist=") or
(http.request.uri.query contains "remove_item=")
Action: Block6.2. Firewall Rules – Nâng cao với Custom Expression
Chặn _wpnonce + page number cao:
Expression:
(http.request.uri.query contains "_wpnonce=") and
(http.request.uri.path matches "^/product-tag/.*/page/[0-9]{3,}/")
Action: BlockChặn theo User-Agent:
Expression:
(http.user_agent contains "python-requests") or
(http.user_agent contains "curl") or
(http.user_agent contains "wget") or
(http.user_agent eq "")
Action: BlockChặn theo quốc gia (chỉ cho phép VN):
Expression:
(ip.geoip.country ne "VN") and
(http.request.uri.query contains "_wpnonce=")
Action: Block6.3. Rate Limiting Rules
Bước 1: Security → WAF → Rate limiting rules → Create rule
Rule: Giới hạn request có _wpnonce
Rule name: wpnonce rate limit
If incoming requests match:
Field: URI Query String
Operator: contains
Value: _wpnonce=
With the same characteristics:
- IP Address
Request rate:
5 requests per 1 minute
Then take action:
Block for 1 hour6.4. Bot Fight Mode
Bước 1: Security → Bots → Configure Super Bot Fight Mode
Cấu hình:
- Definitely automated: Block
- Verified bots: Allow (Google, Bing…)
- JavaScript Detections: Challenge
- Lưu ý: Tính năng này yêu cầu gói Pro trở lên
6.5. Custom Rules với Managed Challenge
Rule: Challenge trước khi cho phép truy cập
Rule name: Challenge suspicious wpnonce
Expression:
(http.request.uri.query contains "_wpnonce=") and
(cf.threat_score gt 10)
Action: Managed ChallengeThreat Score:
- 0 = Rất tin cậy
- 10-30 = Đáng ngờ
- 30+ = Nguy hiểm cao
6.6. Transform Rules (Redirect)
Chuyển hướng request xấu về trang 404:
Rule name: Redirect wpnonce to 404
If: http.request.uri.query contains "_wpnonce="
Type: Static
URL: https://senabooks.com/404
Status code: 301 (hoặc 302)Tóm lại, _wpnonce là lớp bảo vệ quan trọng trong WordPress nhưng không phải tuyệt đối an toàn. Việc sử dụng đúng cách, kết hợp kiểm tra logic và các biện pháp bảo mật bổ sung sẽ giúp giảm thiểu rủi ro bị khai thác và nâng cao độ an toàn cho website.
Với kinh nghiệm thực chiến từ việc tiếp xúc hàng ngày với vô vàn vấn đề về Website, Hosting, VPS, Server tại Phòng Kỹ thuật AZDIGI, mình luôn ấp ủ niềm đam mê chia sẻ kiến thức.
Mình xây dựng các blog không chỉ để tự trau dồi kỹ năng mà còn để cung cấp những tài liệu, hướng dẫn hữu ích nhất đến cộng đồng. Rất mong nhận được sự quan tâm của các bạn!
Để lại thông tin, mình sẽ phản hồi ngay.
