it-swarm.com.de

Kann ich den Tabellennamen in einer vorbereiteten Anweisung parametrieren?

Ich habe die Funktion mysqli_stmt_bind_param mehrmals verwendet. Wenn ich jedoch Variablen trenne, die ich vor SQL-Injection schützen möchte, stoße ich auf Fehler.

Hier ist ein Codebeispiel:

function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol )
{
    $statement = $mysqli->prepare("INSERT INTO " .$new_table . " VALUES (?,?,?,?,?,?,?);");
    mysqli_stmt_bind_param( $statment, 'sssisss', $Partner, $Merchant, $ips, $score, $category, $overall, $protocol );
    $statement->execute();
}

Ist es möglich, die .$new_table.-Verkettung irgendwie durch eine andere Fragezeichenanweisung zu ersetzen, eine andere Bindeparameteranweisung zu machen oder die vorhandene zu ergänzen, um sich vor der SQL-Injection zu schützen?

So oder in irgendeiner Form davon:

function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol )
{    
    $statement = $mysqli->prepare("INSERT INTO (?) VALUES (?,?,?,?,?,?,?);");
    mysqli_stmt_bind_param( $statment, 'ssssisss', $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol );
    $statement->execute();
}
51
GK1667

Die kurze Antwort auf Ihre Frage lautet "nein".

Im strengsten Sinne erlauben vorbereitete Anweisungen auf Datenbankebene nur das Binden von Parametern für "Wertebits" der SQL-Anweisung.

Eine Art, dies zu denken, sind "Dinge, die zur Laufzeit der Anweisung ersetzt werden können, ohne ihre Bedeutung zu ändern". Der oder die Tabellennamen gehören nicht zu diesen Laufzeitwerten, da sie die Gültigkeit der SQL-Anweisung selbst bestimmen (dh welche Spaltennamen gültig sind) und eine Änderung zur Ausführungszeit möglicherweise die Gültigkeit der SQL-Anweisung beeinflussen.

Auf einer etwas höheren Ebene, sogar in Datenbankschnittstellen, die die Parameterersetzung für vorbereitete Anweisungen emulieren, anstatt tatsächlich vorbereitete Anweisungen an die Datenbank zu senden, wie z. B. PDO, wodurch Sie möglicherweise einen Platzhalter überall verwenden können (da der Platzhalter ersetzt wird, bevor er an gesendet wird) der Datenbank in diesen Systemen) wäre der Wert des Tabellenplatzhalters ein String und als solcher in der an die Datenbank gesendeten SQL eingeschlossen, also SELECT * FROM ? mit mytable, da der Parameter letztendlich gesendet würde SELECT * FROM 'mytable' für die Datenbank, bei der es sich um ungültiges SQL handelt.

Ihre beste Wette ist, einfach weiterzumachen

SELECT * FROM {$mytable}

aber Sie absolut sollten eine weiße Liste von Tabellen haben, die Sie zuerst überprüfen, wenn $mytable von Benutzereingaben stammt.

71
Sam Graham

(Verspätete Antwort, siehe meine Randnotiz).

Die gleiche Regel gilt, wenn Sie versuchen, eine "Datenbank" zu erstellen.

Sie können eine vorbereitete Anweisung nicht zum Binden einer Datenbank verwenden.

I.e .:

CREATE DATABASE IF NOT EXISTS ?

wird nicht funktionieren. Verwenden Sie stattdessen eine Sicherheitsliste.

Nebenbemerkung: Ich habe diese Antwort hinzugefügt (als Community-Wiki), da häufig Fragen geschlossen wurden, bei denen einige Personen ähnliche Fragen gestellt haben, als sie versuchten, eine Datenbank zu binden, und nicht eine Tabelle und/oder eine Spalte.

1