Files
2026-08-14 07:59:43 +00:00

406 lines
15 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* WP Multi Modul: Brute-Force-Schutz
*
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
*/
if (!defined('ABSPATH')) { exit; }
/*
* Schutz vor Brute-Force-Angriffen mit wöchentlicher Zusammenfassung
* Sperr-E-Mails entfernt, Zusammenfassung deaktivierbar unter Benutzer mit verbessertem Design
*/
// Funktion zur Erfassung der echten IP-Adresse des Benutzers
function get_user_ip() {
if (!empty($_SERVER['HTTP_CLIENT_IP']) && filter_var($_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP)) {
return $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$ip = trim($ips[0]);
return filter_var($ip, FILTER_VALIDATE_IP) ? $ip : $_SERVER['REMOTE_ADDR'];
}
return filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
}
// Funktion zur Verfolgung von fehlgeschlagenen Anmeldeversuchen
function wp_multi_log_failed_login($username) {
global $wpdb;
$ip = get_user_ip();
if ($ip === '0.0.0.0') {
return;
}
$blocked_table = $wpdb->prefix . 'blocked_ips';
$attempts_table = $wpdb->prefix . 'login_attempts';
$block_threshold = 5;
// Anmeldeversuch in attempts-Tabelle speichern
$wpdb->insert(
$attempts_table,
array(
'ip' => $ip,
'username' => $username,
'attempt_time' => current_time('mysql'),
),
array('%s', '%s', '%s')
);
// Prüfen, ob IP bereits in blocked_ips existiert
$row = $wpdb->get_row($wpdb->prepare("SELECT * FROM $blocked_table WHERE ip = %s", $ip));
if ($row) {
$wpdb->update(
$blocked_table,
array(
'attempts' => $row->attempts + 1,
'last_attempt' => current_time('mysql'),
),
array('ip' => $ip),
array('%d', '%s'),
array('%s')
);
$attempts = $row->attempts + 1;
} else {
$wpdb->insert(
$blocked_table,
array(
'ip' => $ip,
'attempts' => 1,
'last_attempt' => current_time('mysql'),
),
array('%s', '%d', '%s')
);
$attempts = 1;
}
// IP sperren, wenn Schwellenwert erreicht
if ($attempts >= $block_threshold) {
wp_die(
__('Deine IP-Adresse wurde aufgrund zu vieler Fehlversuche gesperrt. Bitte versuche es später noch einmal.', 'wp-multi'),
__('Zugriff gesperrt', 'wp-multi'),
array('response' => 403)
);
}
}
// Hook für fehlgeschlagene Anmeldungen
add_action('wp_login_failed', 'wp_multi_log_failed_login', 10, 1);
// Funktion zur Erstellung der Tabellen
function wp_multi_create_blocked_ips_table() {
global $wpdb;
$blocked_table = $wpdb->prefix . 'blocked_ips';
$attempts_table = $wpdb->prefix . 'login_attempts';
$charset_collate = $wpdb->get_charset_collate();
$version = get_option('wp_multi_blocked_ips_version', '1.0');
if (version_compare($version, '1.1', '<')) {
$sql_blocked = "CREATE TABLE $blocked_table (
id mediumint(9) NOT NULL AUTO_INCREMENT,
ip varchar(45) NOT NULL,
attempts int NOT NULL DEFAULT 0,
last_attempt datetime NOT NULL,
PRIMARY KEY (id),
KEY ip (ip)
) $charset_collate;";
$sql_attempts = "CREATE TABLE $attempts_table (
id mediumint(9) NOT NULL AUTO_INCREMENT,
ip varchar(45) NOT NULL,
username varchar(255) NOT NULL,
attempt_time datetime NOT NULL,
PRIMARY KEY (id),
KEY ip (ip),
KEY attempt_time (attempt_time)
) $charset_collate;";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta($sql_blocked);
dbDelta($sql_attempts);
update_option('wp_multi_blocked_ips_version', '1.1');
}
}
register_activation_hook(WP_MULTI_FILE, 'wp_multi_create_blocked_ips_table');
// Wöchentliche Zusammenfassung
function wp_multi_send_weekly_summary() {
global $wpdb;
// Prüfen, ob Zusammenfassung aktiviert ist
$summary_enabled = get_option('wp_multi_summary_enabled', 1);
if (!$summary_enabled) {
return;
}
$attempts_table = $wpdb->prefix . 'login_attempts';
$last_email_time = get_option('wp_multi_last_summary_email', 0);
$current_time = time();
// Prüfen, ob eine Woche vergangen ist (7 Tage = 604800 Sekunden)
if (($current_time - $last_email_time) < 604800) {
return;
}
// Zeitraum für die Zusammenfassung (letzte Woche)
$week_ago = date('Y-m-d H:i:s', strtotime('-7 days'));
$now = date('Y-m-d H:i:s');
// Gesamtzahl der Anmeldeversuche
$total_attempts = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(*) FROM $attempts_table WHERE attempt_time >= %s",
$week_ago
)
);
$total_attempts = $total_attempts ? $total_attempts : 0;
// Top 10 IPs mit den meisten Anmeldeversuchen
$top_attempts = $wpdb->get_results(
$wpdb->prepare(
"SELECT ip, username, COUNT(*) as attempt_count, MAX(attempt_time) as last_attempt
FROM $attempts_table
WHERE attempt_time >= %s
GROUP BY ip, username
ORDER BY attempt_count DESC
LIMIT 10",
$week_ago
)
);
// E-Mail-Inhalt
$message = __("Wöchentliche Anmeldeversuche-Zusammenfassung\n\n", 'wp-multi');
$message .= sprintf(__("Zeitraum: %s bis %s\n\n", 'wp-multi'), $week_ago, $now);
$message .= sprintf(__("Gesamtzahl der Anmeldeversuche: %d\n\n", 'wp-multi'), $total_attempts);
$message .= __("Top 10 Anmeldeversuche (nach IP und Benutzername):\n", 'wp-multi');
if ($top_attempts) {
foreach ($top_attempts as $index => $attempt) {
$message .= sprintf(
__("%d. IP: %s, Benutzername: %s, Versuche: %d, Letzter Versuch: %s\n", 'wp-multi'),
$index + 1,
$attempt->ip,
$attempt->username,
$attempt->attempt_count,
$attempt->last_attempt
);
}
} else {
$message .= __("Keine Anmeldeversuche in diesem Zeitraum.\n", 'wp-multi');
}
// E-Mail an Admin senden
$admin_email = get_option('admin_email');
wp_mail(
$admin_email,
__('Wöchentliche Anmeldeversuche-Zusammenfassung', 'wp-multi'),
$message,
array('Content-Type: text/plain; charset=UTF-8')
);
// Aktualisiere den Zeitstempel der letzten E-Mail
update_option('wp_multi_last_summary_email', $current_time);
}
// Planen der wöchentlichen Zusammenfassung (jeden Montag um 8:00 Uhr)
function wp_multi_schedule_weekly_summary() {
if (!wp_next_scheduled('wp_multi_weekly_summary_event')) {
wp_schedule_event(strtotime('next Monday 08:00'), 'weekly', 'wp_multi_weekly_summary_event');
}
}
add_action('wp', 'wp_multi_schedule_weekly_summary');
// Hook für die Ausführung der Zusammenfassung
add_action('wp_multi_weekly_summary_event', 'wp_multi_send_weekly_summary');
// Einstellungsoption für die Zusammenfassung
function wp_multi_users_register_settings() {
add_option('wp_multi_summary_enabled', 1);
register_setting('wp_multi_users_settings_group', 'wp_multi_summary_enabled', array(
'type' => 'integer',
'sanitize_callback' => 'absint',
'default' => 1,
));
// Settings Section hinzufügen
add_settings_section(
'wp_multi_security_section',
__('Brute-Force-Schutz Einstellungen', 'wp-multi'),
'wp_multi_security_section_callback',
'wp_multi_users_security_settings'
);
// Settings Field hinzufügen
add_settings_field(
'wp_multi_summary_enabled',
__('Wöchentliche Zusammenfassung', 'wp-multi'),
'wp_multi_summary_enabled_callback',
'wp_multi_users_security_settings',
'wp_multi_security_section'
);
}
add_action('admin_init', 'wp_multi_users_register_settings');
// Callback für die Settings Section
function wp_multi_security_section_callback() {
echo '<p>' . __('Konfiguriere die Sicherheitseinstellungen für den Brute-Force-Schutz deiner Website. Aktiviere oder deaktiviere die wöchentliche Zusammenfassung der fehlgeschlagenen Anmeldeversuche.', 'wp-multi') . '</p>';
}
// Callback für das Settings Field
function wp_multi_summary_enabled_callback() {
$summary_enabled = get_option('wp_multi_summary_enabled', 1);
?>
<input type="checkbox" name="wp_multi_summary_enabled" id="wp_multi_summary_enabled" value="1" <?php checked(1, $summary_enabled); ?> />
<label for="wp_multi_summary_enabled"><?php _e('Wöchentliche E-Mail-Zusammenfassung für fehlgeschlagene Anmeldeversuche aktivieren', 'wp-multi'); ?></label>
<p class="description"><?php _e('Wenn aktiviert, erhält der Administrator jeden Montag um 8:00 Uhr eine E-Mail mit einer Zusammenfassung der fehlgeschlagenen Anmeldeversuche der letzten Woche.', 'wp-multi'); ?></p>
<?php
}
// Blockierte IPs & Sicherheitseinstellungen werden zentral in wp_multi_register_admin_menus() registriert.
// Einstellungsseite unter Benutzer
function wp_multi_users_security_settings_page() {
wpmt_admin_page_open(
__('Benutzer-Sicherheit', 'wp-multi'),
__('Brute-Force-Schutz und Benachrichtigungen für fehlgeschlagene Logins', 'wp-multi')
);
wpmt_admin_card_open(__('Brute-Force-Schutz', 'wp-multi'));
?>
<p><?php _e('Verwalte die Einstellungen für den Schutz vor Brute-Force-Angriffen. Passe die Benachrichtigungen für fehlgeschlagene Anmeldeversuche an.', 'wp-multi'); ?></p>
<form method="post" action="options.php">
<?php
settings_fields('wp_multi_users_settings_group');
do_settings_sections('wp_multi_users_security_settings');
submit_button(__('Einstellungen speichern', 'wp-multi'));
?>
</form>
<?php
wpmt_admin_card_close();
wpmt_admin_page_close();
}
// Anzeige der blockierten IPs im Admin-Bereich
function wp_multi_display_blocked_ips() {
global $wpdb;
$table_name = $wpdb->prefix . 'blocked_ips';
$five_days_ago = date('Y-m-d H:i:s', strtotime('-5 days'));
$per_page = 50;
$page = max(1, isset($_GET['paged']) ? intval($_GET['paged']) : 1);
$offset = ($page - 1) * $per_page;
$blocked_ips = $wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM $table_name WHERE last_attempt >= %s ORDER BY last_attempt DESC LIMIT %d OFFSET %d",
$five_days_ago,
$per_page,
$offset
)
);
$total_ips = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $table_name WHERE last_attempt >= %s", $five_days_ago));
$total_pages = ceil($total_ips / $per_page);
wpmt_admin_page_open(
__('Blockierte IPs', 'wp-multi'),
__('Vom Brute-Force-Schutz erfasste IP-Adressen der letzten 5 Tage', 'wp-multi')
);
wpmt_admin_card_open();
if (empty($blocked_ips)) {
wpmt_admin_notice('info', __('Keine blockierten IPs gefunden.', 'wp-multi'));
} else {
?>
<div class="wpm-table-wrap">
<table class="wpm-table">
<thead>
<tr>
<th><?php _e('ID', 'wp-multi'); ?></th>
<th><?php _e('IP-Adresse', 'wp-multi'); ?></th>
<th><?php _e('Versuche', 'wp-multi'); ?></th>
<th><?php _e('Letzter Versuch', 'wp-multi'); ?></th>
<th><?php _e('Aktionen', 'wp-multi'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($blocked_ips as $ip) : ?>
<tr>
<td><?php echo esc_html($ip->id); ?></td>
<td><?php echo esc_html($ip->ip); ?></td>
<td><span class="wpm-badge <?php echo $ip->attempts >= 5 ? 'wpm-badge--danger' : 'wpm-badge--warning'; ?>"><?php echo esc_html($ip->attempts); ?></span></td>
<td><?php echo esc_html($ip->last_attempt); ?></td>
<td>
<a class="wpm-btn wpm-btn--danger" href="<?php echo esc_url(wp_nonce_url(admin_url('admin-post.php?action=remove_blocked_ip&id=' . $ip->id), 'wp_multi_remove_blocked_ip_' . $ip->id)); ?>">
<?php _e('Entfernen', 'wp-multi'); ?>
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php if ($total_pages > 1) : ?>
<div class="tablenav">
<div class="tablenav-pages">
<?php
echo paginate_links(array(
'base' => add_query_arg('paged', '%#%'),
'format' => '',
'prev_text' => __('«'),
'next_text' => __('»'),
'total' => $total_pages,
'current' => $page,
));
?>
</div>
</div>
<?php endif; ?>
<?php
}
wpmt_admin_card_close();
// Aufräumen: alte Einträge mit wenigen Versuchen entfernen
$three_days_ago = date('Y-m-d H:i:s', strtotime('-3 days'));
$wpdb->query(
$wpdb->prepare(
"DELETE FROM $table_name WHERE attempts < 10 AND last_attempt < %s",
$three_days_ago
)
);
wpmt_admin_page_close();
}
// Funktion zum Entfernen einer blockierten IP
function wp_multi_remove_blocked_ip() {
if (!current_user_can('manage_options')) {
wp_die(__('Du hast nicht die erforderlichen Berechtigungen.', 'wp-multi'), '', array('response' => 403));
}
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
if (!$id || !isset($_GET['_wpnonce']) || !wp_verify_nonce(wp_unslash($_GET['_wpnonce']), 'wp_multi_remove_blocked_ip_' . $id)) {
wp_die(__('Ungültige oder abgelaufene Anfrage.', 'wp-multi'), '', array('response' => 403));
}
global $wpdb;
if ($id > 0) {
$table_name = $wpdb->prefix . 'blocked_ips';
$wpdb->delete($table_name, array('id' => $id), array('%d'));
}
wp_safe_redirect(admin_url('admin.php?page=wp_multi_blocked_ips'));
exit;
}
add_action('admin_post_remove_blocked_ip', 'wp_multi_remove_blocked_ip');