[PHP/MySQL+Sicherheit] Datenbankklasse, Validierung von Eingaben, etc.

Drrichardfahrer

Well-known member
ID: 207405
L
20 April 2006
7.060
691
Ich bin auf der Suche nach einer ordentlichen Datenbankklasse, die wirklich gegen Injections sicher ist. Vielleicht wollen die geschätzten PHP-Profis hier mal ihre Klassen offenlegen bzw. Anregungen geben.

Auch interessiere ich mich für geeignete Überprüfungsfunktionen...ich habe bereits viel gelesen, weiß aber wirklich nicht, wie ich all die Überprüfungen entweder mittels eine Klasse oder mittels einer externen .php-File integrieren soll...

Vielleicht kann der/die eine odere andere mir dabei helfen - vl. können wir hier Codeschnippsel zusammentragen :)
 
noch schöner sind Prepared Statements, dann muss man nicht mehr andauernd selbst den Datentyp festlegen, welchen die Daten haben sollen :biggrin:
 
OK, das versteh ich jetzt und kann auch alle 4 Zeilen nachvollziehen.

Jetzt wurde nur noch meine Frage nicht wirklich beantwortet - wegen einer Datenbankklasse...Zend, POI, und wie sie alle heißen...damit hab ich (noch) wenig am Hut - gibts nicht eine einfache Datei, in der alle notwendigen Funktionen (dann auch noch gesichert) drinnenstehen??

Ich hab mir mal sowas gebastelt (ist aber sicherlich total unsicher und funktioniert auch nicht bei allen Query-Anfragen...):

PHP:
<?php

class MySQL {

function connect($host, $name, $pass, $db) {
  $connection = mysql_connect("$host","$name","$pass");
  mysql_select_db("$db", $connection);
}

function close() {
  mysql_close($this->connection);
}

function query($sql) {
  $sql = mysql_real_escape_string($sql);
  $query = mysql_query($sql) or die(mysql_error());
  return $query;
}

function fetch_row($query) {
  $rows = mysql_fetch_row($query);
  return $rows;
}

function fetch_array($query) {
  $array = mysql_fetch_array($query);
  return $array;
}

function num_rows($query) {
  $num_rows = mysql_num_rows($query);
  return $num_rows; 
}

}

?>

Aber sowas in der Art stelle ich mir vor :) Dann kann ich das einfach einbinden und mit

PHP:
$sql = "SELECT ... FROM ... WHERE ...=1";
$query = $db->query($sql);
$count = $db->num_rows($query);

abrufen...hat jemand sowas für mich? :)
 
neija wofür?
Deine Klasse hat 0 Vorteile gegenüber dem normalen Aufruf der ext/mysql-Funktionen.

Und dann sind solche Komponenten in Frameworks, eben auch nen bissi komplexer, da sie eben mehr zur Verfügung stellen als nur nen Wrapper um die MySQL-Funktionen.
 
Wieso ist man eigentlich zu faul mysql_real_escape_string() ständig einzugeben? Ich finde diese ganzen Klassen einfach scheisse. Und zwar aus folgendem Gründen:

1.) Will man eine solche Klasse oder Funktion nutzen muss man alle Querys neu schreiben bzw anpassen!
%S als Wert und weitere Parameter anfügen!
2.) Wird es in Zukunft eine Funktion geben die automatisch escapet, so müsste jeder Query extra wieder ins Normalformat gebracht werden.
3.) Man mus jeden Query den man in Tools testen will rebuilden und das kostet Zeit und somit Geld! Z.B. Wenn man mehrere SQL Anfragen testen will und diese jedes mal umschreiben muss in das Format der eigenen Klasse, nur um eben mal ein paar Dinge zu testen!

Klug wäre wirklich jeden Wert (gleich oder ungleich ob Sichherheitsrelevant) durch mysql_real..... durchzujagen. Und da die Schreibweise vermutlich zu lang ist um das dauernd zu tun nimmt man sich einen Zwischenbreak:

PHP:
<?
function mres($overgif)
{
	return mysql_real_escape_string($overgif);
}
?>

4. Ich kannm mir nicht vorstellen, dass diese Schreibweise:

PHP:
$res=mysql_queryf("SELECT `field` FROM `table` WHERE `userid`=%u AND `pw`='%s'",$_POST['userid'],$_POST['pw']);

Schneller einzugeben oder bequemer einzugeben wäre wie diese:
PHP:
$res=mysql_query("SELECT `field` FROM `table` WHERE `userid`= '".mres($_POST['userid'])."'AND `pw`='".mres($_POST['pw'])."'");


Vielleicht wird es in Zukunft noch was anderes geben wie mysql_real_escape_stringt so wie get_magic_quotes.... addslashes... etc abelöst wurde. Und dann steht man wieder da.


Ich will niemanden davon abraten sich eine Klasse oder ein Funktion zu bauen. Aber die simplere Weg ist das sicher nicht, nur Kurzfristig! Ich kann daher nur die Logik dieser Klassen nicht verstehen, außer das diese Code zum umschreiben komplizieren.

Eben so simpel und sicher geht es mit der normalen Schreibweise!

Diese Sicherheitslücken kommen durch das verzichten auf die Funktion mysql_real_escape_string und nicht durch das nutzen von mysql_query

Wer nicht escapet hat ein Problem.

Würden diese Klassen irgend etwas vereinfachen, hätte ich vollstes Verständnis dafür. Sie vereinfachen aber rein garnichts. Sie verkomplizieren die Strings eher!

Ich kann mir zum Beispiel im Zend durch 2 Tasenschläge und einem Enter (3 push) -> '".mres()."' einfügen lassen.

Um '%s' einzufügen brauche ich 4 Tastenpush! + das (,) für die Parameter! Wirklich schneller sind deshalb diese Klassen nicht. Aber sie zerabuen den ganzen String in seiner Schreibweise!



Kommen wir zu Punkt 5.)
Wenn man so ein Benchmark macht was das an Leistung kostet jedes Mal den String zusammenzusetzen, auseinander zunehmen und dann wieder zusammenzusetzen und ersetzen. Das ist ein weiterer Nachteil der mit so spontan kommt!


Ungeprüfte eingaben sollte es im Code so oder so nicht geben. Das ist an für sich schon ein Sicherheitsproblem für sich. Die sofortige Prüfung sollte nicht nur Pflicht sondern auch Gewohnheit sein!
 
Zuletzt bearbeitet:
Irgendwie kann ich dem in keinster Weise zustimmen :biggrin:



Wieso ist man eigentlich zu faul mysql_real_escape_string() ständig einzugeben?
weil es unnötige Schreibarbeit ist.

1.) Will man eine solche Klasse oder Funktion nutzen muss man alle Querys neu schreiben bzw anpassen!
%S als Wert und weitere Parameter anfügen!
na, wen dein Script bereits läuft und sicher ist, fordert ja niemand von dir es anzupassen.
Bei Neuentwicklungen kann man dann jedoch gleich dran denken.
Das gute daran ist ja, dass diese Sicherung als zusätzliche Option zur Verfügung gestellt wird, auch ohne diese läuft es.

2.) Wird es in Zukunft eine Funktion geben die automatisch escapet, so müsste jeder Query extra wieder ins Normalformat gebracht werden.
ist nicht möglich, versprochen.
Dazu musst du nachvollziehen was mit den Strings gemacht wird.
Denn wenn der String bei MySQL ankommt ist er bereits mit dem Input unsicher, und MySQL kann nicht erkennen was du meinst.

3.) Man mus jeden Query den man in Tools testen will rebuilden und das kostet Zeit und somit Geld! Z.B. Wenn man mehrere SQL Anfragen testen will und diese jedes mal umschreiben muss in das Format der eigenen Klasse, nur um eben mal ein paar Dinge zu testen!
ääh, dafür unterstützen gute Frameworks so genannte Profiler

4. Ich kannm mir nicht vorstellen, dass diese Schreibweise:

PHP:
$res=mysql_queryf("SELECT `field` FROM `table` WHERE `userid`=%u AND `pw`='%s'",$_POST['userid'],$_POST['pw']);

Schneller einzugeben oder bequemer einzugeben wäre wie diese:
PHP:
$res=mysql_query("SELECT `field` FROM `table` WHERE `userid`= '".mres($_POST['userid'])."'AND `pw`='".mres($_POST['pw'])."'");
na, aber dein Code ist aber sehr unübersichtlich wenn mal mehr variablen kommen, was hälst du hiervon:
PHP:
$res = $this->_db->fetchAll("SELECT field FROM table WHERE userid = ? AND pw = ?", $_POST['userid'], $_POST['pw']);
man hat einen Syntaktisch funktionieren Query im String (Prepared Statement) und trotzdem gut alles getrennt von den dynamischen Variablen.

Vielleicht wird es in Zukunft noch was anderes geben wie mysql_real_escape_stringt so wie get_magic_quotes.... addslashes... etc abelöst wurde. Und dann steht man wieder da.
du scheinst hier aber einiges zu verwechseln.
addslashes wurde nie abgelöst, das hatte nur den Sinn für magic_quotes.
Für Dbs wars auch nie gedacht, nur mysql_(real_)escape_string.
Und geändert wird da nix mehr, ext/mysql ist fertig. An dem "Mist" macht niemand mehr was, wer das noch nutzt, neija (bis auf die mysqlnd-Implementierung in PHP5.3 passiert da nix mehr)
Man muss sich vllt mal PDO ansehen.


Ich will niemanden davon abraten sich eine Klasse oder ein Funktion zu bauen. Aber die simplere Weg ist das sicher nicht, nur Kurzfristig! Ich kann daher nur die Logik dieser Klassen nicht verstehen, außer das diese Code zum umschreiben komplizieren.
jup klar, OOP macht null Sinn. :roll:

Diese Sicherheitslücken kommen durch das verzichten auf die Funktion mysql_real_escape_string und nicht durch das nutzen von mysql_query
ja, und wenn du einmal dein escaping vergisst, ist deine ansonsten vllt total toll abgesicherte Anwendung nutzlos.
Mit meiner Methode die ich oben vorgestellt habe, wird automatisch alles escaped, also sofern du die Funktion auch nutzt ist sie zu 100% sicher.


Würden diese Klassen irgend etwas vereinfachen, hätte ich vollstes Verständnis dafür. Sie vereinfachen aber rein garnichts. Sie verkomplizieren die Strings eher!
ooooooooooh doch. wiedermal scheinbar nicht richtig geschaut.
Mach mal mit deinem hardcoded Query deine Anwendung möglichst DB-unabhängig. supi, wenn du keine Objekte nutzt und direkt die mysql-Funktionen aufrufst.
und macht mal nen insert, ich nenne dir ne Methode die einfacher ist:
PHP:
$spalten = array('spalte1', 'spalte2');
$werte = array('wert1', 'wert2');
$this->_db->insert('table', $spalten, $werte)
es gibt noch Unmengen anderer Dinge, die solch ein Framework einem an Arbeit abnehmen.

Kommen wir zu Punkt 5.)
Wenn man so ein Benchmark macht was das an Leistung kostet jedes Mal den String zusammenzusetzen, auseinander zunehmen und dann wieder zusammenzusetzen und ersetzen. Das ist ein weiterer Nachteil der mit so spontan kommt!
ach sch***, wie ich dieses Argument hasse.
Weisst du wieviel kack-Querys deine Anwendung hat, die nicht optimal von MySQL ausgeführt werden können und stattdessen besser geschrieben werden können.
Der Performancenachteil liegt ja wohl im Millisekundenbereich, dieses Argument ist das letzte, es gibt Unmengen andere Punkte wo man hundertmal soviel Leistung rausholen kann (Autoloading usw)
 
Du hast meinen Abend gerettet. Sorry, aber: :biggrin:

Wieso ist man eigentlich zu faul mysql_real_escape_string() ständig einzugeben?
Eine ganze Menge Code-Overhead, Unübersichtlichkeit, die Gefahr, es zu vergessen. Schonmal daran gedacht?

Ich finde diese ganzen Klassen einfach scheisse. Und zwar aus folgendem Gründen:
Ja, gehen wir zurück zur prozeduralen Programmierung, die ja erst seit - moment mal - seit 30 Jahren als überholt gilt. Hm, warum nur :think:
Aber egal, Klassen sind scheiße.

Herzlich willkommen im Steinzeitalter der Programmierung. 8)

1.) Will man eine solche Klasse oder Funktion nutzen muss man alle Querys neu schreiben bzw anpassen!
%S als Wert und weitere Parameter anfügen!
Schreibt man das Skript direkt ordentlich, dann braucht man gar nichts ändern. Ist das Skript nicht bereits zumindest mit einer solchen Funktion versehen, und man reflektiert das darauf, wie vermutlich auch der Rest des Codes aussieht, sollte man vielleicht besser direkt neu anfangen.

2.) Wird es in Zukunft eine Funktion geben die automatisch escapet, so müsste jeder Query extra wieder ins Normalformat gebracht werden.
Wenn Computer ihren Strom zukünftig aus elektromagnetischen Wellen beziehen, braucht man kein Netzteil mehr, und muss es ausbauen. Also lassen wir das Netzteil besser direkt weg. Und wenn ich bedenke, dass die Autos vielleicht zukünftig ohne Bremsen anhalten können ...... 8O :biggrin:

3.) Man mus jeden Query den man in Tools testen will rebuilden und das kostet Zeit und somit Geld! Z.B. Wenn man mehrere SQL Anfragen testen will und diese jedes mal umschreiben muss in das Format der eigenen Klasse, nur um eben mal ein paar Dinge zu testen!
FirePHP oder ein vergleichbares Tool nehmen, die SQL Querys kopieren, und debuggen.
Schönen Gruß an Tobi *pfeif*

Klug wäre wirklich jeden Wert (gleich oder ungleich ob Sichherheitsrelevant) durch mysql_real..... durchzujagen. Und da die Schreibweise vermutlich zu lang ist um das dauernd zu tun nimmt man sich einen Zwischenbreak:
Bin ich auch dafür. Wir escapen die integralen Werte, prüfen sie aber besser nicht auf Format und Datentyp. :wall:

4. Ich kannm mir nicht vorstellen, dass diese Schreibweise:

PHP:
$res=mysql_queryf("SELECT `field` FROM `table` WHERE `userid`=%u AND `pw`='%s'",$_POST['userid'],$_POST['pw']);
Schneller einzugeben oder bequemer einzugeben wäre wie diese:
PHP:
$res=mysql_query("SELECT `field` FROM `table` WHERE `userid`= '".mres($_POST['userid'])."'AND `pw`='".mres($_POST['pw'])."'");
Ich schon. Bequemer definitiv - vor allem zu lesen.
Stringvergleiche bei User-IDs tun übrigens auch nicht unbedingt gut, und sind nebenbei bemerkt ein schwerer Formatfehler. Hat MySQL nicht auch eine Art strict-Mode, oder täusch ich mich grad ... ? :roll:

Vielleicht wird es in Zukunft noch was anderes geben wie mysql_real_escape_stringt so wie get_magic_quotes.... addslashes... etc abelöst wurde. Und dann steht man wieder da.
They call it PDO. The future has reached our world.

Eben so simpel und sicher geht es mit der normalen Schreibweise!
Simpel? Nein.
Sicher? Ja. Bis dann mal jemand die Ticks vor und nach einem integralen Feld vergisst, oder den MySQL Strict-Mode einschaltet, und, huch, plötzlich geht nichts mehr.

Diese Sicherheitslücken kommen durch das verzichten auf die Funktion mysql_real_escape_string und nicht durch das nutzen von mysql_query
Prinzipiell durchaus richtig - als erste Aussage überhaupt in diesem Post. Zumindest, wenn man nur von Stringvergleichen ausgeht.

Wer nicht escapet hat ein Problem.
Wer integrale Werte in einen Stringvergleich packt, auch.

Würden diese Klassen irgend etwas vereinfachen, hätte ich vollstes Verständnis dafür. Sie vereinfachen aber rein garnichts. Sie verkomplizieren die Strings eher!
Klar. Ein Query, der einfach nur hier und da ein %[a-z] (oder im Zend-Framework: ?) stehen hat, ist deutlich schwerer zu lesen, als ein Query mit lauter mysql_real_escape_string()-Monstern. Ich glaub's auch. :yawn:

Ich kann mir zum Beispiel im Zend durch 2 Tasenschläge und einem Enter (3 push) -> '".mres()."' einfügen lassen.
Ich kann darauf ganz verzichten, weil ich für mein %[a-z] auch nur zwei Tastenanschläge, beim ZF sogar nur einen Tastenanschlag brauche.

Kommen wir zu Punkt 5.)
Wenn man so ein Benchmark macht was das an Leistung kostet jedes Mal den String zusammenzusetzen, auseinander zunehmen und dann wieder zusammenzusetzen und ersetzen. Das ist ein weiterer Nachteil der mit so spontan kommt!
Och bitte. :roll:
Wenn ich mir angucke, wielange der Parser brauchen wird, um dein Gezwirbel da zu lesen, dann sollte das mindestens genau so lange dauern. Und selbst wenn nicht: Mit einem gescheiten Bytecode-Cache lässt sich die Millisekunde grad noch so ertragen. Der Ping von hier zu meinem Server dauert übrigens rund 20ms. Nur mal so nebenbei.

Sorry für meinen Sarkasmus, aber bei so nem Post kann ich mir ja nur noch an den Kopf packen.
 
Wir haben mit sicherheit alle irgendwelche Db Klassen, aber ich habe an meiner DB Klasse mit treiber unterstützung 3 Tage gebastelt. Sie ist noch nicht perfekt aber Sie taugt, nur erklär mir mal warum hier einer Dir die Klassen so geben soll. Wo ist das der Lerneffekt den wir hier im Programmierforum erzielen wollen.

Kleiner Tip wenn Du ne Db Klasse haben willst welche auch Treiber unterstützen um zb mit einer kleinen Änderung im Code von mysql auf Postgre zu switchen heist das Zauberwort "abstract".

Versuch es doch erstmal selber sowas zu programmieren und wenn Fragen aufkommen stehen Dir hier einige User zur Seite, die Dir helfen werden und Dir Tips geben.

*ist nicht böse gemeint, aber ich hasse sowas*
 
Ich bin normalerweise auch kein Freund von "Mach mir das, ich nehms dann" - jeder, der mich bereits kennt, weiß das.

Aber ich hab im Internet schon soviele Klassen gesehen und auch hier scheiden sich die Geister - was der eine für gut hält, ist für den anderen nicht gut...gibt es denn nicht etwas, wo alle sagen: "Ja, das hat Substanz. Das passt."

Sowas suche ich ;)

Ich hatte wie gesagt eh schon die Klasse (oben gepostet) - aber die ist ja wohl wirklich nicht so super, oder etwa doch?? Weil dann belasse ich es bei der. Aber sobald man z.B. ein AND einfügt in einer Query, geht die nimma...
 
Ich hatte wie gesagt eh schon die Klasse (oben gepostet) - aber die ist ja wohl wirklich nicht so super, oder etwa doch?? Weil dann belasse ich es bei der. Aber sobald man z.B. ein AND einfügt in einer Query, geht die nimma...

Folglich ist sie nicht super, abgesehen davon, dass der komplette Query escaped wird (was überhaupt nicht Sinn und Zweck ist).

Es wäre auf jeden Fall sinnvoller, entweder das von ice-breaker vorgeschlagene ZendDb (wo ich leider noch keine Erfahrungen gemacht habe) oder eben PDO zu verwenden. Falls keins von beidem möglich ist, bedien' dich wenigstens dem Snippet.

Mfg
 
Also wenn Du was suchst wo ziehmlich viele sagen jawohl des is was gescheit´s, dann nimm Zend_Db.

Das darf man, wird ständig weiter entwickelt, wenns was neues gibt. Und dann kannst Dich später auch entscheiden das ganze Framework zu nutzen. Bin auch grad dabei mir da rein zu wurschteln.
 
Aber ich hab im Internet schon soviele Klassen gesehen und auch hier scheiden sich die Geister - was der eine für gut hält, ist für den anderen nicht gut...gibt es denn nicht etwas, wo alle sagen: "Ja, das hat Substanz. Das passt."
Zend_Db, Pear::MDB2, Propel, Doctrine
das sind die am meisten "akzeptierten", aber auch bei denen scheiden sich eben die Geister, wie eben bei allem.

aber die ist ja wohl wirklich nicht so super, oder etwa doch?? Weil dann belasse ich es bei der. Aber sobald man z.B. ein AND einfügt in einer Query, geht die nimma...
ne super ist die wirklich net :LOL:
die funktioniert so oft net weil du mysql_real_escape_string auf den Query anwedest, darf man aber nur auf die Vars.
 
*auch wenns nicht so recht hin hinpasst*
Ich weiß nicht ob das andere auch so sehen wie ich(da es ja eigentlich nen manual gibt), aber was haltet Ihr davon alles zu Zend_Db in einem weiteren Unterforum zu kapseln. Ich würde sagen das Zend ziehmlich angesagt ist und wenn sich noch mehrere wie ich da rein arbeiten ist es evtl sinnvoll.