Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs

Verhinderung von SQL Injection Marke .NET

Geschrieben von: Christoph Wille
Kategorie: Sicherheit

This printed page brought to you by AlphaSierraPapa

Was SQL Injection ist, hat der erste Artikel dieser Serie ausführlich erklärt und auch demonstriert. In Folge 2, Gegengifte für SQL Injection, ging es dann um Wege mittels Inputvalidierung SQL Injection zu verhindern, und auch mittels ADO eine Art letzte Bastion zu errichten. Heute wechseln wir von ASP nach ASP.NET, und von ADO zu ADO.NET - und sehen uns die dortigen Abwehrmethoden an.

Ich möchte auch heute wieder den Spruch Michael Howard's wiederholen: All input is evil, until proven otherwise!

Wie man Input validieren kann, haben wir im Artikel Gegengifte für SQL Injection bereits besprochen. Als wichtigste Waffe zur Validierung des Inputs stehen unter .NET (Überraschung!) Regular Expressions zur Verfügung - wer also in ASP RegEx gelernt hat, kann dieses Wissen unter .NET wieder einsetzen. Wer's noch nicht gemerkt hat: ich halte RegEx für eine der wichtigsten Techniken die ein Programmierer beherrschen sollte.

Mit Inputvalidierung werden wir uns heute außer im obigen Absatz nicht weiter beschäftigen - statt dessen möchte ich Codebeispiele zeigen: zuallererst eines, das man sich als schlechtes Beispiel unbedingt immer vor Augen halten sollte, sowie ein weiteres, das man sich aus anderen Gründen merken sollte: weil man in Zukunft nur noch so programmieren sollte!

So in Zukunft nicht mehr

Ich habe ein Beispiel nach alter Verfahrensweise geschrieben - der SQL String wird dynamisch zusammengebaut, was bei unzureichender Überprüfung der übergebenen Daten zur SQL Injection führt (jessas.aspx):

<%@Page Language="C#" %>
<%@Import Namespace="System.Data" %>
<%@Import Namespace="System.Data.SqlClient" %>
<%
string strImagineAsQuerystring = "HANAR";

string strConn = "user id=restricted;password=uX98x00;initial catalog=northwind;" + 
                     "data source=WEBDEVSRV01;Connect Timeout=30";
SqlConnection scNWind = new SqlConnection(strConn);
scNWind.Open();

SqlCommand cmd = new SqlCommand();
cmd.CommandText = "select sum(freight) from Orders " + 
        " where CustomerId = '" + strImagineAsQuerystring + "'";
cmd.Connection = scNWind;

object RetVal = cmd.ExecuteScalar();
Response.Write(RetVal.ToString());

cmd.Dispose();
scNWind.Close();
%>

Ist die Variable strImagineAsQuerystring nicht genügend überprüft, so kann ein Hacker wie im Artikel SQL Injection beschrieben, ein beliebiges SQL Kommando gegen die Datenbank absetzen. Die Überprüfung (Inputvalidierung) sollte man also auf Fälle durchführen - und zwar am besten mit Regular Expressions, siehe dazu auch die Hinweise/Links im Artikel Gegengifte für SQL Injection.

Aber ADO.NET hat noch ein zusätzliches "Zuckerl" für uns, das den Hahn für immer zudreht - und um einiges bequemer funktioniert als in ADO.

Parametrisierte Abfragen

Vorhang auf für parametrisierte Abfragen, den "kleinen Bruder" (oder Schwester, falls man politisch korrekt sein möchte) von Stored Procedures. Wer keine Stored Procedures verwenden will oder kann, findet in parametrisierten Abfragen sicherlich eine probate "last line of defense" gegen SQL Injection.

Somit ohne weitere Umschweife zu einem Beispiel (mitgenuss.aspx):

<%@Page Language="C#" Debug="True" %>
<%@Import Namespace="System.Data" %>
<%@Import Namespace="System.Data.SqlClient" %>
<%
string strImagineAsQuerystring = "HANAR";
// uncomment line below to try SQL Injection (will fail)
// strImagineAsQuerystring = "' DELETE Orders --";

string strConn = "user id=sa;password=;initial catalog=northwind;" + 
                 "data source=WEBDEVSRV01;Connect Timeout=30";
SqlConnection scNWind = new SqlConnection(strConn);
scNWind.Open();

SqlCommand cmd = new SqlCommand();
cmd.CommandText = "select OrderId from Orders where CustomerId = @ParameterCustomerId";
SqlParameter param = cmd.Parameters.Add("@ParameterCustomerId", strImagineAsQuerystring);
cmd.Connection = scNWind;

SqlDataReader MySqlReader = cmd.ExecuteReader();
while (MySqlReader.Read())
{
    Response.Write(MySqlReader.GetInt32(0) + "<br>\r\n");
}
MySqlReader.Close();

cmd.Dispose();
scNWind.Close();
%>

Der richtig interessante Part ist der CommandText, also unser SQL Statement:

cmd.CommandText = "select OrderId from Orders where CustomerId = @ParameterCustomerId";

Hier steht ab sofort ein Platzhalter, nicht einmal mehr Apostrophe, obwohl es sich um ein Textfeld handelt. Klarerweise muß man den Wert dieses Parameters vor der Ausführung bekanntgeben, dies geschieht so:

SqlParameter param = cmd.Parameters.Add("@ParameterCustomerId", strImagineAsQuerystring);

Im Prinzip funktioniert alles genau gleich wie bei Stored Procedures, und mehr zu Stored Procedures in ADO.NET bietet der Artikel Stored Procedures 101 in ADO.NET. Apropos Stored Procedures - es wäre an der Zeit, sich neben Regular Expressions auch mit diesen etwas näher auseinanderzusetzen.

Schlußbemerkung

SQL Injection verschwindet auch unter .NET nicht einfach magisch. Man muß nachhelfen, aber wenn man seine Applikation von vorne herein mit Blickpunkt Sicherheit plant und programmiert, ist es kein Problem.

This printed page brought to you by AlphaSierraPapa

Download des Codes

Klicken Sie hier, um den Download zu starten.
http://www.aspheute.com/code/20011203.zip

Verwandte Artikel

Formularbasierte Authentifizierung in fünf Minuten
http:/www.aspheute.com/artikel/20020705.htm
Gegengifte für SQL Injection
http:/www.aspheute.com/artikel/20011031.htm
Performancemessungen in .NET
http:/www.aspheute.com/artikel/20011206.htm
Regex'en zu Assemblies kompilieren
http:/www.aspheute.com/artikel/20020902.htm
Reguläre Ausdrücke / Regular Expressions
http:/www.aspheute.com/artikel/20000829.htm
SQL Injection
http:/www.aspheute.com/artikel/20011030.htm
Stored Procedures 101 in ADO.NET
http:/www.aspheute.com/artikel/20010626.htm
Vorsicht Falle: Dateien, die keine sind
http:/www.aspheute.com/artikel/20020131.htm

 

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.