1. Dashboard
  2. Artikel
  3. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Dieses Thema
  1. HTML - Webmaster Forum
  2. Programmierung - Entwickler Forum
  3. PHP Forum - Apache - CGI - Perl - JavaScript und Co.

SQL Injektion

  • Loewenzahn
  • 21. September 2006 um 09:56
  • Loewenzahn
    Teeny
    Beiträge
    17
    • 21. September 2006 um 09:56
    • #1

    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

  • GreenRover
    Forum Guru
    Beiträge
    4.787
    • 21. September 2006 um 10:24
    • #2

    injections gehen nur bei insert befehlen...

    das heist, falls du nicht abgesicherte query`s hast, kannst damit echt böse dinge machen...

  • BendOr
    Kaiser(in)
    Beiträge
    2.496
    • 21. September 2006 um 11:45
    • #3

    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!

  • Modula
    Kaiserliche Hoheit
    Beiträge
    1.515
    • 21. September 2006 um 12:33
    • #4

    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.

    Zoggerforum.de Betreuer * Mod @ ibforen.de * Admin @ daoc-ds.de
    ICQ Nummer kann via PN erfragt werden

  • GreenRover
    Forum Guru
    Beiträge
    4.787
    • 21. September 2006 um 16:20
    • #5

    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.....

  • No0ob
    Kaiserliche Hoheit
    Beiträge
    1.500
    • 21. September 2006 um 16:31
    • #6
    Zitat von GreenRover

    injections gehen nur bei insert befehlen...


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

  • GreenRover
    Forum Guru
    Beiträge
    4.787
    • 21. September 2006 um 16:37
    • #7

    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..

  • Modula
    Kaiserliche Hoheit
    Beiträge
    1.515
    • 21. September 2006 um 16:38
    • #8

    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...

    Zoggerforum.de Betreuer * Mod @ ibforen.de * Admin @ daoc-ds.de
    ICQ Nummer kann via PN erfragt werden

  • No0ob
    Kaiserliche Hoheit
    Beiträge
    1.500
    • 21. September 2006 um 16:46
    • #9
    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

    http://www.seite.de/userlist.php?id=4


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

    Zitat

    http://www.seite.de/userlist.php?id=4;DROP TABLE user_list;


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

  • Modula
    Kaiserliche Hoheit
    Beiträge
    1.515
    • 21. September 2006 um 16:54
    • #10

    Der Query hört bei dem Semikolon auf. MySQL schert sich einen feuchten .... um den Teil DROP TABLE user_list.

    Via PHP führt MySQL nur noch maximal einen Query je mysql_query Befehl aus. Genau um sowas zu vermeiden ;)

    Zoggerforum.de Betreuer * Mod @ ibforen.de * Admin @ daoc-ds.de
    ICQ Nummer kann via PN erfragt werden

  • GreenRover
    Forum Guru
    Beiträge
    4.787
    • 21. September 2006 um 17:39
    • #11

    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...

  • Loewenzahn
    Teeny
    Beiträge
    17
    • 21. September 2006 um 18:43
    • #12

    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

  • <source>
    Anfänger
    Beiträge
    7
    • 21. September 2006 um 19:09
    • #13

    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 ;)

  • baloo
    Großmeister(in)
    Beiträge
    514
    • 24. September 2006 um 15:06
    • #14

    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... :)

    thats-me.ch Communtiy

  • No0ob
    Kaiserliche Hoheit
    Beiträge
    1.500
    • 24. September 2006 um 15:26
    • #15

    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;
    }
  • Loewenzahn
    Teeny
    Beiträge
    17
    • 29. September 2006 um 11:14
    • #16

    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


    PHP
    <?php
    
    
    session_start(); 
    
    
    $anrede = $_POST['anrede'];
    
    
    $vorname = $_POST['vorname'];
    
    
    $nachname = $_POST['nachname'];
    
    
    $strasse = $_POST['strasse'];
    
    
    $plz = $_POST['plz'];
    
    
    $ort = $_POST['ort'];
    
    
    $land = $_POST['land'];
    
    
    $email = $_POST['email'];
    
    
    $newuser = $_POST['user'];
    
    
    $daterror = 0;
    
    
    
    
    
    
    if ($vorname==""||$nachname==""||$land==""||$email==""||$newuser=="") {
    
    
    echo '<script language="JavaScript1.2" type="text/javascript">alert("Sie haben nicht alle erforderlichen Felder ausgefüllt!"); history.back()</script>';
    
    
    die();
    
    
    }
    
    
    
    
    
    
    include("admin/config.inc.php");
    ##Der Admin ist mit Passwort versehen .htaccess usw.##
    
    
    
    
    $userda1 = mysql_query ("SELECT * FROM db_user WHERE username = '$newuser'");
    
    
    $userda= mysql_num_rows($userda1);
    
    
    if ($userda>="1") {
    
    
    echo '<script language="JavaScript1.2" type="text/javascript">alert("Der gewünschte Username ist bereits vergeben.\nBitte wählen Sie einen anderen Usernamen."); history.back()</script>';
    
    
    die();
    
    
    }
    
    
    
    
    
    
    $userda2 = mysql_query ("SELECT * FROM db_user WHERE email = '$email'");
    
    
    $mailda= mysql_num_rows($userda2);
    
    
    if ($mailda>="1") {
    
    
    echo '<script language="JavaScript1.2" type="text/javascript">alert("Unter der angegebenen E-Mail-Adresse ist bereits ein Account registriert."); history.back()</script>';
    
    
    die();
    
    
    }
    
    
    
    
    
    
    $zeitjetzt = time();
    
    
    $tim02 = rand(100,999);
    
    
    $newdatcode1 = $zeitjetzt/$tim02; $passwort = round($newdatcode1);
    
    
    $anfuegen = "INSERT INTO db_user (username, passwort, email, anrede, vorname, nachname, strasse, plz, ort, land) VALUES ('$newuser', '$passwort', '$email', '$anrede', '$vorname','$nachname', '$strasse', '$plz', '$ort','$land')";
    
    
    $speicher = mysql_query($anfuegen);
    
    
    echo mysql_error();
    
    
    
    
    
    
    $abfrage01 = mysql_query ("SELECT * FROM db_content WHERE name = 'regmail'");
    
    
    $data = mysql_fetch_row($abfrage01);
    
    
    $mailtxt = $data['1'];
    
    
    eval($mailtxt);
    
    
    mail($email, $betreff, $text, "From: Test <test -@email .de>");
    
    
    ############################################################################
    
    
    echo '<script language="JavaScript1.2" type="text/javascript">alert("Herzlichen Glückwunsch!\n\nIhre Registrierung war erfolgreich und wir haben Ihnen Ihre persönlichen Zugangsdaten an Ihre angegebene E-Mail-Adresse gesendet.\n\nBitte rufen Sie jetzt Ihre E-Mails ab."); history.back(-2)</script>';
    Alles anzeigen


    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

  • Modula
    Kaiserliche Hoheit
    Beiträge
    1.515
    • 29. September 2006 um 11:23
    • #17
    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
    PHP
    <?php
    
    
    session_start(); 
    
    
    $anrede = $_POST['anrede'];
    $vorname = $_POST['vorname'];
    $nachname = $_POST['nachname'];
    $strasse = $_POST['strasse'];
    $plz = $_POST['plz'];
    $ort = $_POST['ort'];
    $land = $_POST['land'];
    $email = $_POST['email'];
    $newuser = $_POST['user'];
    
    
    $daterror = 0;
    
    
    if ($vorname==""||$nachname==""||$land==""||$email==""||$newuser=="") {
    
    
    echo '<script language="JavaScript1.2" type="text/javascript">alert("Sie haben nicht alle erforderlichen Felder ausgefüllt!"); history.back()</script>';
    
    
    die();
    
    
    }
    
    
    
    
    
    
    include("admin/config.inc.php");
    ##Der Admin ist mit Passwort versehen .htaccess usw.##
    
    
    
    
    $userda1 = mysql_query ("SELECT * FROM db_user WHERE username = '$newuser'");
    Alles anzeigen

    $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
    Code
    $userda= mysql_num_rows($userda1);
    
    
    if ($userda>="1") {
    
    
    echo '<script language="JavaScript1.2" type="text/javascript">alert("Der gewünschte Username ist bereits vergeben.\nBitte wählen Sie einen anderen Usernamen."); history.back()</script>';
    
    
    die();
    
    
    }
    
    
    
    
    
    
    $userda2 = mysql_query ("SELECT * FROM db_user WHERE email = '$email'");
    Alles anzeigen


    s. o.

    Zitat von Loewenzahn
    Code
    $mailda= mysql_num_rows($userda2);
    
    
    if ($mailda>="1") {
    
    
    echo '<script language="JavaScript1.2" type="text/javascript">alert("Unter der angegebenen E-Mail-Adresse ist bereits ein Account registriert."); history.back()</script>';
    
    
    die();
    
    
    }
    
    
    
    
    
    
    $zeitjetzt = time();
    
    
    $tim02 = rand(100,999);
    
    
    $newdatcode1 = $zeitjetzt/$tim02; $passwort = round($newdatcode1);
    
    
    $anfuegen = "INSERT INTO db_user (username, passwort, email, anrede, vorname, nachname, strasse, plz, ort, land) VALUES ('$newuser', '$passwort', '$email', '$anrede', '$vorname','$nachname', '$strasse', '$plz', '$ort','$land')";
    Alles anzeigen


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

    Zitat von Loewenzahn
    Code
    $speicher = mysql_query($anfuegen);
    
    
    echo mysql_error();
    
    
    
    
    
    
    $abfrage01 = mysql_query ("SELECT * FROM db_content WHERE name = 'regmail'");
    Alles anzeigen


    Kein Select * verwenden wenn möglich ;)

    Zitat von Loewenzahn
    Code
    $data = mysql_fetch_row($abfrage01);
    
    
    $mailtxt = $data['1'];
    
    
    eval($mailtxt);
    
    
    mail($email, $betreff, $text, "From: Test <test -@email .de>");
    
    
    ############################################################################
    
    
    echo '<script language="JavaScript1.2" type="text/javascript">alert("Herzlichen Glückwunsch!\n\nIhre Registrierung war erfolgreich und wir haben Ihnen Ihre persönlichen Zugangsdaten an Ihre angegebene E-Mail-Adresse gesendet.\n\nBitte rufen Sie jetzt Ihre E-Mails ab."); history.back(-2)</script>';
    Alles anzeigen


    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

    Alles anzeigen

    Zoggerforum.de Betreuer * Mod @ ibforen.de * Admin @ daoc-ds.de
    ICQ Nummer kann via PN erfragt werden

  • Loewenzahn
    Teeny
    Beiträge
    17
    • 29. September 2006 um 12:06
    • #18

    Danke, Danke, das hilft mir jetzt schon ein wenig weiter.
    Ich hatte mir php und mysql Bücher besorgt, aber soetwas steht nicht drin.
    Nichts von Sicherheit usw.
    mfg
    Peter

  • GreenRover
    Forum Guru
    Beiträge
    4.787
    • 29. September 2006 um 12:45
    • #19

    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.

Tags

  • erlaubt
  • tex
  • funktion
  • problem
  • input
  • profil
  • code
  • php
  • zeichen
  • sicherheit
  • passwort
  • script
  • ring
  • buchstabe
  • programmierung
  • sql
  • string
  • login
  • select
  • insert
  • benutzername
  • md5
  • benutzereingabe
  1. Datenschutzerklärung
  2. Impressum
Community-Software: WoltLab Suite™
  • Alles
  • Dieses Thema
  • Dieses Forum
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
Zitat speichern