2769 Stimmen

Wie kann ich SQL-Injection in PHP verhindern?

Wenn Benutzereingaben ohne Änderung in eine SQL-Abfrage eingefügt werden, wird die Anwendung anfällig für SQL-Einschleusung , wie im folgenden Beispiel:

$unsafe_variable = $_POST['user_input']; 

mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')");

Das liegt daran, dass der Benutzer etwas eingeben kann wie value'); DROP TABLE table;-- und die Abfrage wird:

INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')

Was kann getan werden, um dies zu verhindern?

131voto

Chintan Gor Punkte 1062

Es gibt so viele Antworten für PHP und MySQL aber hier ist der Code für PHP und Oracle zur Verhinderung von SQL-Injection sowie zur regelmäßigen Verwendung von oci8-Treibern:

$conn = oci_connect($username, $password, $connection_string);
$stmt = oci_parse($conn, 'UPDATE table SET field = :xx WHERE ID = 123');
oci_bind_by_name($stmt, ':xx', $fieldval);
oci_execute($stmt);

0 Stimmen

Bitte erklären Sie die oci_bind_by_name-Parameter.

126voto

Rakesh Sharma Punkte 13542

Veraltete Warnung: Der Beispielcode dieser Antwort (wie auch der Beispielcode der Frage) verwendet PHPs MySQL Erweiterung, die in PHP 5.5.0 veraltet war und in PHP 7.0.0 vollständig entfernt wurde.

Sicherheitswarnung : Diese Antwort steht nicht im Einklang mit bewährten Sicherheitsverfahren. Escaping ist unzureichend, um SQL-Injection zu verhindern verwenden vorbereitete Erklärungen stattdessen. Die Anwendung der unten beschriebenen Strategie erfolgt auf eigene Gefahr. (Auch, mysql_real_escape_string() wurde in PHP 7 entfernt).

Verwendung von PDO y MYSQLi ist eine gute Praxis, um SQL-Injections zu verhindern, aber wenn Sie wirklich mit MySQL-Funktionen und -Abfragen arbeiten wollen, wäre es besser, wenn Sie

mysql_real_escape_string

$unsafe_variable = mysql_real_escape_string($_POST['user_input']);

Es gibt noch weitere Möglichkeiten, dies zu verhindern: z. B. die Erkennung, ob es sich bei der Eingabe um eine Zeichenkette, eine Zahl, ein Zeichen oder ein Array handelt, es gibt viele eingebaute Funktionen, die dies erkennen. Außerdem wäre es besser, diese Funktionen zur Überprüfung der Eingabedaten zu verwenden.

is_string

$unsafe_variable = (is_string($_POST['user_input']) ? $_POST['user_input'] : '');

ist_numerisch

$unsafe_variable = (is_numeric($_POST['user_input']) ? $_POST['user_input'] : '');

Und es ist so viel besser, diese Funktionen zu verwenden, um die Eingabedaten mit mysql_real_escape_string .

10 Stimmen

Es macht auch absolut keinen Sinn, die Array-Mitglieder von $_POST mit is_string() zu überprüfen.

21 Stimmen

WARNUNG! mysql_real_escape_string() ist nicht unfehlbar .

10 Stimmen

mysql_real_escape_string ist jetzt veraltet, so dass es nicht länger eine brauchbare Option ist. Sie wird in Zukunft aus PHP entfernt werden. Es ist am besten, auf das umzusteigen, was die PHP- oder MySQL-Leute empfehlen.

90voto

Calmarius Punkte 17229

Ich habe diese kleine Funktion schon vor einigen Jahren geschrieben:

function sqlvprintf($query, $args)
{
    global $DB_LINK;
    $ctr = 0;
    ensureConnection(); // Connect to database if not connected already.
    $values = array();
    foreach ($args as $value)
    {
        if (is_string($value))
        {
            $value = "'" . mysqli_real_escape_string($DB_LINK, $value) . "'";
        }
        else if (is_null($value))
        {
            $value = 'NULL';
        }
        else if (!is_int($value) && !is_float($value))
        {
            die('Only numeric, string, array and NULL arguments allowed in a query. Argument '.($ctr+1).' is not a basic type, it\'s type is '. gettype($value). '.');
        }
        $values[] = $value;
        $ctr++;
    }
    $query = preg_replace_callback(
        '/{(\\d+)}/', 
        function($match) use ($values)
        {
            if (isset($values[$match[1]]))
            {
                return $values[$match[1]];
            }
            else
            {
                return $match[0];
            }
        },
        $query
    );
    return $query;
}

function runEscapedQuery($preparedQuery /*, ...*/)
{
    $params = array_slice(func_get_args(), 1);
    $results = runQuery(sqlvprintf($preparedQuery, $params)); // Run query and fetch results.   
    return $results;
}

Dies ermöglicht die Ausführung von Anweisungen in einem Einzeiler C#-ish String.Format wie:

runEscapedQuery("INSERT INTO Whatever (id, foo, bar) VALUES ({0}, {1}, {2})", $numericVar, $stringVar1, $stringVar2);

Der Variablentyp wird dabei nicht berücksichtigt. Wenn Sie versuchen, Tabellen- oder Spaltennamen zu parametrisieren, würde dies fehlschlagen, da jede Zeichenkette in Anführungszeichen gesetzt wird, was eine ungültige Syntax ist.

SECURITY UPDATE: Die vorherige str_replace Version erlaubte Injektionen durch das Hinzufügen von {#}-Tokens in Benutzerdaten. Diese preg_replace_callback Version verursacht keine Probleme, wenn die Ersetzung diese Token enthält.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X