Um frühzeitig dahinter zu kommen, ob eine Spamwelle anrollt oder ein neuer Exploit ausgenutzt wird, ist es hilfreich, die Server-Logfiles zu Rate zu ziehen. Wenn auf einmal SQL-Statements oder Javascript-Code oder Verweise auf externe Scripte in Variablen-Werten auftauchen kann man davon ausgehen, dass da gerade jemand versucht, per SQL-Injection, XSS oder sonstwie das Blog zu cracken.
Im Falle von GET Variablen sieht man das noch ganz gut in den Standard-Server Logs, dagegen schweigen sich diese bei POST Variablen über den Inhalt derselben aus.
Will man also Einblick bekommen, mit welchen POST-Variablen das Blog so gefüttert wird, muss man selbst tätig werden. Dafür habe ich mir ein kleines Script gebastelt, das:
- Den Post-Request sowie ein paar Informationen, wo er herkommt und wo er hinsoll, in eine Datei schreibt
- Mir eine E-Mail mit diesen Informationen schickt
Angeregt wurde das ganze durch die Diskussion über die neuesten WordPress-Exploits bei village-idiot.org. Insbesondere der Ansatz, die Logging-Funktion in die wp-config.php einzubinden, fand ich dort - ich hatte es zunächst in die index.php eingebunden, die aber bei jedem Update aufs Neue geändert werden müsste. Da die wp-config.php in der Regel bei einem Update nicht geändert wird, überlebt die Logging-Funktion also auch künftige Updates.
Ich versuche das hier mal zu skizzieren. Benötigt werden Kenntnisse in PHP, ein Zugang zum Server, der das Ändern von Datei- und Verzeichnisrechten erlaubt und der Zugriff auf ein Verzeichnis ausserhalb der htroot (des Verzeichnisses, welches über das Internet per Browser erreichbar ist).
Das ist nichts für Anfänger!
Schritt 1: Die Log-Datei erzeugen
Auf dem Webserver, möglichst in einem Verzeichnis, das NICHT übers Web erreichbar ist, wird eine leere Datei erzeugt, die der Webserver beschreiben darf (bei mir funktioniert es mit den Dateirechten auf 644). Der Dateiname sollte nicht log.txt oder ähnlich lauten - vor allem nicht, wenn das Logfile in einem übers Web erreichbaren Verzeichnis liegt. In dem Logfile landen eventuell auch sensible Informationen. Wenn man einfach nur alle POST-Requests mitloggt, landen darin auch die Zugangsdaten zum Backend im Klartext. Was es bedeutet, diese in einer Datei, die übers Web erreichbar ist, vorzuhalten, brauche ich wohl nicht zu erklären. Ich sage nur: Ganz schlechte Idee.
Man sollte sich aber auch nicht darauf verlassen, dass die Datei in einem Verzeichnis ausserhalb der htroot sicher ist. Unsichere und/oder schlampig programmierte Scripte in einer anderen Installation auf dem gleichen Server können theoretisch auch den Zugriff auf solche "ausserhalb" liegenden Verzeichnisse ermöglichen. Also: Am Besten wäre, wenn die sensiblen Daten erst garnicht im Logfile auftauchen. Dazu später mehr.
Schritt 2: Datei mit der Logging-Funktion erzeugen
function logpost(mailme='0') { // $log_abspath = '/absoluter/pfad/zum/log/verzeichnis/'; $log_filename = 'der.logfile.name'; // $req = $_SERVER['REQUEST_METHOD']; $req_file = $_SERVER['SCRIPT_NAME']; $req_ip = $_SERVER['REMOTE_ADDR']; if ( $req == 'POST' ) { if ( strpos($req_file, 'wp-login') === false ) { $log = date('d.m.Y, H:i:s').':'; $log .= "\t".'Post-Request: '; foreach ($_POST as $key => $value) { $log .= $key.':'.$value.' '; } $log .= "\t".'Request-Time: '.strftime('%d.%m.%Y, %T',$_SERVER['REQUEST_TIME']); $log .= "\t".'Request-Uri: '.$_SERVER['REQUEST_URI']; $log .= "\t".'Remote-Adress: '.$req_ip; $log .= "\t".'User-Agent: '.$_SERVER['HTTP_USER_AGENT']; $log .= "\t".'File-Name: '.$req_file; $log .= "\n\n"; // logfile oeffnen und schreiben und schliessen: $handle = fopen($log_abspath.$log_filename,'a+'); fwrite($handle,$log); fclose($handle); // mailme? if(mailme == 'email') $mailheader = 'From: watchdog@deineblog.adresse'."\r\n".'X-Mailer: PHP/'.phpversion(); mail('deine@email.adresse','Blogname: POST-LOG',$log,$mailheader); } } } } |
So. In dem Script müssen die Zeilen mit den Pfadangaben und Mailadressen natürlich auf die eigene Konfiguration angepasst werden.
Die if-Abfrage if ( strpos($req_file, 'wp-login') === false ) { ... }
sorgt dafür, dass Anfragen an die wp-login.php nicht mitgeloggt werden, somit also keine Zugangsdaten in dem Log (oder der Email) auftauchen. Allerdings bekommt man so auch nicht mit, wenn die wp-login.php attackiert wird. Wer das auch mitbekommen möchte, muss diese Abfrage rausnehmen und sollte das Logfile zeitnah ansehen und leeren.
Das Script auf dem Webserver als .php Datei speichern und den Pfad merken, denn der wird im nächsten Schritt benötigt.
Schritt 3: Einbinden und Aktivieren in der wp-config.php
Am Ende der wp-config.php, vor dem schliessenden ?>
Tag, wird das Script per include() eingebunden und bei Bedarf mit dem Funktionsaufruf aktiviert. Dabei kann der Parameter "email" verwendet werdem um zu bestimmen, ob eine E-Mail versendet wird oder nicht:
(...) include('pfad/zur/scriptdatei/scriptname.php'); logpost('email'); // leer lassen, wenn keine e-mail erwuenscht: logpost(); |
Bitte darauf achten, dass in der wp-content.php keine Leerzeichen oder Zeilenumbrüche vor oder nach den <?php und ?> Tags stehen - ansonsten gibt es Fehler und Warnungen mit "blah blah Headers already sent".
Das Logfile sollte regelmässig gelesen und geleert werden. POST Parameter können sehr viel Daten enthalten und das Log so recht schnell ziemlich aufblasen. Ausserdem (siehe Kommentar) besteht die Gefahr, dass durch einen gezielten Angriff mit grossen POST Request-Daten das Log so aufgeblasen wird, dass die Speicherlimits vom Hostingvertrag überschritten werden, und man entweder die Website abgeklemmt bekommt oder nachzahlen darf!
Weitere Überlegungen, die in das obige Script noch nicht mit einbezogen sind:
- Man könnte sich die User und Passwortdaten verkürzt ausgeben lassen (PW****)
- Um ein Aufblasen der Log-Datei zu verhindern, könnte man die Werte der POST-Variablen mit strlen(); checken und bei Überschreiten einer bestimmten Länge verkürzt ausgeben.
Disclaimer
War ja klar, dass der kommt, nicht wahr? :-)
Also, ich übernehme keinerlei Haftung für das Script und eventuelle Schäden, die dadurch ausgelöst werden. Ich bin kein professioneller Programmierer und das Script ist lediglich in meiner Installation getestet. Auf die Gefahren die mir bewusst sind, habe ich im Beitrag hingewiesen, aber wahrscheinlich gibt es noch viel mehr, die mir nicht bewusst sind - ich denke es gibt einen guten Grund, warum POST requests nicht in den Standard-Serverlogs mitgeschrieben werden.
Wer sich unsicher ist, was das alles soll, sollte die Finger davon lassen. Alle anderen sollten das auch nicht ständig aktiviert lassen, sondern nur bedarfsweise, wenn man eben mal sehen möchte, was da so alles an das Blog herangetragen wird.
2 Reaktionen zu “DIY: Post-Requests mitloggen”
Vielleicht sollte man drauf hinweisen, dass man auf diese Art und Weise die Speichergrenzen von kleinen Shared-Hosting Verträgen relativ schnell erreichen/überschreiten kann, wenn wirklich ein Angriff erfolgen sollte. Ich könnte z.B. Dein Blog bzw. Deinen Hoster relativ schnell angreifen, jetzt wo ich weiss, dass Du sämtlich POST Parameter aauf diese Weise mitloggst. Ein Skript, dass viele, große POST Requests schickt ist schnell geschrieben und das dann ein paar tausend Mal hintereinander auszuführen ist ebenso kein großes Problem.
Ich bin mir sicher, dass Du das alles berücksichtigt hast, schließlich warnst Du ja auch eindringlich davor, dass ganze dauerhaft zu machen. Dachte nur, dass man das evtl. erwähnen sollte...
Hi Robert,
danke für den Hinweis. Das Logging läuft hier natürlich nicht die ganze Zeit. :-)
Ich werde Deinen Hinweis auf die Speichergrenzen im Post mit aufnehmen, das ist ein wichtiger Punkt.
Kommentare sind geschlossen.