Als Betreiber einer Webseite kümmerst du dich erstaunlich selten um das, was du eigentlich machen wolltest. Du wolltest Technik testen und darüber schreiben. Stattdessen sitzt du an einem Samstagabend vor einem Logfile und versuchst herauszufinden, warum deine eigene Seite dich nicht mehr reinlässt.
Genau das ist mir letzte Woche passiert. Und weil das Ganze am Ende eine ziemlich lehrreiche Kette aus drei Symptomen, einem Fehlalarm und einer Sicherheitsfunktion war, die ihr Ziel deutlich verfehlt hat, schreibe ich es hier auf.
Kurz vorweg: Betroffen war nicht nur ich, sondern auch etliche von euch. Ohne dass ich es gemerkt habe.
Symptom 1: Die Produktbilder waren weg
Angefangen hat es harmlos. In meinen Produktboxen, also den kleinen Kästen mit Bild, Preis und Amazon-Link, wurde plötzlich kein Produktbild mehr angezeigt. Nur noch das kaputte Bild-Symbol des Browsers.
Alles andere in der Box funktionierte weiterhin: Titel, Preis, Link. Nur das Bild fehlte.
Warum ich Produktbilder nicht direkt von Amazon lade
Normalerweise funktioniert das bei Affiliate-Seiten so, du bindest das Produktbild direkt von Amazons Servern ein. Ein <img>-Tag, das auf m.media-amazon.com zeigt, fertig. Das ist der Standardweg, den auch die offizielle Amazon-Schnittstelle vorsieht.
Nur hat dieser Weg einen Haken.
Wenn dein Browser ein Bild von Amazon lädt, dann baut dein Browser eine Verbindung zu Amazon auf. Nicht mein Server. Das heißt, Amazon erfährt deine IP-Adresse, deinen Browser, dein Betriebssystem und die Seite, von der du kommst. Und das passiert automatisch, in dem Moment, in dem die Seite lädt. Ohne dass du irgendwo geklickt hättest.
Und da fängt es an, mir gegen den Strich zu gehen. Auf Techtest gibt es kein AdSense, keine Werbenetzwerke, kein Tracking (Dank Dell Technologies).
Die Lösung ist ein sogenannter Bild-Proxy. Der funktioniert so:
- Dein Browser fragt das Bild bei techtest.org an, nicht bei Amazon
- Mein Server holt das Bild bei Amazon ab
- Mein Server liefert es an dich aus
Amazon sieht dabei nur die IP-Adresse meines Servers. Für dich sieht das Bild aus wie jedes andere Bild auf der Seite.
Für die Produktboxen nutze ich das Plugin AAWP, und das bringt genauso einen Datenschutz-Proxy von Haus aus mit. Technisch übernimmt die Arbeit eine kleine PHP-Datei namens image.php im Plugin-Verzeichnis. Genau die war das Problem.
Symptom 2: Die Seite war plötzlich komplett tot
Parallel zu den kaputten Bildern fiel mir noch etwas auf, das ich zunächst für ein völlig separates Problem hielt.
Wenn ich mich durch mehrere Artikel klickte, war Techtest irgendwann schlicht nicht mehr erreichbar:
Die Website ist nicht erreichbar
Die Antwort von techtest.org hat zu lange gedauert.
ERR_CONNECTION_TIMED_OUT
Keine Fehlermeldung, keine 403-Seite, nichts. Einfach Stille. Nach ungefähr zehn Minuten ging es wieder.
Es betraf alle Geräte in meinem Netzwerk. PC, Notebook, Tablet. Über Mobilfunk am Handy lief die Seite dagegen völlig normal.
Das war der entscheidende Hinweis. Wenn alle Geräte an einem Anschluss betroffen sind, aber Mobilfunk funktioniert, dann ist nicht die Seite kaputt, sondern die IP-Adresse ist gesperrt. Und zwar auf Firewall-Ebene, denn sonst käme eine Fehlerseite zurück und kein Timeout.
Die Spurensuche im Logfile
Mein Server läuft unter Plesk, und dort ist standardmäßig Fail2Ban aktiv. Das ist ein Standardwerkzeug, das Logdateien mitliest und IP-Adressen sperrt, die sich verdächtig verhalten.
Gedacht ist es gegen Brute-Force-Angriffe auf Login-Formulare, gegen Schwachstellen-Scanner und Ähnliches. Plesk bringt dafür fertige Regelsätze mit, sogenannte Jails.
Ein Blick ins Log war ernüchternd:
17:10:44 [plesk-apache] Found 87.78.x.x
17:32:15 [plesk-apache] Found 87.78.x.x
17:35:31 [plesk-apache] Found 87.78.x.x
17:39:08 [plesk-apache] Found 87.78.x.x
17:39:37 [plesk-apache] Found 87.78.x.x
17:40:19 [plesk-apache] Found 87.78.x.x
17:41:40 [plesk-apache] Found 87.78.x.x
17:41:40 [plesk-apache] Ban 87.78.x.x
17:51:40 [plesk-apache] Unban 87.78.x.x
Da stand meine eigene IP. Gesperrt um 17:41 Uhr, freigegeben um 17:51 Uhr. Exakt zehn Minuten, das ist die Standardeinstellung.
Der Zusammenhang, den ich zunächst übersehen hatte
Die zuständige Jail heißt plesk-apache und wertet das Fehlerprotokoll von Apache aus. Und dort stand, sauber im Sekundentakt, immer dieselbe Zeile:
AH01630: client denied by server configuration:
/var/www/vhosts/techtest.org/httpdocs/wp-content/plugins/aawp/public/image.php
- Jeder Artikel mit Produktbox ruft die image.php auf
- Der Zugriff darauf wird verweigert, deshalb die kaputten Bilder
- Jede Verweigerung schreibt eine Fehlermeldung ins Protokoll
- Fail2Ban zählt diese Fehlermeldungen und hält sie für einen Angriff
- Nach sechs Artikelseiten innerhalb von zehn Minuten ist Schluss
Wer sich also für meine Tests interessiert und mehrere hintereinander liest, also genau der Leser, den man sich als Betreiber wünscht, wurde von meinem eigenen Server vor die Tür gesetzt.
Der Schuldige: ein Fehlalarm
Blieb die Frage, warum der Zugriff auf die image.php überhaupt verweigert wurde. Fündig wurde ich in einer .htaccess direkt im Ordner wp-content/plugins/aawp/public/:
<FilesMatch „image.php“>
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
</FilesMatch>
AAWP legt an dieser Stelle selbst eine .htaccess an, allerdings mit dem gegenteiligen Zweck. Sie soll den Zugriff sicherstellen. Hier hatte jemand anderes das Ruder übernommen und aus der Freigabe eine Sperre gemacht. Sehr wahrscheinlich ein Sicherheits-Scanner (was genau die Änderung vollzogen hat, kann ich nicht sagen).
Folgender Code ist das „Problem“:
$url = base64_decode( $encoded_image_url );
…
readfile( $url );
Nimm einen Parameter aus der URL, dekodiere ihn und lies dann die Datei, die dabei herauskommt. Das ist das Standardmuster einer Webshell, also einer Hintertür, über die Angreifer beliebige Dateien vom Server abgreifen. Nach genau diesem Muster suchen Malware-Scanner.
Was der Scanner nicht sieht sind die zwanzig Zeilen darüber. Dort prüft das Plugin die dekodierte Adresse gegen eine feste Positivliste. Erlaubt sind ausschließlich Amazons Bildserver, ausschließlich der Bilderpfad, ausschließlich die Endungen .jpg, .jpeg und .png. Dazu kommt ein Ablaufzeitstempel, damit einmal erzeugte Links nicht ewig gültig bleiben.
Die Datei ist also sauber abgesichert. Sie sieht nur für einen automatisierten Scanner aus wie eine Hintertür.
Was das für euch bedeutet hat
An dieser Stelle wurde es für mich unangenehm. Ich habe das komplette Fail2Ban-Protokoll einer Woche ausgewertet, nicht nur meine eigene IP…

Es wurden hunderte IP Adressen(Temporär) gesperrt wegen diesem Problem.
Das waren keine Angreifer. Das waren Leser, die zu schnell Seiten mit Produktboxen aufgerufen haben. Autsch.
Die Lösung
Am Ende war es eine Handvoll Zeilen in einer .htaccess. Aus denied wurde granted:
<FilesMatch „image\.php“>
<IfModule mod_authz_core.c>
Require all granted
</IfModule>
</FilesMatch>
Bilder waren sofort wieder da.
Falls du dasselbe Problem hast, ruf die Datei einfach direkt im Browser auf, also deine-domain.de/wp-content/plugins/aawp/public/image.php. Kommt ein 403, ist es dieselbe Geschichte. Kommt eine leere weiße Seite, ist alles in Ordnung und du musst woanders suchen.
Fazit
Solltest du in den letzten Wochen einmal vor einem Timeout auf Techtest gestanden haben…. Das war meine Schuld. Sorry dafür. Ich hätte dem Problem früher nachgehen sollen.







