• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

mysql_escape_string - ausreichend gegen SQL-injection?

StephanBo

Mitglied
Hatte gestern ein Video gesehen, in dem die einzelnen Variablen neben dem o.g. mysql_escape_string noch mit stripslashes und mit strip_tags versehen waren.

Meine Frage wäre nun, ob die beiden letztgenannten tags wirklich erforderlich sind, da ich bisher immer geglaubt hatte, der mysql_escape_string würde alle gefährlich werdenden Sonderzeichen eindämmen.
 
Das Video ist da wohl Quatsch. MySQL schert sich nicht um HTML-Tags.
stripslashes() wird wahrscheinlich benutzt worden sein, um magic_quotes zu entfernen.
strip_tags() entfernt HTML-Tags. Das ist höchstens bei der Ausgabe sicher. Aber bei der Ausgabe gibt es feinere Methoden, um das zu regeln: htmlspecialchars().

mysql_real_escape_string() ist nicht ein Allheilmittel. Wenn man es falsch benutzt, ist es nutzlos. Es sollte nur bei Zeichenketten benutzt werden.

PHP:
"select * from tabelle where name = '".mysql_real_escape_string($name)."'";
Hier ist es nützlich.


___________________________________
PHP:
"select * from tabelle where user_id = ".mysql_real_escape_string($user_id); // NICHT BENUTZEN!
Hier nicht, hier wäre das richtig:
PHP:
"select * from tabelle where user_id = ".(int)$user_id;


Außerdem noch ganz wichtig: PHP rät von der Benutzung von mysql_*-Funktionen ab. Nimm stattdessen lieber mysqli oder PDO!
 
Edit: Ups, Beitrag nicht gesehen, Asterixus.

Die sind nicht erforderlich. Habe dazu zufällig gerade das hier geschrieben:

- php.de - Einzelnen Beitrag anzeigen - EVA Prinzip

Zu strip_tags steht dort was, stripslashes ist ein Überbleibsel aus Magic-Quotes-Zeiten, das die Auswirkung einer dummen, mittlerweile entfernten PHP-Konfigurationseinstellung wieder rückgängig macht.

- Magic Quotes - PHP Forum: phpforum.de

stripslashes hat mit dem Einfügen in eine SQL-Query thematisch nichts zu tun. In kurzen Scripts mag das notgedrungenen mal an derselben Stelle stehen, aber das ist ein funktional abgegrenzter Themenbereich. (Edit: Auch wenn es ursprünglich anders gedacht war… ;))

Am Rande:

- Standardantwort zu veraltete mysql-Extension - PHP Forum: phpforum.de

Edit:

Asterixus schrieb:
mysql_real_escape_string() ist nicht ein Allheilmittel.

Stimmt schon, was du schreibst, aber es lassen sich auch numerische Daten als Strings in SQL-Queries einfügen. Dann braucht es nur *_real_escape_string.

Ob das maximal elegant ist, lasse ich mal dahingestellt. Es ist aber definitiv eine Option.
 
Zuletzt bearbeitet:
Das man es nicht bei Zeichenketten anwenden sollte wusste ich noch gar nicht. Also in meinem Fall will ich keine SELECT-ABFRAGE starten sondern per POST Befehl jeweils genau eine Variable eingeben. Ich habe dazu jetzt einfach bei der Variablendefinition zu Beginn des Codes vor jeder Variable den mysql_escape_string gesetzt. Ist das ausreichend oder hilft meine Vorgehensweise gar nicht? Aufs wesentliche verkürzt sieht mein Code nun so aus:

if (isset($_POST['title'], $_POST['artist'], $_POST['link'] )) {
...
$title = mysql_escape_string($_POST['title']);
$artist = mysql_escape_string($_POST['artist']);
$link = mysql_escape_string($_POST['link']);
$description = mysql_escape_string($_POST['description']);

$query = "INSERT INTO images (title, artist, link, description) VALUES ('".$title."', '".$artist."', '".$link."', '".$description."')";
mysql_query($query) or die ('Ups, something went wrong. Please try again.'); }
 
Und so sieht es dann noch besser aus:
PHP:
if (isset($_POST['title'], $_POST['artist'], $_POST['link'] )) 
{
   $query = "INSERT 
                INTO 
                  `images`
                SET
                  `title`='"       . mysql_real_escape_string($_POST['title'])       . "', 
                  `artist`='"      . mysql_real_escape_string($_POST['artist'])      . "', 
                  `link`='"        . mysql_real_escape_string($_POST['link'])        . "', 
                  `description`='" . mysql_real_escape_string($_POST['description']) . "'";
                  
                  
    mysql_query($query) 
       or die ('Ups, something went wrong. Please try again.'); 
}
 
Und so sieht es dann noch besser aus...

Ich benutze vorher noch eine Valiadation, welche die Korrektheit der ausgefüllten Felder überprüft. Weiß dehalb nicht, ob ich deinen Vorschlag dann immer noch umsetzen kann. Hier wäre mein ganzer Code, den ich jetzt verwende.

PHP:
<?php
if (isset($_POST['title'], $_POST['artist'], $_POST['link'] )) {                      
   $errors = array();  

   $title =   mysql_real_escape_string($_POST['title']);                
   $artist = mysql_real_escape_string($_POST['artist']);                
   $link = mysql_real_escape_string($_POST['link']);                
   $description = mysql_real_escape_string($_POST['description']);

    if (empty($title)) {                    
      $errors[] = '<strong>Song Title</strong> needs to be named'; 
    }                
    if (empty($artist)) {                   
      $errors[] = '<strong>Original Perfomer</strong> needs to be named';
    }                
    if (empty($link)) {         
      $errors[] = '<strong>Youtube-Link</strong> needs to be set';    
     }
     if (!empty($errors)) {     
       echo '<h4 style="margin-bottom: 20px; color: #c22336;">Your attention is required:</h4>';    
        foreach ($errors as $error) {   
           echo '<p style="margin-bottom: 20px;">', $error, '</p>';         
         }                    
           echo '<p style="margin-bottom: 20px;">Please fill out the blank field and send your nomination again.</p><hr />';               
       }               
       else {          
           echo '<h4 style="margin-bottom: 20px; color: #c22336">The song has been successfully nominated. Thank you...</h4>';

         // db connection                   
         include("xxx");
          
         $query = "INSERT INTO images (title, artist, link, description) VALUES ('".$title."', '".$artist."', '".$link."', '".$description."')";

          mysql_query($query) or die ('Ups, something went wrong. Please try again.');                }
}
?>

Gibt es eigentlich noch einen Code-Schnnipsel am Ende, der bei einem Refresh der Seite verhindert, dass die Daten zweimal in der DB gespeichert werden? Ich brauche diesen jetzt hierfür zwar nicht, da ich noch eine Validation einbauen werde, die doppelte Einträge dadurch verhindert, dass sie warnt, wenn ein Name schon in der DB abgespeichert wurde. Aber würde mich trotzdem interessieren, wie ein doppelter Eintag durch einen Refreh zu verhindern ist.
 
Zuletzt bearbeitet:
Ich benutze vorher noch eine Valiadation, welche die Korrektheit der ausgefüllten Felder überprüft.
Und wo steht geschrieben, dass man eine Validation nicht mit $_POST durchführen darf?

Es ist schon traurig, wenn man einen Code-Schnipsel liefert, und dieser dann einfach ignoriert wird, selbst wenn er nicht zu 100% übernommen werden kann!
PHP:
<?php
  if (isset($_POST['title']))
  {
     $errors = array();

     if (empty($_POST['title']))
       $errors[] = '<strong>Song Title</strong> needs to be named';
     
     if (empty($_POST['artist']))
       $errors[] = '<strong>Original Perfomer</strong> needs to be named';
    
     if (empty($_POST['link']))
       $errors[] = '<strong>Youtube-Link</strong> needs to be set';

     if (!empty($errors)) 
     {
        echo '<h4 style="margin-bottom: 20px; color: #c22336;">Your attention is required:</h4>';
        
        foreach ($errors as $error) 
        {
           echo '<p style="margin-bottom: 20px;">', $error, '</p>';
        }
        
        echo '<p style="margin-bottom: 20px;">Please fill out the blank field and send your nomination again.</p><hr />';
     }
     else 
     {
        echo '<h4 style="margin-bottom: 20px; color: #c22336">The song has been successfully nominated. Thank you...</h4>';

        // db connection
        include("xxx");

        $query = "INSERT 
                   INTO 
                    `images`
                   SET
                    `title`='"       . mysql_real_escape_string($_POST['title'])       . "', 
                    `artist`='"      . mysql_real_escape_string($_POST['artist'])      . "', 
                    `link`='"        . mysql_real_escape_string($_POST['link'])        . "', 
                    `description`='" . mysql_real_escape_string($_POST['description']) . "'";
                  
                  
       mysql_query($query) 
         or die ('Ups, something went wrong. Please try again.'); 

     }
  }
?>
Gibt es eigentlich noch einen Code-Schnnipsel am Ende, der bei einem Refresh der Seite verhindert, dass die Daten zweimal in der DB gespeichert werden?
Einfach nach dem Eintrag auf eine andere Seite weiterleiten. Was aber nicht bedeutet, dass du auf doppelte Einträge nicht mehr prüfen solltest.
 
Ich habe den überarbeiten Code von dir nicht hundertprozentig verstanden, da ich bisher davon ausgegangen bin, dass die Variablen bereits vor der Validierung mit dem real_escape_string versehen werden müssen. So jedenfalls wurde es in den Tuts erklärt, die ich gesehen hatte. Das dies nicht erforderlich ist, habe ich nun verstanden und ist auch irgendwo logisch. In der Validierung wird ja schließlich noch nichts übermittelt. Jedenfalls danke für den kompletten Code.
 
Zurück
Oben