log.php: neue, token-geschuetzte Ansicht fuer das Angriffsprotokoll hinzugefuegt
This commit is contained in:
@@ -0,0 +1,96 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eigenständige, schlanke Protokoll-Ansicht für abgelehnte Anfragen (Angriffsprotokoll).
|
||||||
|
*
|
||||||
|
* Bewusst OHNE Einbindung des JTL-Shop-Bootstraps: diese Datei liegt im öffentlich erreichbaren
|
||||||
|
* Plugin-Verzeichnis (genau wie assets/fp-altcha.js) und wird direkt vom Webserver ausgeführt,
|
||||||
|
* nicht über die Shop-Routen. Der Zugriff wird stattdessen über einen eigenen, zufällig
|
||||||
|
* erzeugten Zugriffsschlüssel abgesichert (siehe data/fp_altcha_log_token.php, automatisch
|
||||||
|
* erzeugt nach demselben Muster wie der HMAC-Geheimschlüssel in src/Service/AltchaService.php).
|
||||||
|
*
|
||||||
|
* Aufruf: https://ihre-domain/plugins/fp_altcha_spamschutz/log.php?key=<Zugriffsschluessel>
|
||||||
|
*
|
||||||
|
* Den aktuellen Zugriffsschlüssel finden Sie in der Datei data/fp_altcha_log_token.php im
|
||||||
|
* Plugin-Verzeichnis (einmalig per FTP/Datei-Manager auslesen). Die Datei wird automatisch
|
||||||
|
* angelegt, sobald das Angriffsprotokoll in den Plugin-Einstellungen aktiviert ist.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$dataDir = __DIR__ . '/data';
|
||||||
|
$tokenFile = $dataDir . '/fp_altcha_log_token.php';
|
||||||
|
$logFile = $dataDir . '/fp_altcha_attacklog.jsonl';
|
||||||
|
|
||||||
|
$expectedToken = \is_file($tokenFile) ? @include $tokenFile : null;
|
||||||
|
$providedToken = isset($_GET['key']) && \is_string($_GET['key']) ? $_GET['key'] : '';
|
||||||
|
$tokenIsValid = \is_string($expectedToken)
|
||||||
|
&& $expectedToken !== ''
|
||||||
|
&& $providedToken !== ''
|
||||||
|
&& \hash_equals($expectedToken, $providedToken);
|
||||||
|
|
||||||
|
if (!$tokenIsValid) {
|
||||||
|
\http_response_code(404);
|
||||||
|
echo 'Not found';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
\header('Content-Type: text/html; charset=UTF-8');
|
||||||
|
\header('X-Robots-Tag: noindex, nofollow');
|
||||||
|
|
||||||
|
$entries = [];
|
||||||
|
if (\is_file($logFile)) {
|
||||||
|
$lines = @\file($logFile, \FILE_IGNORE_NEW_LINES | \FILE_SKIP_EMPTY_LINES) ?: [];
|
||||||
|
foreach (\array_reverse($lines) as $line) {
|
||||||
|
$decoded = \json_decode($line, true);
|
||||||
|
if (\is_array($decoded)) {
|
||||||
|
$entries[] = $decoded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$anzahl = \count($entries);
|
||||||
|
|
||||||
|
echo '<!DOCTYPE html><html lang="de"><head><meta charset="UTF-8">'
|
||||||
|
. '<title>fp_altcha_spamschutz – Angriffsprotokoll</title>'
|
||||||
|
. '<style>'
|
||||||
|
. 'body{font-family:sans-serif;margin:2rem;background:#f7f7f7;color:#222;}'
|
||||||
|
. 'h1{font-size:1.2rem;}'
|
||||||
|
. 'table{border-collapse:collapse;width:100%;background:#fff;}'
|
||||||
|
. 'th,td{border:1px solid #ddd;padding:.4rem .6rem;font-size:.9rem;text-align:left;}'
|
||||||
|
. 'th{background:#eee;}'
|
||||||
|
. '.ja{color:#a30000;font-weight:bold;}'
|
||||||
|
. '.nein{color:#2a7d2a;}'
|
||||||
|
. '</style></head><body>';
|
||||||
|
|
||||||
|
echo '<h1>fp_altcha_spamschutz – Angriffsprotokoll ('
|
||||||
|
. $anzahl . ' Einträge, neueste zuerst)</h1>';
|
||||||
|
|
||||||
|
if ($anzahl === 0) {
|
||||||
|
echo '<p>Noch keine abgelehnten Anfragen protokolliert.</p>';
|
||||||
|
} else {
|
||||||
|
echo '<table><tr><th>Zeit</th><th>Formular</th><th>IP</th><th>Sicherheitsprüfung</th>'
|
||||||
|
. '<th>Namensmuster</th><th>Honeypot</th></tr>';
|
||||||
|
|
||||||
|
foreach ($entries as $entry) {
|
||||||
|
$zeit = \htmlspecialchars((string) ($entry['zeit'] ?? ''), \ENT_QUOTES, 'UTF-8');
|
||||||
|
$formular = \htmlspecialchars((string) ($entry['formular'] ?? ''), \ENT_QUOTES, 'UTF-8');
|
||||||
|
$ip = \htmlspecialchars((string) ($entry['ip'] ?? ''), \ENT_QUOTES, 'UTF-8');
|
||||||
|
$pruefung = \htmlspecialchars((string) ($entry['sicherheitspruefung'] ?? ''), \ENT_QUOTES, 'UTF-8');
|
||||||
|
$muster = !empty($entry['namensmuster']) ? '<span class="ja">ja</span>' : '<span class="nein">nein</span>';
|
||||||
|
$honeypot = !empty($entry['honeypot']) ? '<span class="ja">ja</span>' : '<span class="nein">nein</span>';
|
||||||
|
|
||||||
|
echo '<tr>'
|
||||||
|
. '<td>' . $zeit . '</td>'
|
||||||
|
. '<td>' . $formular . '</td>'
|
||||||
|
. '<td>' . $ip . '</td>'
|
||||||
|
. '<td>' . $pruefung . '</td>'
|
||||||
|
. '<td>' . $muster . '</td>'
|
||||||
|
. '<td>' . $honeypot . '</td>'
|
||||||
|
. '</tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '</table>';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '</body></html>';
|
||||||
Reference in New Issue
Block a user