kostenloser Webspace werbefrei: lima-city


MySQL Injectionen verhindern

lima-cityForumProgrammiersprachenPHP, MySQL & .htaccess

  1. Autor dieses Themas

    g****e

    ich bin an der Umprogramierung eines XNova skriptes und nun bin ich auf die MySQL injectionen gestoßen.
    allerdings hab ich das problem das ich mich damit recht wenig bis eig eher garnicht auskenne, und aber dagegen absichern will.
    wie kann ich dagegen absichern, oder wie kann ich zumindest verhindern, das in der Browserzeile ein Symikolon verwendet wird (wird ja in fast jeder injection verwendet)

    brauche dringend hilfe :(
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. des Problem kenn ich.
    vllt kennst du ja die Seite www.xnova-germany.de
    Da gibts auch ein paar Sachen mit Sicherheit und so.
    Vllt hift dir das weiter.
    Auch wird da wohl demnächst eine neuen, sicherere Version released.
  4. tischfussball

    tischfussball hat kostenlosen Webspace.

    Um Semikola brauchst du dich gar nicht zu kümmern. Wichtig ist, dass bei Strings, die bei einer SQL-Abfrage benutzt werden, der String kein String-Endezeichen beinhaltet (also ' oder " ). Wenn das Skript in PHP geschrieben ist, kannst du das einfach verhindern, indem du vorher die genannten Sonderzeichen in den Strings mit mysql_escape_string() maskierst. Alternativ kannst du die natürlich auch selbst mit str_replace() ersetzen. Die Semikola oder auch Kommentarzeichen (--) sind dann völlig egal.


    Beitrag geändert: 25.10.2008 15:20:59 von tischfussball
  5. Anstatt mysql_escape_string()(http://de.php.net/manual/de/function.mysql-escape-string.php) kannst du auch mysql_real_escape_string()(http://de.php.net/manual/de/function.mysql-real-escape-string.php) benutzen, was zusätzlich die Zeichenkodierung berücksichtigt.
  6. s*****r

    Eine andere Möglichkeit wäre, nur Zahlen als Parameter zu übergeben. So musst du nur noch mit is_numeric() prüfen und gleichzeitig ist deine URL kürzer und hübscher. :biggrin:
  7. Autor dieses Themas

    g****e

    danke.
    ja xnova-germany.de kenne ich, und die leute da haben von ihrem eigenen tun und machen keine ahnung^^
    das ist da nicht so strukturiert, und ich habe mich schon mit den "großen" programmierern auseinander gesetzt, und die meinten: keine ahnung.
    die codes werde ich gleich mla ausprobieren, danke, kann man nicht aber ein Skript vllt entwickeln, welches man nur einmal hochladen muss, und jede domain eingabe und linkaktivierung überprüft?
    gibt es sowas, oder wäre das möglich? (wäre schneller bei so ca 80 datein)
  8. Also ich persönlich favorisiere das mysql_real_escape_string(), da damit Umlaute in der Datenbank keine Probleme mehr sind, und es gibt auch keine Darstellungsfehler im späteren HTML-Code ^^
  9. Wenn du das so machst:
    mysql_real_escape_string()
    musst du vorher eine Datenbankverbindung aufgebaut haben, sonst geht das nicht.
    Des weiteren solltest du, wenn du irgendetwas über ein Formular in deine DB einträgst, und das dann wieder ausgibst, die backslashes wieder mit http://www.php.net/manual/de/function.stripslashes.php entfernen.

    Gruß, Prog


    Beitrag geändert: 27.10.2008 21:03:34 von prog
  10. gibt es nicht eine funktion die man am Anfang des php Files einfügen kann?

  11. gibt es nicht eine funktion die man am Anfang des php Files einfügen kann?

    die();


    Nein. Wenn das so einfach wäre, wären MySQL-Injections ja wohl kein Thema.


    Beitrag geändert: 30.10.2008 11:09:50 von tavern
  12. Bei SQL-Injection geht es darum, Variablen in SQL_Statements so abzusichern, dass diese Variablen nie von "außen" (z.B. per URL) geändert werden können.

    D.h. konkret für dich, wenn du immer die übergebenen Werte prüfst (z.B. ob Integerwerte auch Integerwerte sind), kann auch kein SQL-Injection funktionieren.

    Diese Überprüfung der Parameter ist zumindest beim neuen MySQLi in einigen Teilen schon eingebaut, da dort das SQL-Statement seperat zusammengebaut wird und dabei überprüft wird.

    Alternativ könntest du bei normalen MySQL deine Statements mit sprintf() zusammen bauen. Wenn dort dann bei %d / %u oder %f keine Integer übergeben wird, wird auch ein Fehler ausgegeben und das Statement nicht ausgeführt.

    Grüßle
  13. Autor dieses Themas

    g****e

    die antwort ist gut (die letzte) nur das verstehe ich leider auf anhieb nicht...
    tut mir leid...
  14. Also ganz nach der PHP-Doku... MySQLi und Parameterbindung...
    funktioniert bei Inserts so:
    <?php
    $host = 'localhost';
    $user = 'username';
    $pass = 'password';
    $db = 'datenbank';
    
    /* create a connection object which is not connected */
    $mysqli = mysqli_init();
    
    /* set connection options */
    // $mysqli->options(MYSQLI_INIT_COMMAND, "SET AUTOCOMMIT=0");
    $mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5);
    
    /* connect to server */
    $mysqli->real_connect($host, $user, $pass, $db);
    
    /* check connection */
    if (mysqli_connect_errno()) {
        printf("Connect failed: %sn", mysqli_connect_error());
        exit();
    }
    
    $stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
    $stmt->bind_param('sssd', $code, $language, $official, $percent);
    
    $code = 'DEU';
    $language = 'Bavarian';
    $official = "F";
    $percent = 11.2;
    
    /* execute prepared statement */
    $stmt->execute();
    
    printf("%d Row inserted.n", $stmt->affected_rows);
    
    /* close statement and connection */
    $stmt->close();
    
    /* Clean up table CountryLanguage */
    $mysqli->query("DELETE FROM CountryLanguage WHERE Language='Bavarian'");
    printf("%d Row deleted.n", $mysqli->affected_rows);
    
    /* close connection */
    $mysqli->close();
    ?>


    Das wichtige ist dabei diese Zeile:
    $stmt->bind_param('sssd', $code, $language, $official, $percent);


    Da werden die Werte auf ihre Gültigkeit hin geprüft (wie angegeben ...sssd... also string,string,string,digit)
    Sollte dies nicht der Fall sein kommt eine Fehlermeldung.


    Beim normalen SQL kann man das nicht ganz so elegant machen, dort kann man höchstens mit sprintf() arbeiten.
    Das sieht dann in etwa so aus:
    <?  
      $userid = 56; // hier könnte auch $userid=$_REQUEST['id'];  stehen
      $username = "test";   // $username = $_REQUEST['username'];
    
      $query = sprintf("SELECT * FROM Table WHERE id=%u and name='%s';", $userid, $username);
      $res = mysql_query($query);
    ?>


    Hoffe es ist jetzt verständlicher geworden.
    Grüßle


    Beitrag geändert: 7.11.2008 12:38:29 von scout
  15. Autor dieses Themas

    g****e

    ist schon verständlicher :)
    danke ;)
  16. Und hier noch ein Beispiel, wenn du die Resultwerte günstig an Variablen binden willst:

    <?php
    $host = 'localhost';
    $user = 'username';
    $pass = 'password';
    $db = 'datenbank';
    
    /* create a connection object which is not connected */
    $mysqli = mysqli_init();
    
    /* set connection options */
    //$mysqli->options(MYSQLI_INIT_COMMAND, "SET AUTOCOMMIT=1");
    $mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5);
    
    /* connect to server */
    $mysqli->real_connect($host, $user, $pass, $db);
    
    /* check connection */
    if (mysqli_connect_errno()) {
        printf("Connect failed: %sn", mysqli_connect_error());
        exit();
    }
    
    if ($stmt = $mysqli->prepare("SELECT * FROM tablexyz WHERE spaltexyz LIKE ?")) {
        $tt2 = '%';  // der Wert nach dem gesucht werden soll, hier könnte auch ein $_REQUEST[] stehen, 
                     // MySQLi bindet immer den gesamten String an 1 Variable (womit SQL Injection verhindert wird)
       
        $stmt->bind_param("s", $tt2);
        $stmt->execute();
    
        $meta = $stmt->result_metadata();
        while ($field = $meta->fetch_field())
        {
            $params[] = &$row[$field->name];
        }
    
        call_user_func_array(array($stmt, 'bind_result'), $params);
    
        while ($stmt->fetch()) {
            foreach($row as $key => $val)
            {
                $c[$key] = $val;
            }
            $result[] = $c;
        }
       
        $stmt->close();
    }
    $mysqli->close();
    echo "<pre>";
    print_r($result);
    echo "</pre>";
    
    ?>


    Grüßle


    Beitrag geändert: 7.11.2008 12:45:18 von scout
  17. Autor dieses Themas

    g****e

    und was ist wenn ich keine MySQLi datenbank habe?
    geht das skript denn trotzdem?
    (ich habe um ehrlich zu sein noch nicht viel von dem MySQLi gehört^^)
  18. MySQLi ist keine neue Datenbank, sondern die Ansteuerlogik von PHP um eine MySQL-Datenbank anzusteuern ;-)
    Grüßle
  19. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!