Alle Datenbanken auslesen und die Anzahl der Veränderungen per Email senden

Hallo ihr Lieben,

ich kenne mich passabel mit SQL und php aus und möchte jetzt gerne etwas realisieren, was mich irgendwie überfordert :wink:
Dabei bin ich sicher, dass es eine supereinfache Lösung dazu gibt.

Ich möchte mir gerne per Cronjob jeden Abend die Veränderungen an meinen SQL-Tabellen anzeigen lassen. Und zwar nur die, die sich verändert haben und das aber von allen Datensätzen aller Tabellen aller Datenbanken.
Das heisst, im Idealfall möchte ich eine Email bekommen, in welcher dann steht:
li_web.kunden: +3 
sa_forum.comments: -1
sa_forum.entry: -1
usw.

Hat jemand eine brilliante Idee dazu?
Ich vermute ja, dass es Sinn macht immer den jeweiligen Zwischenstand in eine separate Tabelle zu schreiben, damit man dann am Abend immer Vergleichen kann.
Und mir ist klar, dass im einfachsten Ansatz sich z.B. eine Löschung und ein Neueintrag sich aufheben würden, aber das wäre nicht so schlimm. Falls aber jemand diesbezüglich eine Idee hat, wäre das super. Falls es z.B. auch möglich wäre, dass der Report dann so aussieht:
li_web.kunden: +3 (Gelöscht: - / Neu: Id 5,73,120)
sa_forum.comments: -1 (Gelöscht: Id 54 / Neu: -)
sa_forum.entry: -1 (Gelöscht: Id 17,28 / Neu: Id 55)

Am letzten Punkt sieht man, was ich meine: Einer neu, zwei gelöscht = -1

Alles Liebe,
Dirk.

Hallo Dirk,

nachdem Du von Cronjob redest, gehe ich mal davon aus, dass du mit MySQL arbeitest. Bin da zwar nicht der Spezalist (eher MS SQL) aber von der Grundsache sollte das keinen Unterschied machen.
Wenn Du nur geänderte Datensätze erfassen willst, dann kannst Du in jede Tabelle eine Spalte „Changed [date]“ einfügst, und diese per Trigger After Update das aktuelle Datum einträgst. Dann kannst Du über diese Spalte selektieren und hast alle geänderten DS eines Datums.
Wenn Du auch gelöschte DS erfassen willst, dann musst Du diese wohl wirklich per Trigger in eine zweite Tabelle kopieren. Alternativ kannst du aber auch diese Datensätze in Deiner Tabelle belassen, eine Spalte „Deleted“ einfügen und diese Datensätze entsprechend markieren. Musst dann aber in deiner Applikation das auch entsprechend berücksichtigen.
Hoffe ich konnte Dir ein paar Tipps für die Struktur geben, die Dir weiter helfen.

Gruß
Michael

Hi,

Vorab, mein Vorschlag ist nur eine spontane Idee und müsste vielleicht noch zu ende gedacht werden.

Du könntest Mysql-Trigger-Events einsetzen, d.h du erstellst dir eine Tabelle „action“ oder so und setzt für alle Tabellen die du „geloggt“ haben möchtest einen After-Trigger (für Delete,Insert und Update) Bsp. dazu:

USE `deine DB`;
DELIMITER $$
CREATE DEFINER=`deinusername`@`deinhost` TRIGGER `eineTabelle_AUPD` AFTER UPDATE ON `eineTabelle` 
 FOR EACH ROW
 BEGIN
 INSERT INTO action SET wert1 = NEW.wert1, wert2 = NEW.wert2, wert3 = NEW.wert3;
 END

Dieses Beispiel wirft ein Event nachdem ein „Update“ auf „eineTabelle“ und schreibt die Werte in die Tabelle „action“. Das „_AUPD“ am Ende des Namenstrigger musst du nicht so nennen…ich mache das damit ich weiss anhand des Names was der Trigger macht (A=AFTER, UP=Update, D=Database)

Ich möchte mir gerne per Cronjob jeden Abend die Veränderungen
an meinen SQL-Tabellen anzeigen lassen. Und zwar nur die, die
sich verändert haben und das aber von allen Datensätzen aller
Tabellen aller Datenbanken.
Das heisst, im Idealfall möchte ich eine Email bekommen, in
welcher dann steht:
li_web.kunden: +3 
sa_forum.comments: -1
sa_forum.entry: -1
usw.

Jetzt bräuchtest du nur noch per cron-job auslesen und in schön formatierter Form, dir einmal am Tag die Tabelle „action“, zusenden lassen.

Gruß XXD

Guter Tip mit den Triggern - kannte ich noch gar nicht.
Das Problem ist jedoch, dass ich dann für JEDEN Table einen separaten Trigger erstellen müsste - das ist bei 20 Datenbanken mit je zwischen 20 und 40 Tabellen allerdings eher umständlich.
Mir geht es auch vor allem und eigentlich nur darum, dass ich gelöschte und hinzugefügte Einträge protokolliere.
(MySQL, übrigens)
Hintergrund: Ich habe einen Hacker, der mir ständig vermutlich über SQL-injections die Datenbanken punktuell zerschießt. Ich suche schon verzweifelt die Nadel im Heuhaufen und bis ich die finde brauche ich eine Info, ob wieder Datensätze gelöscht wurden, und wenn ja, welche. Verdammter Mist ist das :frowning:
Gibt es denn eine einfach Möglichkeit, die einfach z.B. per php in ALLEN bestehenden Datenbanken (ohne, dass ich sie definieren müsste) ALLE Löschungen und Hinzufügungen erfasst, ein Abbild erstellt und jeden Abend die Unterschiede erfasst und losschickt?
Hmm, klingt jetzt immer komplizierter, je länger ich darüber nachdenke…

Mir geht es auch vor allem und eigentlich nur darum, dass ich
gelöschte und hinzugefügte Einträge protokolliere.
(MySQL, übrigens)
Hintergrund: Ich habe einen Hacker, der mir ständig vermutlich
über SQL-injections die Datenbanken punktuell zerschießt. Ich
suche schon verzweifelt die Nadel im Heuhaufen und bis ich die
finde brauche ich eine Info, ob wieder Datensätze gelöscht
wurden, und wenn ja, welche. Verdammter Mist ist das :frowning:
Gibt es denn eine einfach Möglichkeit, die einfach z.B. per
php in ALLEN bestehenden Datenbanken (ohne, dass ich sie
definieren müsste) ALLE Löschungen und Hinzufügungen erfasst,
ein Abbild erstellt und jeden Abend die Unterschiede erfasst
und losschickt?
Hmm, klingt jetzt immer komplizierter, je länger ich darüber
nachdenke…

Exakt! so was in php zu realisieren ist weit mehr Arbeit als Trigger zu verwenden.

Zu den sql-Injections…da musst du halt alle sql-concat Strings finden und allgemein alles auf Prepared-Statements umbauen. In Eclipse kannst du alle PHP-Dateien nach einem Muster durchsuchen in den Suchergebnissen klickst du dich durch und korrigierst Schritt für Schritt den Quellcode.

Das andere wäre, du könntest dir ein Script schreiben, dass allen Tabellen einen Trigger hinzufügt im Prinzip ändert sich beim Trigger nur die Tabelle(Name) und der Triggername.

Also so was im Prinzip (dient nur zum Denkanstoss):

$dbs = array('db1','db2',...);
foreach($dbs as $db){
 query('USE ' . $db);
 $result = query('SHOW TABLES');
 foreach($result as $res){
 query('CREATE TRIGGER ' . $res . '\_AUPD AFTER UPDATE ON ' .$res. ' FOR EACH ROW BEGIN INSERT INTO action SET wert1=' . $res['wert1'] ...usw');
 }
} 

Jedoch würde ich meine Zeit, in das auffinden der Lücken, investieren.

Eine andere Möglichkeit, die jedoch im Produktivbetrieb nicht ratsam ist, du könntest in der my.ini alle Queries loggen aktivieren, doch sei dir bewusst dass die Datei (query.log) ganz schnell, verdammt groß werden kann. Die kannst du dir per cron-job -> Email schicken lassen und per grep filtern.

Gruß

Hintergrund: Ich habe einen Hacker, der mir ständig vermutlich
über SQL-injections die Datenbanken punktuell zerschießt. Ich
suche schon verzweifelt die Nadel im Heuhaufen und bis ich die
finde brauche ich eine Info, ob wieder Datensätze gelöscht
wurden, und wenn ja, welche.

Dein Ansatz ist der falsche. Du musst deine Anwendung sicher kriegen und nicht versuchen, die gelöschten Sachen immer wieder herzustellen.

Ich bin der Meinung, du solltest folgendermaßen vorgehen:

Zuerst lies und verstehe das hier: http://php.net/manual/de/security.database.php
Danach gehst du jedes einzelne SQL-Kommando in deiner Anwendung durch und wendest die Gegenmaßnahmen an.
Wenn die Anwendung nicht von dir ist, dann melde den Fehler unbedingt dem Entwickler der Software und lade dir ggf. die neueste Version herunter.

Nochmal ganz eindringlich: eine kompromittierte PHP-Anwendung ist gefährlich, da sie dem Besucher malware unterschieben oder aber andere Webseiten angreifen kann (DDOS) oder sonstwie gefährlichen/illegalen Unsinn macht.

Ich schliesse mich den oberen Meinungen - man muss einfach die „Lücke“ finden und schliessen. Vieles hängt davon ab, wie deine SQL-Queries erfolgen. Ich nehme an, du hast eine zentrale Klasse, die für Queries zuständig ist. Dann würde ich deren Funktionen erweitern, damit bei jedem Request (ausser SELECT) die komplette Query mit $_SERVER[‚REQUEST_URI‘], $_SERVER[‚REMOTE_ADDR‘], $_SERVER[‚HTTP_USER_AGENT‘] in eine extra angelegte Log-Tabelle mitgeschrieben werden. So erfährst du etwas mehr von deinem Angreifer und kannst ihm den Zugriff sperren. Sofort mit „exit“ antworten o.ä. Dann hast du erstmal Ruhe und kannst die Lücke suchen.

Danke an Alle erstmal. Ich werde mich direkt am Montag hinsetzen und die Umsetzung der Tips in Angriff nehmen.

Hallo Dirk,

Ich schlage mal einen völlig anderen Lösungsweg vor: Du könntest (z.B. per cron) jeden Tag die Datenbanken im SQL-Format exportieren, z.B. mit  mysqldump.
Dann kannst du mit einem diff-Tool deiner Wahl die Unterschiede zur Vortages-Version ermitteln. Das Diff zeigt dir genau an, wo Einträge hinzugekommen sind und wo welche weggefallen sind. (Allerdings auch geänderte Datensätze.)

Wenn das grundsätzlich funktioniert, könnte man dazu ein Shellskript anlegen, das die Arbeitsschritte automatisch ausführt und das Diff auch automatisch per Mail verschickt, wenn z.B. eine bestimmte Schwelle an Änderungen überschritten wird.

Beste Grüße
Stefan

Ah, cool. Das mache ich in jedem Fall parallel zur Hackersuche. Danke!

…bei der Lückensuche?