SQLight Sicherheit und Codeanalysen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 35 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    SQLight Sicherheit und Codeanalysen

    Moin moin

    Ich versuche mich gerade mit SQLight zu beschäftigen, weil ich von Access 2003 Datenbanken weg möchte.
    Soweit klappt das ja mit den Abfragen nur diese Codeanalyse bzgl der "Sicherheit" macht mich <X :S

    Warnung CA2100 Die in 'DBConnection.LoadTableColumns(String)' an 'SQLiteCommand.CommandText.Set(String)' übergebene Abfragezeichenfolge könnte die folgenden 'DBConnection.QuoteIdentifier(tableName)'-Variablen enthalten.
    Wenn eine dieser Variablen aus Benutzereingaben stammt, sollten Sie eine gespeicherte Prozedur oder eine parametrisierte SQL-Abfrage verwenden, anstatt die Abfrage mit Zeichenfolgenverkettungen zu erstellen.
    SqLightTest A:\Entwicklung\2024\SqLightTest\SqLightTest\DBConnection.vb 38 Aktiv


    Die Zeile:

    VB.NET-Quellcode

    1. command.CommandText = query



    Spoiler anzeigen

    Auf dem Form:

    VB.NET-Quellcode

    1. Public Class FrmMain
    2. Public Sub New()
    3. AddHandler DBConnection.TablesLoaded, AddressOf DBConnection_DBTabels
    4. AddHandler DBConnection.ColumnsLoaded, AddressOf DBConnection_TableColums
    5. InitializeComponent()
    6. End Sub
    7. Private Sub DBConnection_TableColums(ByVal colnames As List(Of String))
    8. ListBoxCategory.DataSource = colnames
    9. End Sub
    10. Private Sub DBConnection_DBTabels(ByVal tablesnames As List(Of String))
    11. ListBoxTables.DataSource = tablesnames
    12. End Sub
    13. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    14. DBConnection.LoadTables()
    15. End Sub
    16. Private Sub ListBoxTables_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBoxTables.SelectedIndexChanged
    17. If ListBoxTables.SelectedItem IsNot Nothing Then
    18. DBConnection.SelectedTable = ListBoxTables.SelectedItem.ToString()
    19. Debug.WriteLine(DBConnection.SelectedTable)
    20. DBConnection.LoadTableColumns(DBConnection.SelectedTable)
    21. End If
    22. End Sub
    23. End Class

    Im Modul:

    VB.NET-Quellcode

    1. Module DBConnection
    2. Private connection As SQLiteConnection
    3. Public Event TablesLoaded(ByVal tableNames As List(Of String))
    4. Public Event ColumnsLoaded(ByVal cloumnList As List(Of String))
    5. Public Property SelectedTable As String
    6. Public ReadOnly DataBaseName As String = "northwindEF.db"
    7. Private Sub Con2DataBase()
    8. Dim databasePath As String = Path.Combine(Application.StartupPath, DataBaseName)
    9. Dim connectionString As String = $"Data Source={databasePath};Version=3;"
    10. connection = New SQLiteConnection(connectionString)
    11. connection.Open()
    12. End Sub
    13. Public Sub CloseConnection()
    14. If connection IsNot Nothing AndAlso connection.State = ConnectionState.Open Then
    15. connection.Close()
    16. End If
    17. End Sub
    18. Public Sub LoadTableColumns(tableName As String)
    19. ' Zur DB verbinden und öffnen
    20. Con2DataBase()
    21. Dim columnList As New List(Of String)()
    22. ' Sicheren Tabellennamen erstellen
    23. Dim query As String = $"PRAGMA table_info({QuoteIdentifier(tableName)})"
    24. ' SQLiteCommand mit parametrisierter Abfrage
    25. Using command As New SQLiteCommand(connection)
    26. command.CommandText = query
    27. command.Parameters.AddWithValue("@tableName", tableName)
    28. Using reader As SQLiteDataReader = command.ExecuteReader()
    29. While reader.Read()
    30. Dim columnName As String = reader("name").ToString()
    31. columnList.Add(columnName)
    32. End While
    33. End Using
    34. End Using
    35. CloseConnection()
    36. RaiseEvent ColumnsLoaded(columnList)
    37. End Sub
    38. Private Function QuoteIdentifier(identifier As String) As String
    39. ' Funktion zum Sicheren Umgeben von Tabellen-/Spaltennamen mit Anführungszeichen
    40. Return $"`{identifier.Replace("`", "``")}`"
    41. End Function
    42. Public Sub LoadTables()
    43. ' Zur DB verbinden und öffnen
    44. Con2DataBase()
    45. Dim tableNames As New List(Of String)()
    46. ' sqlite_master, um Informationen zu den Tabellen zu erhalten
    47. Using command As New SQLiteCommand("SELECT name FROM sqlite_master WHERE type='table' AND name <> 'sqlite_sequence'", connection)
    48. Using reader As SQLiteDataReader = command.ExecuteReader()
    49. While reader.Read()
    50. Dim tableName As String = reader("name").ToString()
    51. tableNames.Add(tableName)
    52. End While
    53. End Using
    54. End Using
    55. CloseConnection()
    56. RaiseEvent TablesLoaded(tableNames)
    57. End Sub
    58. End Module


    *Topic verschoben*
    Bilder
    • sqlight-1.jpg

      170,33 kB, 684×363, 76 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Du solltest dir vielleicht mal Prepared Statements anschauen. Damit übergibst du keine "rohen" Variablen, sondern die Bibliothek nimmt deine Variablen separat und sieht zu, dass du die Abfrage escapest; sprich verhindert, dass ungefilterter Input eine Sicherheitslücke darstellt.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.

    Amelie schrieb:

    ' Sicheren Tabellennamen erstellen
    Dim query As String = $"PRAGMA table_info({QuoteIdentifier(tableName)})"
    ' SQLiteCommand mit parametrisierter Abfrage
    Using command As New SQLiteCommand(connection)
    command.CommandText = query
    command.Parameters.AddWithValue("@tableName", tableName)


    versuche es mal do:

    VB.NET-Quellcode

    1. ​Dim query As String = $"PRAGMA table_info(@tableName))"
    2. ' SQLiteCommand mit parametrisierter Abfrage
    3. Using command As New SQLiteCommand(connection)
    4. command.CommandText = query
    5. command.Parameters.AddWithValue("@tableName", QuoteIdentifier(tableName))
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    Ich habe nun etliches ausprobiert. Diese Warnung bekomme ich einfach nicht weg. :(
    Hier nur mal 3 Teile die ich probiert habe.


    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Sub LoadTableColumns(tableName As String)
    2. ' Zur DB verbinden und öffnen
    3. Con2DataBase()
    4. Dim columnList As New List(Of String)()
    5. Using command As New SQLiteCommand(connection)
    6. Dim quotedTableName As String = QuoteIdentifier(tableName)
    7. Dim query As String = $"PRAGMA table_info({quotedTableName})"
    8. command.CommandText = query
    9. Using reader As SQLiteDataReader = command.ExecuteReader()
    10. While reader.Read()
    11. Dim columnName As String = reader("name").ToString()
    12. columnList.Add(columnName)
    13. End While
    14. End Using
    15. End Using
    16. CloseConnection()
    17. RaiseEvent ColumnsLoaded(columnList)
    18. End Sub
    19. Public Sub LoadTableColumns(tableName As String)
    20. ' Zur DB verbinden und öffnen
    21. Con2DataBase()
    22. Dim columnList As New List(Of String)()
    23. Dim query As String = $"PRAGMA table_info({tableName})"
    24. Debug.WriteLine($"Class: {query}")
    25. Using command As New SQLiteCommand(connection)
    26. command.CommandText = query
    27. command.Parameters.AddWithValue("@tableName", QuoteIdentifier(tableName))
    28. Using reader As SQLiteDataReader = command.ExecuteReader()
    29. While reader.Read()
    30. Dim columnName As String = reader("name").ToString()
    31. columnList.Add(columnName)
    32. End While
    33. End Using
    34. End Using
    35. CloseConnection()
    36. RaiseEvent ColumnsLoaded(columnList)
    37. End Sub
    38. Public Sub LoadTableColumns(tableName As String)
    39. ' Zur DB verbinden und öffnen
    40. Con2DataBase()
    41. Dim columnList As New List(Of String)()
    42. Dim query As String = $"PRAGMA table_info({tableName})"
    43. Debug.WriteLine($"Class: {query}")
    44. Using command As New SQLiteCommand(query, connection)
    45. command.Parameters.AddWithValue("@tableName", QuoteIdentifier(tableName))
    46. Using reader As SQLiteDataReader = command.ExecuteReader()
    47. While reader.Read()
    48. Dim columnName As String = reader("name").ToString()
    49. columnList.Add(columnName)
    50. End While
    51. End Using
    52. End Using
    53. CloseConnection()
    54. RaiseEvent ColumnsLoaded(columnList)
    55. End Sub

    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Jo, was siycah als "prepared Statement" bezeichnet, stellt sich in der .Net Welt als parametrisiertes DbCommand dar - so wie'ss INOPIAE vormacht.

    Nur musst du es auch so machen, wie ers vormacht. Schau genau an, was er als query baut, und was du.
    Er verwendet einen Platzhalter im CommandText.



    Was anderes: Architektonisch ists höchst unangebracht, die ColumnList als Event an iwelche Empfänger zu verteilen.
    Schreib stattdessen eine Function, die die ColumnList einfach returnt.
    (Ist dir das ühaupt bekannt, dass Functions einen Wert returnen können?)
    Probier ma:

    VB.NET-Quellcode

    1. Dim query As String = $"PRAGMA table_info(@{tableName})"


    Aber du solltest nicht die Verbindung für jeden query öffnen und schliessen. Im Konstruktor oder einer Sub die Connection aufbauen, IDisposeable implementieren beim Disposen schliessen wenn offen und alles disposen was zu disposen ist.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    Hallo;

    Ich habe das:
    Dim query As String = $"PRAGMA table_info(@{tableName})"
    Dim query As String = $"PRAGMA table_info({@tableName})"

    Und alles mögliche getestet.

    VB.NET-Quellcode

    1. Dim newTable As String = "Regions" '<=== HIER mit fixen Tabellennamen ist ALLES OK!!
    2. ' Sicheren Tabellennamen erstellen
    3. Dim query As String = $"PRAGMA table_info({QuoteIdentifier(newTable)})"


    Einiges bring gleich einen Absturz.....
    Sobald ich das: Public Property SelectedTable As String
    verwende kommt die Warnung.

    Der letzte Code der funktioniert ABER noch immer die Warnung CA2100 wirft.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Sub LoadTableColumns(tableName As String)
    2. ' Zur DB verbinden und öffnen
    3. Con2DataBase()
    4. Dim columnList As New List(Of String)()
    5. Dim query As String = $"PRAGMA table_info({tableName})"
    6. Debug.WriteLine($"Class: {query}")
    7. Using command As New SQLiteCommand(connection)
    8. command.CommandText = query
    9. command.Parameters.AddWithValue("@tableName", QuoteIdentifier(tableName))
    10. Using reader As SQLiteDataReader = command.ExecuteReader()
    11. While reader.Read()
    12. Dim columnName As String = reader("name").ToString()
    13. columnList.Add(columnName)
    14. End While
    15. End Using
    16. End Using
    17. CloseConnection()
    18. RaiseEvent ColumnsLoaded(columnList)
    19. End Sub
    20. Private Function QuoteIdentifier(identifier As String) As String
    21. Return $"`{identifier.Replace("`", "``")}`"
    22. End Function



    -----
    Das ganze ist erstmal um mich mit SQLight zu beschäftigen. Deswegen das simple Event usw...
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Fehler / Absturz
    Dim query As String = $"PRAGMA table_info(@{tableName})"
    Debug.WriteLine($"Class: {query}")

    Fehlermeldung:
    Class: PRAGMA table_info(@Regions)
    SQLite error (1): near "@Regions": syntax error in "PRAGMA table_info(@Regions)"
    Ausnahme ausgelöst: "System.Data.SQLite.SQLiteException" in System.Data.SQLite.dll
    Ausnahme ausgelöst: "System.Data.SQLite.SQLiteException" in System.Data.SQLite.dll

    Keine Fehler aber CA 2100 Warnung
    Dim query As String = $"PRAGMA table_info({tableName})"
    Debug.WriteLine($"Class: {query}")
    ..
    command.CommandText = query <== Hier wird IMMER die Warnung angezeigt...
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Dim query As String = $"PRAGMA table_info(@{tableName})"

    das muss immer noch so lauten, achte auf die Klammern:

    VB.NET-Quellcode

    1. String = "PRAGMA table_info(@tableName)"


    Und ich glaube nicht, dass Du die Funktion QuoteIdentifier benötigst. Der Parameteraufruf sorgt eigentlich für das richtige Format.
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „INOPIAE“ ()

    @INOPIAE

    Das hatte ich auch schon getestet!! So kommt dann kein verwertbarer Ausdruck an. Deswegen hatte ich ja diese{} darum gemacht aber dann muss auch das @ weg...
    Debugausgabe: ==> Class: PRAGMA table_info(@tableName)
    SQLite error (1): near "@tableName": syntax error in "PRAGMA table_info(@tableName)"
    Ausnahme ausgelöst: "System.Data.SQLite.SQLiteException" in System.Data.SQLite.dll


    VB.NET-Quellcode

    1. Public Sub LoadTableColumns(tableName As String)
    2. ' Zur DB verbinden und öffnen
    3. Con2DataBase()
    4. Dim columnList As New List(Of String)()
    5. Dim query As String = "PRAGMA table_info(@tableName)"
    6. Debug.WriteLine($"Class: {query}")
    7. Using command As New SQLiteCommand(connection)
    8. command.CommandText = query
    9. command.Parameters.AddWithValue("@tableName", QuoteIdentifier(tableName))
    10. Using reader As SQLiteDataReader = command.ExecuteReader()
    11. While reader.Read()
    12. Dim columnName As String = reader("name").ToString()
    13. columnList.Add(columnName)
    14. End While
    15. End Using
    16. End Using
    17. CloseConnection()
    18. RaiseEvent ColumnsLoaded(columnList)
    19. End Sub
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    SQLite error (1): near "@tableName": syntax error in "PRAGMA table_info(@tableName)"
    Tja, wenn PRAGMA table_info(@tableName) einen SqLite-SyntaxError gibt, dann wäre das erste, die SqLite-Syntax-Doku nachzulesen.
    Vielleicht kann SqLite keine benannten Parameter, und erwartet ? stattdessen? Oder wasweissich - ich werd die SqLite-Syntax-Doku jetzt nicht nachlesen
    Guten Morgen

    Also ich habe etwas gelesen und wie ich schrieb habe so viel getestet.

    Wenn ich mir hier das Result ausgeben lasse:

    VB.NET-Quellcode

    1. Dim query As String = "PRAGMA table_info(@tableName)"
    2. Debug.WriteLine($"Class: {query}")

    und dann da keine der Tabellen drinsteht, stimmt etwas nicht. Und bei egal was ich als Platzhalter, in welcher Form auch immer versucht habe (@ ' + : ? ...) funktioniert es nicht.

    Bei diesem funktioniert es nur das dann eben wieder diese CA2100 Warnung erscheint.

    VB.NET-Quellcode

    1. Dim query As String = $"PRAGMA table_info({tableName})"
    2. Debug.WriteLine($"Class: {query}")


    Wenn es nicht geht, dann lasse ich es eben.
    Im übrigen, nur um sicher zu gehen, habe ich diese "Codeanalyse" sowohl mit VS 2015 und VS 2017 durchgeführt!
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    @ErfinderDesRades
    Nein geht auch nicht, weil auch hier kein "Tabellenname" ankommt.

    Hier mein letzter Versuch, der zwar funktioniert ABER noch immer den "CA2100" wirft.


    VB.NET-Quellcode

    1. Public Sub LoadTableColumns(tableName As String)
    2. Con2DataBase()
    3. Dim columnList As New List(Of String)()
    4. Dim query As String = $"PRAGMA table_info({QuoteIdentifier(tableName)})"
    5. Debug.WriteLine($"Class: {query}")
    6. Using command As New SQLiteCommand(query, connection) ' <==== Zeile 47!
    7. Using reader As SQLiteDataReader = command.ExecuteReader()
    8. While reader.Read()
    9. Dim columnName As String = reader("name").ToString()
    10. columnList.Add(columnName)
    11. End While
    12. End Using
    13. End Using
    14. CloseConnection()
    15. RaiseEvent ColumnsLoaded(columnList)
    16. End Sub
    17. Private Function QuoteIdentifier(identifier As String) As String
    18. Return $"`{identifier.Replace("`", "``")}`"
    19. End Function



    Schweregrad Code Beschreibung Projekt Datei Zeile Unterdrückungszustand
    Warnung CA2100 Die in 'DBConnection.LoadTableColumns(String)' an 'SQLiteCommand.New(String, SQLiteConnection)' übergebene Abfragezeichenfolge könnte die folgenden 'DBConnection.QuoteIdentifier(tableName)'-Variablen enthalten.
    Wenn eine dieser Variablen aus Benutzereingaben stammt, sollten Sie eine gespeicherte Prozedur oder eine parametrisierte SQL-Abfrage verwenden, anstatt die Abfrage mit Zeichenfolgenverkettungen zu erstellen.
    SqLightTest A:\Entwicklung\2024\SqLightTest\SqLightTest\DBConnection.vb 47 Aktiv
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Also mit Tablenamen scheint es nicht zu gehen, nur bei parametern. Das es mit den Tablenamen nicht geht, ist aber nicht schlimm. Denn Tablenamen fliessen im Normalfall nicht durch Usereingaben in den Query ein.

    Wenn du so die Parameter bindest sollte es gut sein:

    C#-Quellcode

    1. private void PrintPersonID(string name)
    2. {
    3. using (SqliteCommand command = DbConnection.CreateCommand())
    4. {
    5. command.CommandText = "SELECT id FROM person WHERE name = @name";
    6. command.Parameters.AddWithValue("@name", name);
    7. using (SqliteDataReader reader = command.ExecuteReader())
    8. {
    9. while (reader.Read())
    10. {
    11. Debug.WriteLine(reader.GetValue(reader.GetOrdinal("id")));
    12. }
    13. }
    14. }
    15. }

    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D