Úvod: Proč je zabezpečení komentářů důležité
WordPress komentáře jsou jedním z nejčastěji napadaných vektorů na webových stránkách. Podle statistik Wordfence tvoří útoky na komentářové systémy více než 35% všech automatizovaných útoků na WordPress. Spam komentáře nejen zhoršují uživatelskou zkušenost, ale mohou také negativně ovlivnit SEO hodnocení a v extrémních případech vést k blacklistingu domény.
Jak fungují útoky na komentáře
Technické pozadí útoků
Moderní spamovací boti používají sofistikované metody pro obcházení standardních ochran:
1. Přímé HTTP požadavky
- Boti nepoužívají webový formulář na stránce, ale posílají přímé POST požadavky
- Obcházejí tak JavaScript validace, CSRF tokeny a jiné klientské ochrany
- Dokáží simulovat legitimní user-agenty a HTTP hlavičky
2. Cílené endpointy:
wp-comments-post.php
– hlavní endpoint pro zpracování komentářů/wp-json/wp/v2/comments
– REST API endpoint (WordPress 4.7+)xmlrpc.php
– XML-RPC metody pro pingbacky a trackbacky/wp-json/wp/v2/posts/{id}/comments
– specifické REST endpointy pro jednotlivé příspěvky
3. Pokročilé techniky:
- Rate limiting evasion – rotace IP adres přes proxy sítě
- Fingerprint spoofing – napodobování legitímních browserů
- Content spinning – automatické generování variací textů
- Honeypot detection – rozpoznávání a obcházení past pro boty
Dopady úspěšných útoků
Typ dopadu | Popis | Závažnost |
---|---|---|
Performance | Přetížení databáze, zpomalení webu | Vysoká |
SEO | Spam odkazy, degradace v SERP | Vysoká |
Bezpečnost | Potenciální XSS, injection útoky | Kritická |
Náklady | Vyšší server nároky, čištění | Střední |
Reputace | Ztráta důvěry návštěvníků | Střední |
Komplexní zabezpečení – krok za krokem
1. Základní nastavení v administraci
Diskuzní nastavení (wp-admin/options-discussion.php)
Kritická nastavení:
Nastavení → Diskuze
Doporučená konfigurace:
- Výchozí nastavení článků:
- Povolit návštěvníkům webu přidávat komentáře k novým příspěvkům
- Přidávat komentáře mohou pouze registrovaní a přihlášení uživatelé
- Další nastavení komentářů:
- Autor komentáře musí vyplnit jméno a e-mail
- Uživatelé musí být registrováni a přihlášeni pro přidání komentáře
- Automaticky uzavřít komentáře u článků starších než 30 dní
- Oznámení a moderace:
- Komentář musí být schválen ručně
- Komentář musí být schválen, pokud obsahuje 2 nebo více odkazů
- Poslat e-mail při každém komentáři
- Poslat e-mail při čekání komentáře na schválení
- Blacklist nastavení:
- Přidat běžná spam slova do seznamu zakázaných výrazů
- Nastavit automatické označení komentářů s podezřelými klíčovými slovy
Pokročilé WordPress hooks
Pre-comment validace:
// functions.php nebo MU plugin
add_action('pre_comment_on_post', 'custom_comment_security_check');
function custom_comment_security_check($comment_post_id) {
// Kontrola, zda je uživatel přihlášen
if (!is_user_logged_in()) {
wp_die(
'Komentáře jsou povoleny pouze přihlášeným uživatelům.',
'Přístup zamítnut',
['response' => 403]
);
}
// Kontrola rychlosti přidávání komentářů
$user_id = get_current_user_id();
$last_comment = get_transient('last_comment_time_' . $user_id);
if ($last_comment && (time() - $last_comment) < 30) {
wp_die(
'Příliš rychlé přidávání komentářů. Zkuste to za chvíli.',
'Rate limit exceeded',
['response' => 429]
);
}
set_transient('last_comment_time_' . $user_id, time(), 3600);
}
2. Technické zabezpečení endpoints
REST API ochrany
Kompletní blokace anonymních komentářů:
// Zakáže anonymní komentáře přes REST API
add_filter('rest_allow_anonymous_comments', '__return_false');
// Přidá dodatečnou autentifikaci
add_filter('rest_pre_insert_comment', 'secure_rest_comments', 10, 2);
function secure_rest_comments($prepared_comment, $request) {
if (!is_user_logged_in()) {
return new WP_Error(
'rest_comment_login_required',
'Pro přidání komentáře se musíte přihlásit.',
['status' => 401]
);
}
return $prepared_comment;
}
// Volitelně - odstranění celého comments endpointu
add_filter('rest_endpoints', 'remove_comments_endpoints');
function remove_comments_endpoints($endpoints) {
if (isset($endpoints['/wp/v2/comments'])) {
unset($endpoints['/wp/v2/comments']);
}
if (isset($endpoints['/wp/v2/comments/(?P<id>[\d]+)'])) {
unset($endpoints['/wp/v2/comments/(?P<id>[\d]+)']);
}
return $endpoints;
}
Selective REST API protection:
// Pokročilejší ochrana s logováním
add_filter('rest_pre_dispatch', 'monitor_comments_api', 10, 3);
function monitor_comments_api($result, $server, $request) {
$route = $request->get_route();
if (strpos($route, '/wp/v2/comments') !== false) {
// Logování pokusů o přístup
error_log(sprintf(
'Comments API access attempt - IP: %s, User-Agent: %s, Route: %s',
$_SERVER['REMOTE_ADDR'] ?? 'unknown',
$_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
$route
));
// Blokace pro nepřihlášené
if (!is_user_logged_in()) {
return new WP_Error(
'rest_comments_forbidden',
'Comments API access forbidden',
['status' => 403]
);
}
}
return $result;
}
XML-RPC zabezpečení
XML-RPC je častým cílem útoků, zejména pingback metody:
// Kompletní vypnutí XML-RPC
add_filter('xmlrpc_enabled', '__return_false');
// Nebo selektivní blokace nebezpečných metod
add_filter('xmlrpc_methods', 'secure_xmlrpc_methods');
function secure_xmlrpc_methods($methods) {
// Odstranění nebezpečných metod
unset($methods['pingback.ping']);
unset($methods['pingback.extensions.getPingbacks']);
unset($methods['wp.newComment']);
return $methods;
}
// Dodatečná ochrana XML-RPC pomocí .htaccess
// Přidat do .htaccess:
/*
<Files "xmlrpc.php">
Order Allow,Deny
Deny from all
</Files>
*/
wp-comments-post.php zabezpečení
PHP metoda (doporučená):
add_action('init', 'secure_comments_post_endpoint');
function secure_comments_post_endpoint() {
if (strpos($_SERVER['REQUEST_URI'], 'wp-comments-post.php') !== false) {
// Kontrola referer
if (!wp_verify_nonce($_POST['_wp_http_referer'] ?? '', 'comment_nonce')) {
// Logování podezřelé aktivity
error_log(sprintf(
'Suspicious comment attempt - IP: %s, User-Agent: %s, Referer: %s',
$_SERVER['REMOTE_ADDR'] ?? 'unknown',
$_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
$_SERVER['HTTP_REFERER'] ?? 'none'
));
}
if (!is_user_logged_in()) {
status_header(403);
wp_die('Komentáře jsou povoleny pouze přihlášeným uživatelům.');
}
// Rate limiting
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
$attempts = get_transient('comment_attempts_' . md5($ip));
if ($attempts && $attempts > 5) {
status_header(429);
wp_die('Příliš mnoho pokusů. Zkuste to později.');
}
set_transient('comment_attempts_' . md5($ip), ($attempts + 1), 300);
}
}
.htaccess metoda (Apache):
<IfModule mod_rewrite.c>
RewriteEngine On
# Blokace wp-comments-post.php pro nepřihlášené
RewriteCond %{REQUEST_URI} ^/wp-comments-post\.php$ [NC]
RewriteCond %{HTTP_COOKIE} !wordpress_logged_in_ [NC]
RewriteCond %{REQUEST_METHOD} POST [NC]
RewriteRule .* - [R=403,L]
# Blokace podezřelých User-Agents
RewriteCond %{HTTP_USER_AGENT} ^$ [NC,OR]
RewriteCond %{HTTP_USER_AGENT} (bot|crawler|spider) [NC]
RewriteCond %{REQUEST_URI} wp-comments-post\.php$ [NC]
RewriteRule .* - [R=403,L]
</IfModule>
Nginx varianta:
location = /wp-comments-post.php {
# Kontrola přihlášení přes cookie
if ($http_cookie !~* "wordpress_logged_in_") {
return 403;
}
# Rate limiting
limit_req zone=comments burst=2 nodelay;
# Blokace prázdných User-Agentů
if ($http_user_agent = "") {
return 403;
}
try_files $uri =404;
fastcgi_pass php;
}
# Rate limiting definice (přidat do http bloku)
limit_req_zone $binary_remote_addr zone=comments:10m rate=1r/m;
3. Pokročilá ochrana proti spamu
Anti-spam pluginy – srovnání
Plugin | Cena | Metody detekce | Výhody | Nevýhody |
---|---|---|---|---|
Akismet | $5-50/měs | AI, blacklisty, community | Oficiální, přesný | Placený pro komerční |
Antispam Bee | Zdarma | Honeypot, geolokace | Zdarma, GDPR compliant | Méně funkcí |
CleanTalk | $8/rok | AI, behavior analysis | Pokročilé funkce | Závislost na API |
WP Armour | Zdarma | reCAPTCHA, honeypot | Jednoduché | Základní funkce |
Vlastní antispam řešení
Honeypot implementace:
// Přidání honeypot pole do comment formu
add_action('comment_form_after_fields', 'add_honeypot_field');
function add_honeypot_field() {
echo '<p style="display:none;">
<label for="url-extra">Leave this field empty:</label>
<input type="text" name="url-extra" id="url-extra" value="" />
</p>';
}
// Kontrola honeypot při submit
add_action('pre_comment_on_post', 'check_honeypot');
function check_honeypot() {
if (!empty($_POST['url-extra'])) {
wp_die('Spam detected.', 'Error', ['response' => 403]);
}
}
Behavioral analysis:
// Analýza času vyplnění formuláře
add_action('comment_form', 'add_timing_check');
function add_timing_check() {
echo '<input type="hidden" name="comment_timestamp" value="' . time() . '" />';
}
add_filter('pre_comment_approved', 'timing_spam_check', 99, 2);
function timing_spam_check($approved, $commentdata) {
$timestamp = $_POST['comment_timestamp'] ?? 0;
$time_spent = time() - $timestamp;
// Příliš rychlé vyplnění (bot) nebo příliš pomalé (opuštěný formulář)
if ($time_spent < 5 || $time_spent > 3600) {
return 'spam';
}
return $approved;
}
CAPTCHA implementace
Google reCAPTCHA v3:
// Přidání reCAPTCHA do comment formu
add_action('comment_form_after_fields', 'add_recaptcha_v3');
function add_recaptcha_v3() {
$site_key = 'YOUR_RECAPTCHA_SITE_KEY';
echo '<script src="https://www.google.com/recaptcha/api.js?render=' . $site_key . '"></script>';
echo '<script>
grecaptcha.ready(function() {
grecaptcha.execute("' . $site_key . '", {action: "comment"}).then(function(token) {
document.getElementById("g-recaptcha-response").value = token;
});
});
</script>';
echo '<input type="hidden" id="g-recaptcha-response" name="g-recaptcha-response" />';
}
// Validace reCAPTCHA
add_filter('pre_comment_approved', 'validate_recaptcha', 10, 2);
function validate_recaptcha($approved, $commentdata) {
$secret_key = 'YOUR_RECAPTCHA_SECRET_KEY';
$response = $_POST['g-recaptcha-response'] ?? '';
if (empty($response)) {
return new WP_Error('recaptcha_required', 'reCAPTCHA verification required.');
}
$verify = wp_remote_post('https://www.google.com/recaptcha/api/siteverify', [
'body' => [
'secret' => $secret_key,
'response' => $response,
'remoteip' => $_SERVER['REMOTE_ADDR']
]
]);
$verify_body = wp_remote_retrieve_body($verify);
$result = json_decode($verify_body, true);
if (!$result['success'] || $result['score'] < 0.5) {
return 'spam';
}
return $approved;
}
Cloudflare Turnstile (alternativa k reCAPTCHA):
// Cloudflare Turnstile implementace
add_action('comment_form_after_fields', 'add_turnstile');
function add_turnstile() {
echo '<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>';
echo '<div class="cf-turnstile" data-sitekey="YOUR_TURNSTILE_SITE_KEY"></div>';
}
add_filter('pre_comment_approved', 'validate_turnstile', 10, 2);
function validate_turnstile($approved, $commentdata) {
$secret = 'YOUR_TURNSTILE_SECRET_KEY';
$token = $_POST['cf-turnstile-response'] ?? '';
if (empty($token)) {
return new WP_Error('turnstile_required', 'Turnstile verification required.');
}
$response = wp_remote_post('https://challenges.cloudflare.com/turnstile/v0/siteverify', [
'body' => [
'secret' => $secret,
'response' => $token,
'remoteip' => $_SERVER['REMOTE_ADDR']
]
]);
$body = json_decode(wp_remote_retrieve_body($response), true);
if (!$body['success']) {
return 'spam';
}
return $approved;
}
4. Monitoring a forensní analýza
Logování pokusů o spam
// Komplexní logování comment aktivit
add_action('wp_insert_comment', 'log_comment_activity', 10, 2);
function log_comment_activity($id, $comment) {
$log_data = [
'comment_id' => $id,
'post_id' => $comment->comment_post_ID,
'author_ip' => $comment->comment_author_IP,
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
'referer' => $_SERVER['HTTP_REFERER'] ?? '',
'timestamp' => current_time('mysql'),
'status' => $comment->comment_approved
];
// Ukládání do custom log tabulky nebo file
error_log('COMMENT_LOG: ' . json_encode($log_data));
// Detekce podezřelých vzorů
if (is_comment_suspicious($comment)) {
// Poslání alertu administrátorům
wp_mail(
get_option('admin_email'),
'Suspicious comment detected',
sprintf('Suspicious comment detected from IP %s on post %d',
$comment->comment_author_IP,
$comment->comment_post_ID
)
);
}
}
function is_comment_suspicious($comment) {
// Kontrola na známé spam patterns
$spam_indicators = [
strlen($comment->comment_content) < 5, // Příliš krátký
preg_match('/https?:\/\//', $comment->comment_content) > 2, // Mnoho linků
preg_match('/\[url=|\[link=/', $comment->comment_content), // BBcode linky
empty($comment->comment_author_email), // Bez emailu
];
return array_sum($spam_indicators) >= 2;
}
Databázová analýza spamu
// Funkce pro analýzu spam komentářů
function analyze_comment_patterns() {
global $wpdb;
// Top IP adresy s odmítnutými komentáři
$spam_ips = $wpdb->get_results("
SELECT comment_author_IP, COUNT(*) as count
FROM {$wpdb->comments}
WHERE comment_approved = 'spam'
AND comment_date > DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY comment_author_IP
ORDER BY count DESC
LIMIT 20
");
// Časové vzory útoků
$time_patterns = $wpdb->get_results("
SELECT HOUR(comment_date) as hour, COUNT(*) as count
FROM {$wpdb->comments}
WHERE comment_approved = 'spam'
AND comment_date > DATE_SUB(NOW(), INTERVAL 7 DAY)
GROUP BY HOUR(comment_date)
ORDER BY count DESC
");
return [
'spam_ips' => $spam_ips,
'time_patterns' => $time_patterns
];
}
5. Úplné vypnutí komentářů
Plugin Disable Comments
Nejjednodušší způsob je použití pluginu Disable Comments:
Funkce:
- Kompletní odstranění UI pro komentáře
- Blokace všech komentářových endpoints
- Čištění existujících komentářů
- Podpora pro custom post types
Manuální vypnutí
// Kompletní odstranění comment systému
add_action('admin_init', 'disable_comments_admin');
function disable_comments_admin() {
// Odstranění menu items
remove_menu_page('edit-comments.php');
remove_submenu_page('options-general.php', 'options-discussion.php');
}
add_action('init', 'disable_comments_frontend');
function disable_comments_frontend() {
// Odstranění podpory pro komentáře ze všech post types
$post_types = get_post_types();
foreach ($post_types as $post_type) {
if (post_type_supports($post_type, 'comments')) {
remove_post_type_support($post_type, 'comments');
remove_post_type_support($post_type, 'trackbacks');
}
}
}
// Blokace wp-comments-post.php
add_action('wp_loaded', 'block_comments_completely');
function block_comments_completely() {
if (strpos($_SERVER['REQUEST_URI'], 'wp-comments-post.php') !== false) {
wp_die('Comments are completely disabled.', 'Comments Disabled', 410);
}
}
// Odstranění z feeds
add_filter('comments_open', '__return_false', 20, 2);
add_filter('pings_open', '__return_false', 20, 2);
add_filter('comments_array', '__return_empty_array', 10, 2);
6. Optimalizace performance
Databázové optimalizace
-- Vyčištění spam komentářů starších než 30 dní
DELETE FROM wp_comments
WHERE comment_approved = 'spam'
AND comment_date < DATE_SUB(NOW(), INTERVAL 30 DAY);
-- Optimalizace comment meta tabulky
OPTIMIZE TABLE wp_commentmeta;
-- Index pro rychlejší dotazy
CREATE INDEX idx_comment_approved_date ON wp_comments(comment_approved, comment_date);
Caching considerations
// Invalidace cache při nových komentářích
add_action('comment_post', 'clear_comment_cache');
function clear_comment_cache($comment_id) {
$comment = get_comment($comment_id);
// Vyčištění page cache
if (function_exists('wp_cache_flush')) {
wp_cache_flush();
}
// LiteSpeed Cache
if (class_exists('LiteSpeed_Cache_API')) {
LiteSpeed_Cache_API::purge_post($comment->comment_post_ID);
}
// W3 Total Cache
if (function_exists('w3tc_flush_post')) {
w3tc_flush_post($comment->comment_post_ID);
}
}
7. Bezpečnostní monitoring
Server-level monitoring
.htaccess advanced rules:
<IfModule mod_security.c>
# Blokace společných spam patterns v komentářích
SecRule ARGS:comment "@detectSQLi" \
"id:1001,phase:2,block,msg:'SQL Injection in comment'"
SecRule ARGS:comment "@detectXSS" \
"id:1002,phase:2,block,msg:'XSS in comment'"
# Rate limiting pro comment submissions
SecRule IP:comment_rate "@gt 5" \
"id:1003,phase:2,deny,status:429"
SecAction "id:1004,phase:2,setvar:IP.comment_rate=+1,expirevar:IP.comment_rate=60"
</IfModule>
Fail2Ban konfigurace
# /etc/fail2ban/jail.local
[wordpress-comment-spam]
enabled = true filter = wordpress-comment-spam action = iptables-multiport[name=wp-comment, port=“http,https“] logpath = /var/log/apache2/access.log maxretry = 5 bantime = 3600 findtime = 300 # Filter: /etc/fail2ban/filter.d/wordpress-comment-spam.conf [Definition] failregex = ^<HOST> .* „POST .*wp-comments-post\.php.*“ 403 ^<HOST> .* „POST .*/wp-json/wp/v2/comments.*“ 40[13]
Bezpečnostní checklist
Základní ochrana (must-have)
- [ ] Komentáře pouze pro přihlášené uživatele
- [ ] Vypnutí pingbacks a trackbacks
- [ ] XML-RPC vypnuto nebo omezeno
- [ ] Antispam plugin (Akismet/Antispam Bee)
- [ ] Automatické zavření starých komentářů
- [ ] Moderace nových komentářů
Pokročilá ochrana (recommended)
- [ ] REST API endpoints zabezpečené
- [ ] wp-comments-post.php chráněno
- [ ] CAPTCHA/Turnstile implementováno
- [ ] Rate limiting nastaveno
- [ ] Honeypot pole přidána
- [ ] Behavioral analysis aktivní
Expert level (optional)
- [ ] Server-level filtering (.htaccess/Nginx)
- [ ] Fail2Ban konfigurace
- [ ] Custom logging implementováno
- [ ] Database optimization provedena
- [ ] Performance monitoring nastaveno
- [ ] Security headers konfigurovány
Závěr a doporučení
Zabezpečení WordPress komentářů vyžaduje vícevrstvý přístup kombinující správné nastavení administrace, technické ochrany a aktivní monitoring. Nejefektivnější je začít se základními opatřeními a postupně přidávat pokročilejší funkce podle potřeb konkrétního webu.
Klíčové body:
- Prevention over cleanup – lepší zabránit spamu než ho později odstraňovat
- Layered security – kombinace více obranných mechanismů
- Regular monitoring – aktivní sledování a vyhodnocování útoků
- Performance impact – vždy zvážit dopad na rychlost webu
Pro většinu webů postačí kombinace správného nastavení v administraci, kvalitního antispam pluginu a základní technické ochrany. Pokročilejší metody jsou vhodné pro weby s vysokým provozem nebo specifickými bezpečnostními požadavky.
Užitečné externí zdroje: