2009-03-25 13 views
25

Ich habe eine kleine Umfrage-Website auf unserer Firma Intranet erstellt. Diese Webseite ist von außen nicht zugänglich.SQL-Injektion auf INSERT

Die Form ist einfach ein paar Radiobuttons und ein Kommentarfeld.

Ich möchte gute Programmierpraktiken pflegen und möchte mich vor SQL-Injektionen schützen.

Können SQL-Injektionen auf einer insert-Anweisung mit Kommentaren aus der Textbox passieren? Wenn ja, wie kann ich dagegen mit .NET 2.0 schützen?

+0

Zusätzliche Informationen: Wenn Sie eine Webseite erstellen, konzentrieren Sie sich nicht nur auf die SQL-Injektion. Überprüfen Sie auch die XSS-Gefahr des Textes, bevor Sie ihn in Ihre Datenbank einfügen. Ist jeder Ausgabecode über Server.HtmlEncode (...) gesichert? –

Antwort

54

Die Injektion kann bei jeder SQL-Anweisung nicht ordnungsgemäß ausgeführt werden.

Nehmen wir zum Beispiel an, dass Ihre Kommentartabelle zwei Felder hat, eine Ganzzahl-ID und die Kommentarzeichenfolge. So sollten Sie INSERT wie folgt:

INSERT INTO COMMENTS VALUES(122,'I like this website'); 

Betrachten jemand den folgenden Kommentar eingeben:

'); DELETE FROM users; -- 

Wenn Sie nur den Kommentartext in das, ohne dass dies jeder Abarbeitung von SQL setzen könnte schalten Sie einzelne INSERT um die folgenden zwei gefolgt von einem Kommentar Aussagen:

INSERT INTO COMMENTS VALUES(123,''); DELETE FROM users; -- '); 

Dies würde alles von Ihrer users Tabelle löschen. Und es gibt Leute, die bereit sind, den ganzen Tag damit zu verbringen, den richtigen Tabellennamen zu finden, um ihn mit Trial-and-Error und verschiedenen Tricks zu leeren. Here's a description of how you could perform an SQL Injection attack.

Sie müssen parameterized SQL statements verwenden, um dies zu verhindern.

Und das ist nicht nur aus Sicherheitsgründen. Zum Beispiel, wenn Sie erstellen SQL-Anweisungen naiverweise den folgenden Kommentar:

I'm just loving this website 

würde eine SQL-Syntax-Fehler verursachen, da der Apostroph von SQL als Schlusskurs interpretiert wird.

+2

schönen Punkt auf dem Apostroph - ich habe die string.replace-Methode verwendet - aber ich kann sehen, das ist viel einfacher. – Brad

+0

Sehr gut erklärt. Schön gemacht. –

+1

Selbst ein Name würde ein Problem verursachen, wenn nicht als Parameter, zB O'Tool, O'Rourke. – Martin

27

Verwenden Sie parametrisierte Abfragen, damit der Text automatisch für Sie zitiert wird.

SqlCommand command = connection.CreateCommand(); 
command.CommandText = "insert into dbo.Table (val1,val2,txt) values (@val1,@val2,@txt)"; 
command.AddParameterWithValue("val1", value1); 
command.AddParameterWithValue("val2", value2); 
command.AddParameterWithValue("txt", text); 

... 
-4

Der einfachste Weg, sich vor dieser Form der SQL-Injektion zu schützen, besteht darin, Parameter und gespeicherte Prozeduren zu verwenden, statt SQL-Anweisungen zu erstellen. (In C# oder intern zu SQL Server).

Aber ich bin mir nicht ganz sicher, ob Sie Zeit damit verbringen sollten, es sei denn, es ist Ihre Firmenpolitik, da die Chancen, dass es intern passiert, im besten Fall minimal sind, und wenn es passiert, würde ich Sie hoffen Ich würde sofort wissen, wer es ist.

+0

Natürlich würde ein verärgerter Mitarbeiter niemals versuchen, Ihre Firmendatenbank zu verschweißen. Sie müssen sich IMMER um die Sicherheit kümmern und die Best Practices befolgen. – tvanfosson

+0

Ich stimme nicht zu. Dies ist eine interne Webseite, auf die kein Ex-Mitarbeiter zugreifen darf. Auch würde ich vermuten (oder zumindest hoffen), dass der gesamte interne Traffic protokolliert wird. Sicherheitsanforderungen, müssen zusammen mit anderen Kriterien ausgewertet werden und sind möglicherweise nicht in einer Reihe von Situationen gerechtfertigt. – Bravax

+0

Wer sagt, dass du ein Ex-Angestellter sein musst, um verärgert zu sein? Gute Sicherheit verhindert Schaden und hinterlässt keine Schuld. In diesem Fall sind die Kosten für die Verwendung parametrisierter Abfragen nicht einmal sehr hoch. Es sollte die Norm sein, wenn Abfragen manuell erstellt werden. – tvanfosson

0

Ja, kann es.Lassen Sie uns sagen, dass der Kunde diese sendet:

OR 1 = 1 

, die für Ihre

SELECT * FROM admin WHERE name = @name AND password = @password 

sehr schmerzhaft sein, können Sie dies mit

+0

Die Frage war explizit über INSERT-Anweisungen. –

+0

wahr. aber vielleicht hilft die Liste – boj

0

Ja, sie können passieren. Der einfachste Weg, sich davor zu schützen, besteht darin, vorbereitete Anweisungen zu verwenden, anstatt SQL manuell zu erstellen.

Also, anstatt dies:

String sql = 
String.Format("INSERT INTO mytable (text_column) VALUES ('{0}')", 
    myTextBox.Text); // Unsafe! 

Sie würden so etwas tun:

String sql = "INSERT INTO mytable (text_column) VALUES (?)"; // Much safer 

Dann fügen Sie den Text des Textfeldes als Parameter an Ihre DbCommand, die sie verursachen automatisch entkamen und das "?" in der SQL.

0

Neben vorbereitete Anweisungen und Parameter, anstatt Strings in Ihre SQL verketten sollten Sie Folgendes tun auch:

  1. Validate und Format Benutzereingabe auf der Server-Seite. Client-seitige Validierung und Limits können mit Tools wie WebScarab oder durch Spoofing Ihres Formulars leicht umgangen werden.

  2. Konfigurieren Sie die entsprechenden Berechtigungen für das Datenbankbenutzerkonto. Die Webanwendung sollte ein separates Konto oder eine separate Rolle in Ihrer Datenbank verwenden, deren Berechtigungen nur auf die Tabellen, Ansichten und Verfahren beschränkt sind, die für die Ausführung Ihrer Anwendung erforderlich sind. Stellen Sie sicher, dass der Benutzer keine Auswahlrechte für die Systemtabellen hat

  3. Verbergen Sie detaillierte Fehlermeldungen von Benutzern und verwenden Sie weniger gebräuchliche Namen für Ihre Objekte. Es erstaunt mich, wie oft man den Servertyp (Oracle, MySQL, Sqlserver) ermitteln und grundlegende Schemainformationen in einer Fehlermeldung finden und dann Informationen aus den Tabellen 'Benutzer', 'Mitarbeiter' abrufen kann. Wenn Sie nicht Ihre Berechtigungen wie in (2) festgelegt haben, und ich kann Ihren Servertyp bestimmen, sind Sie offen für Aussagen wie diese für SQL Server

    SELECT table_name FROM information_schema.table

    EXECUTE Sp_help foundTableName

3

SQL-Injektion kann jedes Mal passieren, wenn Sie eine Abfrage an die Datenbank zurückgeben. Hier ist eine einfache Demonstration:

SQL Injection Explained

Der Schlüssel innerhalb von .NET zu tun ist, wie Dave Webb gegeben hat. Es verhindert den Injektionsversuch, indem es den gesamten String als einen zu übergebenden Parameter umfasst und alle Zeichen behandelt, die von SQL Server interpretiert werden könnten, um die Abfrage zu ändern oder zusätzliche Befehle anzuhängen.

Und es sollte darauf hingewiesen werden, dass SQL-Injektion in jeder Anwendung, nicht nur Webanwendungen auftreten kann. Und dass ein interner Angriff für eine Organisation normalerweise der teuerste ist. Man kann nicht mit Sicherheit davon ausgehen, dass ein Angriff nicht von innen kommt.

0

Verhindern Sie SQL Injection mithilfe vorbereiteter Anweisung. Die Verwendung von placehoder (?) Eliminiert vollständig die sql Injection Vulnerability. Beispiel String sql = Wählen Sie * aus user_table wobei username = '+ request.getparameter ("Benutzername") +'; statement.executeQuery (sql);

Die obige Aussage ist anfällig für SQL-Injektion.

Um es gegen sql Injektion sicher zu machen. Verwenden Sie nach dem Snippet

String sql = Wählen Sie * aus user_table wo username = ?; statement.setString (1, Benutzername);

+0

Die '?' - Syntax funktioniert nicht für alle Provider/DBs. –