FlawOpen

flawopen.com/SQL Injection in C#/EF Core FromSqlRaw

Ist Entity Framework Core FromSqlRaw sicher?

Referenzleitfaden
Kurzantwort

Ja, wenn Werte vom SQL-Text getrennt bleiben. FromSqlRaw akzeptiert rohes SQL; nicht vertrauenswürdige Eingaben anzuhängen oder in den String zu interpolieren, kann die Abfrage verändern. Verwenden Sie separate Parameterargumente oder übergeben Sie einen interpolierten FormattableString an FromSqlInterpolated (oder ab EF Core 7 an FromSql). Ein Parameter ist wie ein versiegeltes Wertfach: Die Datenbank erhält den Wert, keine neuen SQL-Anweisungen.

UNSICHER — Interpolation wird zu einem normalen String
// Die Interpolation wird zuerst zu einem String ausgewertet.
var sql = $"SELECT * FROM Users WHERE Id = {id}";

// FromSqlRaw erhält SQL-Text, keinen FormattableString.
var query = context.Users.FromSqlRaw(sql);
SICHER — Werte bleiben Parameter
// EF Core 3–6: Positionsplatzhalter und separater Wert.
var byRawParameter = context.Users.FromSqlRaw(
    "SELECT * FROM Users WHERE Id = {0}", id);

// EF Core 3+: Interpolation an die Parameter-API übergeben.
var byInterpolation = context.Users.FromSqlInterpolated(
    $"SELECT * FROM Users WHERE Id = {id}");

// EF Core 7+: FromSql akzeptiert ebenfalls FormattableString.
var byFromSql = context.Users.FromSql(
    $"SELECT * FROM Users WHERE Id = {id}");

Der kontraintuitive Punkt

FromSqlInterpolated erhält einen FormattableString. EF Core liest Format und Argumente und sendet jeden interpolierten Wert als separaten Datenbankparameter; eine Kompilierzeit-Interception findet nicht statt. EF Core 7 führte FromSql mit demselben sicheren Verhalten für interpolierte Strings ein. Ältere Versionen verwenden FromSqlInterpolated. FromSqlRaw ist ebenfalls sicher, wenn Platzhalter wie {0} zu separat übergebenen Werten passen. Ein interpolierter String, der zuerst in einem string gespeichert wird, hat seine Parameter-Metadaten bereits verloren.

Parameter binden Werte, keine Spaltennamen

Ein Datenbankparameter steht für einen Wert, nicht für Tabellen- oder Spaltennamen, SQL-Operatoren oder Sortierrichtungen. Wenn sich die Abfragestruktur ändern muss, wählen Sie jeden Bezeichner aus einer festen Allowlist im Anwendungscode. Versuchen Sie nicht, Bezeichner zu parametrisieren, und ersetzen Sie die Allowlist nicht durch Zeichenfilter. Prüfen Sie außerdem Berechtigungen und Abfragekosten: Eine gültige Spalte kann vertrauliche Daten offenlegen oder teure Scans auslösen.

So prüfen Sie Ihre Codebasis

rg -n -g '*.cs' '(FromSqlRaw|FromSqlInterpolated|FromSql)\s*\(' .
Prüfen Sie bei jedem Aufruf die Überladung und den Argumenttyp. Verfolgen Sie nicht vertrauenswürdige Daten bis zu Verkettungen, Interpolation an FromSqlRaw oder einer Umwandlung von FormattableString in string zurück; untersuchen Sie dynamische Bezeichner separat.

Häufige Fragen

Ist FromSqlRaw sicher, wenn es Parameter erhält?

Ja, wenn das SQL Platzhalter enthält und Werte als separate Argumente übergeben werden, zum Beispiel FromSqlRaw("... {0}", value). Verketten oder interpolieren Sie den Wert nicht vorher in den SQL-String.

Warum ist FromSqlInterpolated mit einem C#-Interpolationsstring sicher?

Die Methode erhält einen FormattableString, der Format und Werte getrennt erhält. EF Core wandelt jeden Wert in einen Datenbankparameter um. Wird die Interpolation zuerst einem string zugewiesen oder an FromSqlRaw übergeben, geht dieser Schutz verloren.

Können Parameter Tabellen- oder Spaltennamen ersetzen?

Nein. Parameter stehen nur für Werte. Ordnen Sie Benutzerauswahlen dynamischer Bezeichner einer festen Allowlist bekannter Bezeichner zu und prüfen Sie Berechtigungen sowie Abfragekosten.

Quellen

Siehe auch SQL-Injection (CWE-89): Funktionsweise und Schutz in jeder Sprache — flawopen.com FastAPI SQL Injection: Was Pydantic verhindert GORM Raw SQL: SQL-Injection in Go verhindern Reicht das Escapen von Anführungszeichen gegen SQL Injection? Reicht ein ORM aus, um SQL-Injection zu verhindern? Ist Knex.js vor SQL-Injection geschützt? MyBatis ${} vs. #{}: SQL Injection verhindern