• Ein Freund hat mir erzählt ich muß meinen Script mit "SQL Injektion"
    überarbeiten, sonst ist meine Datenbank nicht sicher.
    Wißt ihr wie das geht, an folgenden Beispiel: (Ausschnitt)

    $userda1 = mysql_query ("SELECT * FROM db_user WHERE username = '$newuser'");

    oder

    $userda= mysql_num_rows($userda1); if ($userda>="1")


    Danke.
    mfg
    Peter

  • ich dachte das geht mit jedem query, da man die befehle doch mit simikolon trennen kann oder ?
    also SELECT * FROM db_user WHERE username = 'klaus'; DELETE FROM db_user WHERE 1='1;

    $newuser = klaus'; DELETE FROM db_user WHERE 1='1

    Sei immer du selbst. Außer du kannst Batman sein. Sei immer Batman!

  • Weder das eine noch das andere ist ganz korrekt.

    1. PHP kann nicht mehrere Querys in einem String ausführen (seit Version ka.) - da könnt ihr da Semikolons reinkloppen wie ihr lustig seit, es geht nicht.
    2. Nehmen wir mal an wir haben einen Query ala

    Code
    $SQL = "SELECT * FROM benutzertabelle WHERE benutzername LIKE '{$_REQUEST['user']}' AND passwort = '{$_REQUEST['passwort']}' LIMIT 1"

    Jetzt könnte man sich einloggen indem man als username folgendes eingibt:

    Code
    ' OR 1 --

    das Passwortfeld lässt man leer oder trägt irgendetwas ein.

    Der Query sieht dann so aus:

    Code
    $SQL = "SELECT * FROM benutzertabelle WHERE benutzername LIKE '' OR 1 -- ' AND passwort = 'irgendetwas' LIMIT 1"

    Da -- in MySQL der Beginn für ein Kommentar ist würde nur noch dieser Query an die Datenbank geschickt werden:

    Code
    $SQL = "SELECT * FROM benutzertabelle WHERE benutzername LIKE '' OR 1


    Da 1 immer true ist ist der hintere Teil der WHERE Bedingung erfüllt. Es werden also automatisch ALLE Datensätze zurückgegeben die in der Datenbank sind. Möchte man nur den ersten Datensatz haben den MySQL findet - z.B. um sich einzuloggen - so nutzt man

    Code
    ' OR 1 LIMIT 1

    als Benutzernamen. Jetzt wird man - sofern im Script keine weitere Prüfung stattfindet - automatisch als der erste gefundene Benutzer angemeldet (das Beispiel kann mit ein paar Modifikationen auch bei aktivem magic_quotes funktionieren)

    Um einen solchen Angriff zu verhindern kann man nur dafür sorgen dass 1. der Passwortvergleich im PHP Script stattfindet und nicht bereits über den MySQL Query und 2. man konsequent dafür sorgt, dass alle möglichkeiten ein ', " oder sonstiges quot einzuschleusen dicht sind.

  • ja und da begrenze man doch einfac hdie query`s mit:

    Dann schaut das ganze so aus:

    Ordnungsgemäs:
    $sql ='SELECT `id`, `rabatt` FROM `user_login` WHERE `login`="GreenRover" AND `passwort`=MD5("geheim") LIMIT 0 , 1';

    Inject versuch:
    $sql ='SELECT `id`, `rabatt` FROM `user_login` WHERE `login`="GreenRover\" --" AND `passwort`=MD5("geheim") LIMIT 0 , 1';

    da man ja immer noch das auto entquote von PHP hat und daher der inject versuch zur sau ist.....

  • Zitat von GreenRover

    injections gehen nur bei insert befehlen...


    Stimmt nicht.
    Entweder eine Funktion schreiben oder die Funktion mysql_real_escape_string benutzen

  • vorgabe:

    $sql ='SELECT `id`, `rabatt` FROM `user_login` WHERE `login`="'.$_GET['user'].'" AND `passwort`=MD5("'.$_GET['password'].'") LIMIT 0 , 1';


    So nb0ob: liefer nun mal den beweis das heist die eingaben für die beiden get vars um fäschlich eun zu loggen oder zu schaden..

  • Wie gesagt, ist magic_quotes längst nicht auf allen Systemen aktiv oder funktioniert dort einwandfrei.

    Desweiteren wäre dies jetzt lediglich ein Beispiel. Viele Integerwerte sind beispielsweise nicht mit quot versehen... - wenn diese nun via get erst eingelesen werden bieten sie eine gute Angriffsfläche.

    Man brauch sich ja nur ansehen, was mittlerweile so alles an exploids veröffentlicht wurde...

  • Zitat von GreenRover


    $sql ='SELECT `id`, `rabatt` FROM `user_login` WHERE `login`="'.$_GET['user'].'" AND `passwort`=MD5("'.$_GET['password'].'") LIMIT 0 , 1';


    Ich meinte das gar nicht mal so böse GreenRover aber nun ja :-/

    SQ-Injection kann man nur in der Domain machen, das heisst, ich müsste sehen wie das ausgegeben wird. Bei so internen Sachen, kann es so genug sein, würde ich mich allerdings auch nicht darauf verlassen.

    Wenn du also z.B. ein Link mit SELECT ID FROM user_list WHERE ID = 4 hast, kann man das dann in der URL z.b so sehn:

    Zitat


    Das könnte man z.B. so umändern.

    Zitat


    Dazu muss man natürlich den Tabellennamen wissen.
    Ich hoffe das stimmt so.

  • Dazu nutzt man auch bei id`s anführungszeichen und schon ist die Welt wieder lieb :-p

    @ Modula ja das mit dme magic quote stimmt schon so aber wenn es an ist, muss man sich drauf verlasen, da man sonst alles doppelt enquotiert ....


    Also moral von der geschicht, alles immer schön mit ; anschliessen

    die werte in " schreiben und NIE mit $sql = " sondern immer $sql =' das ist vileicht aufwendiger aber wesentlich besser von der performance und noch um einiges sicherer...

  • Au man, das kann ja richtig böse werden.
    Denn der User trägt sich über ein Formular ein.
    Wenn ich das richtig verstehe, kann er mit einen sql-Eintrag meine
    Datenbank löschen bzw. an geschützten Bereich rankommen, wo er nicht befugt ist.
    Da hat der Freund recht, das scheint ein wichtiges Thema zu sein.

    Zitat

    mysql_real_escape_string

    Wie würde denn der Script dann aussehen ?

    Danke.
    mfg
    Peter

  • bei ID-angaben, die mit sql_querys verknüpft sind, macht doch einfach

    Code
    if (!is_numeric($id))
    {
    	die('Die ID-Nummer ist ungültig!');
    }

    Hoffentlich könnt ihr mir helfen oder ich konnte euch helfen ;)

  • hatte dieses problem auch mal.
    meistens vernachlässigt man die sicherheit bei der programmierung.

    am besten jede benutzereingabe genau überprüfen. grundsatz: all input is evil :twisted: :)

    meistens werden sql injections über login-formulare oder GET manipulationen durchgeführt.

    bei mir werden praktisch nur integer als get-parameter erwartet, deshalb führe ich am anfang jeder seite

    Code
    $id = sec_int($_GET['id']);

    durch.
    die funktion sec_int steht für mich für "security_integer" :roll: (da es ja noch sec_string etc. gibt) und enthält:

    Code
    function sec_int($wert) {
    	if ((string)((int)$wert) != $wert) {
    		die("Es wurde eine ungültige ID angegeben.");
    	}
    	return $wert;
    }

    am besten für jede benutzereingabe eine solche funktion schreiben.
    sind für den benutzernamen z.b. nur buchstaben von a-z und zahlen erlaubt, schreibst du dir vllt. eine funktion sec_nick(), welche das script abbricht, sobald beim login ungültige zeichen eingegeben werden. diese funktion verwendest du dann auch, wenn du den nick z.b. über profil.php?nick=blabla übergibst.

    etc... :)

  • Man kann auch eine Funktion für beide schreiben :)

    Code
    function safesql($value)
    {
      if (get_magic_quotes_gpc()) 
          $value = stripslashes($value);
      if (!is_numeric($value)) 
          $value = mysql_real_escape_string($value);
      }
      return $value;
    }
  • Wenn ich das richtig verstehe,geht doch bloß um Daten die in eine Datenbank
    geschrieben werden.
    So das man beinm Eintragen SQL Befehle unterbringen kann, die die Datenbank z.B. löschen oder ...

    Befehle die nur die Datenbank auslesen werden doch nicht davon betroffen oder ??

    Wenn es so ist, betrifft es bei mir nur um eine Datei mit insert Befehl
    "INSERT INTO db_user"
    Der Rest kann doch dann belieben oder



    Dier Scripte hat mir mal ein Freund erstellt.
    Jetzt kämpfe ich mich mit Spam, Hack usw. rum
    Formulare habe ich schon mit Captcha gesichert.
    Jetzt geht es nur noch um die Datenbankgeschichte.
    Ich komme nur mit kleinen Schritten vorran, da ich in Sachen php , mysql noch in den Kinderschuhe stecke.

    Danke für Eure Hilfe
    mfg
    Peter

  • Zitat von Loewenzahn

    Wenn ich das richtig verstehe,geht doch bloß um Daten die in eine Datenbank
    geschrieben werden.


    Nein, jeder SQL Befehl ist betroffen. Insbesondere auch SELECT.

    Zitat von Loewenzahn

    So das man beinm Eintragen SQL Befehle unterbringen kann, die die Datenbank z.B. löschen oder ...

    Befehle die nur die Datenbank auslesen werden doch nicht davon betroffen oder ??


    Oder ist richtig ;) s.o.

    Zitat von Loewenzahn

    Wenn es so ist, betrifft es bei mir nur um eine Datei mit insert Befehl
    "INSERT INTO db_user"
    Der Rest kann doch dann belieben oder

    nehmen wir mal wieder "oder" ;)

    Zitat von Loewenzahn

    $newuser sollte unbedingt vorher mit stripslashes() und mysql_real_escape_string() aufbereitet werden.

    Desweiteren ist SELECT * PFUI. Du solltest gezielt NUR die Felder angeben die du brauchst. Wenn du hinter das username='$newuser' noch ein LIMIT 1 anhängt bist du noch etwas sicherer.

    Zitat von Loewenzahn


    s. o.

    Zitat von Loewenzahn


    auch hier: alle Strings vorher wie oben beschrieben durchackern...

    Zitat von Loewenzahn


    Kein Select * verwenden wenn möglich ;)

  • Ja das liegt leider daran, das soetwas nur von n00b`s geschrieben wird die selbst keine ahnung haben...

    Da kann ich dir aber auch nur googel empfehlen.. an büchern habe ich auch noch nichts gutes endeckt.