SQL Injection verhindern



  • Hallo Forum,

    ich benutze ein System wo ich kein Parameter Klassensystem benutzen kann. Ich muß SQL Injection bei den Kundeneingaben manuell verhindern. Als Datenbank wird MS SQL Server verwendet.

    1. Um SQL Injection zu verhindern müsste es doch reichen die Hochkomma zu entschärfen? Zum Beispiel indem sie verdoppelt werden. Der böse SQL Code wäre damit wieder innerhalb eines Strings. Ich muß VB.net benutzen, auf den Backslash zum Maskieren des Hochkommas muss ich somit nicht extra beachten.

    Ich habe es jetzt so gemacht:

    ''' <summary>
    ''' SQL Injection verhindern indem das Escapen mit den Hochkommas unterbunden wird.
    ''' Durch Verdopplung der Hochkommas. Bereits verdoppelte Hochkommas werden so belassen.
    ''' </summary>
    ''' <param name="Parameter">Der Parameter</param>
    ''' <returns>Der gesäuberte Parameter</returns>
    ''' <remarks></remarks>
    Private Shared Function RemoveSqlInj(Parameter As String) As String
        Dim ParameterArray As String() = Parameter.Split(New String() {"''"}, StringSplitOptions.None)
        Dim RetVal As String = ""
        For i As Integer = 0 To ParameterArray.Length - 1
            If i > 0 then RetVal += "''"
            RetVal += ParameterArray(i).Replace("'", "''")
        Next i
    
        Return RetVal
    End Function
    

    2. Die anderen Hochkommas werden scheinbar hier nicht verwendet. Ich kann mich aber erinnern das bei einem anderen SQL Dialekt andere Hochkommas verwendet werden.

    3. Gibt es eigentlich ein Klassensystem das mit die SQL Stmnts generiert?
    Sowas in der Art:

    using (SqlCommand command = new SqlCommand("SELECT * FROM Tab1 WHERE Name LIKE @Name", connection)) {
    	command.Parameters.Add(new SqlParameter("Name", dogName));
    
    	//SqlDataReader reader = command.ExecuteReader(); // So nicht.
    
    	// Stattdessen schicke ich das SQL über die andere Schnittstelle.
    	string Sauberes_SQLStmnt = command.ToSQL()
    	MySpecialSQLCon.Execute(Sauberes_SQLStmnt)
    


  • Du suchst Prepared Statements.



  • ich benutze ein System wo ich kein Parameter Klassensystem benutzen kann

    Und welches wäre das?



  • Ich finde gerade keine Prepared Statements bei .net? Google verweist mich immer auf die SqlCommand Klasse und dort kann ich das zusammengesetzte SQL Stmnt nicht herausziehen.

    Ich steuere über die DI Schnittstelle von Business One eine MS SQL Datenbank an. In die DI Schnittstelle kann ich SQL Stmnts eintüten, zB für Views. Aber ich finde keine Möglichkeit die Parameter 'sicher' in den SQL-String zu legen. Aktuell begnüge ich mich damit keine ungerade Anzahl von Hochkommata zuzulassen.





  • Ah, du verwendest also gar nicht .NET sondern eine externe API.
    Sag das doch gleich. Dann musst du wohl dort in die Doku schauen.



  • Es ist .net, aber die Datenbankverbindung läuft über die DI Schnittstelle von SAP B1.



  • abcd schrieb:

    1. Um SQL Injection zu verhindern müsste es doch reichen die Hochkomma zu entschärfen?

    Im Prinzip, einfach gesagt: ja.
    Das Problem ist bloss dass man es nirgends vergessen darf. Und genau das macht die Sache unsicher. Wenn man sich angewöhnt grundsätzlich nie SQL Strings dynamisch zusammenzubauen, und alles über Parameter zu machen, ist das viel einfacher konsequent durchzuziehen.

    abcd schrieb:

    2. Die anderen Hochkommas werden scheinbar hier nicht verwendet. Ich kann mich aber erinnern das bei einem anderen SQL Dialekt andere Hochkommas verwendet werden.

    Wäre mir neu. Ist aber nicht schwer zu checken - guck einfach in die Doku zum SQL Dialekt deines Servers.
    Was du auch noch beachten solltest sind "special characters" in LIKE Strings. Also falls du LIKE irgendwo mit Strings verwendest die teilweise vom User stammen. Da muss dann z.B. "%" auch escaped werden, und oft auch weitere Zeichen die sonst eine spezielle Bedeutung hätten.

    abcd schrieb:

    3. Gibt es eigentlich ein Klassensystem das mit die SQL Stmnts generiert?
    Sowas in der Art:

    using (SqlCommand command = new SqlCommand("SELECT * FROM Tab1 WHERE Name LIKE @Name", connection)) {
    	command.Parameters.Add(new SqlParameter("Name", dogName));
    
    	//SqlDataReader reader = command.ExecuteReader(); // So nicht.
    
    	// Stattdessen schicke ich das SQL über die andere Schnittstelle.
    	string Sauberes_SQLStmnt = command.ToSQL()
    	MySpecialSQLCon.Execute(Sauberes_SQLStmnt)
    

    Gibt es sicher irgendwo von irgendwem - würde mich sehr wundern wenn das noch keiner gemacht hätte.
    Nur nix im .NET Framework, und ich kenne auch sonst keine Library die ich empfehlen könnte.
    Ist aber relativ einfach selbst zu basteln.
    Dazu musst du ja keinen vollständigen SQL Parser schreiben. Dazu musst du bloss zwei Dinge "wissen":

    1. Welche @ an einer Stelle stehen wo Parameter ersetzt werden können
    2. Wie SQL Literals für die Datentypen aussehen die du unterstützen willst

    1 ist relativ easy: Alles was nicht Teil eines SQL String-Literals ist, nicht Teil eines gequoteten Identifiert etc. ist, und nicht Teil eines Kommentars ist, kann ersetzt werden.
    D.h. du musst nur die Regeln dafür wo Literals, gequotete Identifier und Kommentare anfangen und aufhören implementieren.

    Und 2 ist noch einfacher. Integers einfach dezimal rausknallen, Daten z.B. als "CONVERT(...)" formatieren, Strings eben als Strings (hier wird dann escaped), bools als 0 oder 1 usw. Inklusive der jeweiligen Casts halt damit der Datentyp passt (sonst weiss der SQL Server ja nicht ob 42 z.B. ein INT oder SMALLINT oder BIGINT sein soll).

    Also z.B. nen short Parameter mit Wert 2 machst du zu " CAST(2 AS SMALLINT) ", nen bool mit Wert true machst du zu " CAST(1 AS BIT) " etc.
    Nen DateTime machst du z.B. zu " CONVERT(DATETIME, 126, '2016-08-10T17:55:00.123') " - bzw. was entsprechendes für den SQL Dialekt den du unterstützen musst.
    Und den String "Sag's mit SQL" machst du zu " N'Sag''s mit SQL' ".





  • @Hustbaer: Danke für deine ausführliche Hilfe. 🙂
    Die Like Parameter hatte ich gar nicht auf dem Schirm. Da geht es dann aber nur darum das jemand das Ergebnis von Suchergebnissen beeinflussen könnte. In meinem Fall ist das nicht relevant.


Anmelden zum Antworten