mySQL String "Abfangen" bevor er im DGV angezeigt wird

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

Es gibt 24 Antworten in diesem Thema. Der letzte Beitrag () ist von Mokki.

    mySQL String "Abfangen" bevor er im DGV angezeigt wird

    Hi,
    folgendes Thema:

    Ich habe eine MySQL Datenbank, in dieser habe ich zum Beispiel drei Spalten:

    - Datum
    - String a
    - String b

    "String a" wird "Verschlüsselt" in die Datenbank geschrieben.

    Die Frage ist nun, wie "Entschlüssel" ich das BEVOR die Daten im DataTable landen?
    Wie das entschlüsseln geht weiß ich schon aber ich muss den String beim auslesen vor dem Anzeigen erst mal "abfangen".

    Zum entschlüsseln habe ich eine Funktion der ich dann eben diesen "String a" übergeben muss, die antwort von der Funktion soll dann anstelle von Stringa ins DGV.

    :/

    Beispielhafter Code mit dem ich die Daten in der Datenbank im DGV anzeige.

    VB.NET-Quellcode

    1. Private EventsTable As DataTable
    2. Private Sub MySQLLaden()
    3. Dim Connection As New MySqlConnection
    4. Dim command As New MySqlCommand
    5. Dim MyAdapter As MySqlDataAdapter
    6. EventsTable = New DataTable
    7. Connection.ConnectionString = My.Settings.DatenbankVerbindungsstring
    8. Connection.Open()
    9. command.Connection = Connection
    10. MyAdapter = New MySqlDataAdapter("SELECT Datum, Stringa , Stringb FROM Events WHERE benutzer='" & BenutzerName & "'", Connection)
    11. MyAdapter.Fill(EventsTable)
    12. dgvEvents.DataSource = EventsTable
    13. Connection.Close()
    14. End Sub
    Und mal wieder muss ich anmerken das das ganze 1. Unsicher ist da man das passwort auslesen kann und 2. Unsicher ist weil Mysql Injections möglich sind(höchstens du escapst BenutzerName).

    So zum Problem: Weshalb liegt das ganze verschlüsselt vor? Wie verschlüsselst du?


    Lg Mokki
    ​Smartnotr - ein intelligentes Notizprogramm
    zum Thread

    1. Unsicher ist da man das passwort auslesen kann

    Mir ist klar, dass man das Passwort sehen kann wenn sich jemand die Mühe macht und es durch einen decompiler jagt.

    2. Unsicher ist weil Mysql Injections möglich sind(höchstens du escapst BenutzerName)

    Was meinst du damit? Wie mach ich das?
    Hab noch nicht so viel Erfahrung zum Thema mySQL. Kennst du irgendwelche Anlaufstellen die ich Lesen kann zum Beispiel zum Thema Injections?

    Zum Ursprünglichen Problem:
    Ich habe es folgendermasen lösen können (Beispielhaft dargestellt):

    VB.NET-Quellcode

    1. Private EventsTable As DataTable
    2. Private Sub MySQLLaden()
    3. Dim Connection As New MySqlConnection
    4. Dim command As New MySqlCommand
    5. Dim MyAdapter As MySqlDataAdapter
    6. Dim StringaVerschlüsselt As String
    7. Dim StringaEntschlüsselt As String
    8. EventsTable = New DataTable
    9. Connection.ConnectionString = My.Settings.DatenbankVerbindungsstring
    10. Connection.Open()
    11. command.Connection = Connection
    12. MyAdapter = New MySqlDataAdapter("SELECT Datum, Stringa , Stringb FROM Events WHERE benutzer='" & BenutzerName & "'", Connection)
    13. MyAdapter.Fill(EventsTable)
    14. ' Die Funktion habe ich hier beispielhaft "FunktionEntschlüsseln" genannt.
    15. For t = 0 To EventsTable.Rows.Count -1
    16. StringaVerschlüsselt = EventsTable.Rows(t).Item(1).ToString
    17. StringaEntschlüsselt = FunktionEntschlüsseln(StringaVerschlüsselt)
    18. EventsTable.Rows(t).Item(1) = StringaEntschlüsselt
    19. Next
    20. dgvEvents.DataSource = EventsTable
    21. Connection.Close()
    22. End Sub


    Damit Funktioniert es.
    Hier mal der Wikipedia Artikel: de.wikipedia.org/wiki/SQL-Injection

    CFire schrieb:

    Mir ist klar


    Wenn dir des so klar ist, dann ist dir hoffentlich auch klar das der Server dann damit down ist, wenn dir jmd schaden will....


    Lg Mokki
    ​Smartnotr - ein intelligentes Notizprogramm
    zum Thread

    Ich hab mir den Tipp mit der Injection zu herzen genommen.
    Ist es so sicherer?:

    VB.NET-Quellcode

    1. Dim Connection As New MySqlConnection
    2. Dim command As New MySqlCommand
    3. Dim MyAdapter As MySqlDataAdapter
    4. EventsTable = New DataTable
    5. Connection.ConnectionString = My.Settings.DatenbankVerbindungsstring
    6. command.Connection = Connection
    7. command.CommandText = "SELECT Datum, Stringa, Stringb FROM Events WHERE benutzer= @benutzer"
    8. command.Parameters.AddWithValue("@benutzer", BenutzerName)
    9. MyAdapter = New MySqlDataAdapter
    10. MyAdapter.Fill(EventsTable)

    Es ist schonmal mehr Sicherheit, aber nein. Lies dir mal das durch: stackoverflow.com/questions/13…-to-prevent-sql-injection
    Und dann hier ev. eine Lösung: stackoverflow.com/questions/53…using-c-sharp-and-asp-net
    Ich mach des ganze halt immer mit Php, deshalb kann ich nicht 100%tig sagen, dass wenn du alles in den Links beachtest du 100%tige Sicherheit hast.

    Lg Mokki
    ​Smartnotr - ein intelligentes Notizprogramm
    zum Thread

    ErfinderDesRades schrieb:

    überarbeitung das Sql-Injection-Problem behoben

    Ja für das Query, aber dadurch kann trotzdem Code in die Datenbank gelangen(also Sql-Code).
    Deshalb hab ich auf den Artikel verlinkt...
    In der ersten Antwort wird erklärt weshalb es nicht sicher ist bzw. unter welchen Bedingungen es sicher ist. Wenn er immer und überall PDO benutzt wird nix passieren. Wenn er aber irgendwo im Code normale Querys verwendet, die Daten aus der Datenbank enthalten, dann ist es immer noch ein Einfallstor.
    Ich hab jetzt noch den Link gefunden: codeproject.com/Articles/9378/…-on-How-to-Prev#pre177376
    Das erste Query ist sicher. Aber dadurch kommt im Bsp. '; DELETE Orders;-- in die Datenbank(bis dahin passiert noch nix).
    Jetzt wird aber ein zweites Query zusammengesetzt in dem kein PDO verwendet wurde:

    C#-Quellcode

    1. // Get the valid user name and friendly name of the favourite
    2. int uid = this.GetUserID();
    3. string friendlyName = this.GetFriendlyName();
    4. // Create the SQL statement to retrieve the search criteria
    5. string sql = string.Format("SELECT Criteria FROM Favourites "+
    6. "WHERE UserID={0} AND FriendlyName='{1}'",
    7. uid, friendlyName);
    8. SqlCommand cmd = new SqlCommand(sql, this.Connection);
    9. string criteria = cmd.ExecuteScalar();
    10. // Do the search
    11. sql = string.Format("SELECT * FROM Products WHERE ProductName = '{0}'",
    12. criteria);
    13. SqlDataAdapter da = new SqlDataAdapter(sql, this.Connection);
    14. da.Fill(this.productDataSet);

    Dadurch kommt '; DELETE Orders;--, was aus der Datenbank kommt, in ein Query und dann knallts.


    Natürlich wird diese Art von Angriff nicht of ausgeführt, ich wollte aber darauf hinweisen, da er ja nach der Sicherheit gefragt hat.
    (Hoffe du kannst es jetzt nachvollziehen)
    Hinzufügen kann man natürlich auch, dass man die Zugangsdaten imme rnoch aus der Exe rauskriegt.

    Lg Mokki
    ​Smartnotr - ein intelligentes Notizprogramm
    zum Thread

    Danke =)
    Bin auf jeden Fall etwas schlauer.
    Wenn ich wieder ein paar Stunden dafür Zeit habe, werd ich mir die Thematik trotzdem genauer anschauen.

    evtl. werde ich direkt auf die PHP Lösung umsteigen, dazu muss ich das aber auch erst mal verstehen.
    Vielen Dank für die Untertützung
    Warum sollte man eine Php-Schicht zwischenschieben, wenn man eine Lösung hat, die es auch ohne Php-Schicht dazwischen löst?
    Verwende DbParameter, wie du es bereits tust, und der SqlInjection ist vorgebeugt.

    Einfacher wird sicherlich nichts, wenn du da nun noch eine PHP-Schicht einfügst. Und sicherer erst recht nicht.
    Viel Code bedeutet immer auch viele mögliche Fehlerquellen.
    Zumal du das PHP erst noch verstehen lernen musst.
    Warum sollte man eine Php-Schicht zwischenschieben, wenn man eine Lösung hat, die es auch ohne Php-Schicht dazwischen löst?


    Weil ich dann die Zugangsdaten doch nicht mehr im QuellCode habe.
    Mir wäre es am liebsten ohne PHP aber ich wüsste nicht, wie ich die Zugangsdaten sonst "Verstecken" kann.

    Zumal du das PHP erst noch verstehen lernen musst.

    Da hast du durchaus Recht.
    ZugangsDaten muss der User haben, was anneres geht nicht.

    Oder wie soll das funzen, dass wenn dein Proggi die Zugangsdaten auffm Server nutzen kann, dass dann ein Angreifer das nicht ebenfalls wird können?

    Ausserdem musste dich um TSL-verschlüsselte Kommunikation kümmern, sonst können deine User abgehört werden.
    Du hast mich falsch verstanden.
    Ich meinte nicht die Zugangsdaten vom Benutzer, sondern die vom SQL Server.

    Irgendwo im QuellCode muss ich ja den ConnectionString unter bringen, soweit ich das überflogen und verstanden habe, liegt eben dieser auf den Servern und nicht im VB QuellCode.
    Ich kann mich auch täuschen.
    Das Problem zu lösen ist ganz einfach. Du hast ja 2 Funktionen, die Decrypt Funktion ( um etwas zu verschlüsseln ) und die Encrypt Funktion. Falls du die Encrypt Funktion nicht hast, hier ist sie. Dazu musst du noch die Imports System.Security.Cryptography und System.Text machen:


    VB.NET-Quellcode

    1. Dim MD5 As New MD5CryptoServiceProvider
    2. Dim DES As New TripleDESCryptoServiceProvider
    3. Function MD5Hash(value As String) As Byte()
    4. Return MD5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(value))
    5. End Function
    6. Function Encrypt(StringInput As String, Key As String) As String
    7. DES.Key = MD5Hash(Key)
    8. DES.Mode = CipherMode.ECB
    9. Dim buffer As Byte() = ASCIIEncoding.ASCII.GetBytes(StringInput)
    10. Return Convert.ToBase64String(DES.CreateEncryptor().TransformFinalBlock(buffer, 0, buffer.Length))
    11. End Function


    Nachdem du die Datenbank mit dem DGV verbunden hast, machst du folgendes:

    VB.NET-Quellcode

    1. For i As Integer = 0 To Acces.DBDT.Rows.Count - 1
    2. Acces.DBDT.Rows(i)(4) = Decrypt(Acces.DBDT.Rows(i)(4), "key")
    3. Next

    ERKLÄRUNG: Das machst du mit jeder Spalte die du entschlüsseln willst. Im Befehl "Acces.DBDT.Rows(i)(..)<-- Da musst du die ID der Spalte angeben. Bedenke das die Anfangszahl 0 ist. Das heißt du möchtest die 1. zeile entschlüsseln? Dann wäre der Code so:





    VB.NET-Quellcode

    1. Dim MD5 As New MD5CryptoServiceProvider
    2. Dim DES As New TripleDESCryptoServiceProvider
    3. Function MD5Hash(value As String) As Byte()
    4. Return MD5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(value))
    5. End Function
    6. Function Encrypt(StringInput As String, Key As String) As String
    7. DES.Key = MD5Hash(Key)
    8. DES.Mode = CipherMode.ECB
    9. Dim buffer As Byte() = ASCIIEncoding.ASCII.GetBytes(StringInput)
    10. Return Convert.ToBase64String(DES.CreateEncryptor().TransformFinalBlock(buffer, 0, buffer.Length))
    11. End Function
    12. Private Sub RefreshGrid()
    13. Acces.ExecQuery("SELECT * FROM table")
    14. Try
    15. For i As Integer = 0 To Acces.DBDT.Rows.Count - 1
    16. Acces.DBDT.Rows(i)(4) = Decrypt(Acces.DBDT.Rows(i)(4), "key")
    17. Next
    18. End Try
    19. End Sub





    Zur Erklärung, die "Acces" Funktion ist keine von VB.NET. Das ist eine von mir erstellte Klasse. Falls du die auch kopieren willst ( die kannst du einfach so kopieren und in deinen Code stecken ), da hast du sie. Ich mag es nicht solche Wizzards zu benutzen. Darum habe ich eine eigene Funktion dafür erstellt.

    VB.NET-Quellcode

    1. Imports System.Data.OleDb
    2. Public Class DBControl
    3. 'VERBINDUNG ZUR DATENBANK HERSTELLEN
    4. Public DBCon As New OleDbConnection("Provider= Microsoft.ACE.OLEDB.12.0;" &
    5. "Data Source=DB.accdb")
    6. 'DB Befehl Vorbereiten
    7. Public DBcmd As OleDbCommand
    8. 'DB Daten
    9. Public DBAD As OleDbDataAdapter
    10. Public DBDT As DataTable
    11. 'QUERY PARAMETERS
    12. Public Params As New List(Of OleDbParameter)
    13. 'QUERY STATISTIKEN
    14. Public RecordCount As Integer
    15. Public Exception As String
    16. Public Sub ExecQuery(Query As String)
    17. 'NEULADEN VON STATISTIKEN
    18. RecordCount = 0
    19. Exception = ""
    20.  
    21. Try
    22. 'VERBINDUNG ÖFFNEN
    23. DBCon.Open()
    24. 'DB BEFEHL HERSTELLEN
    25. DBcmd = New OleDbCommand(Query, DBCon)
    26. 'LADEN VON PARAMETERN IN DBcmd
    27. Params.ForEach(Sub(p) DBcmd.Parameters.Add(p))
    28. 'REINIGEN VON PARAMETERN
    29. Params.Clear()
    30. 'DURCHFÜHREN DES BEFEHLS & FÜLLEN VON DATATABLE
    31. DBDT = New DataTable
    32. DBAD = New OleDbDataAdapter(DBcmd)
    33. RecordCount = DBAD.Fill(DBDT)
    34.  
    35.  
    36.  
    37.  
    38. Catch ex As Exception
    39. Exception = ex.Message
    40. End Try
    41. 'DATENBANK SCHLIESSEN
    42. If DBCon.State = ConnectionState.Open Then DBCon.Close()
    43.  
    44.  
    45. End Sub
    46.  
    47.  
    48.  
    49.  
    50.  
    51. Public Sub AddParam(Name As String, Value As Object)
    52. Dim NewParam As New OleDbParameter(Name, Value
    53. )
    54. Params.Add(NewParam)
    55.  
    56. End Sub
    57. End Class






    So ich hoffe damit klappts. Falls nicht, sag mir das dann schreibe ich dir nochmal.
    MFG Cedric
    Nein bitte kein MD5.... verwende SHA1 bittte.
    MD5 gilt nicht mehr als sicher, da die heutigen Pc so schnell sind, dass ein Brute-Force Angrifd möglich ist..... (und auch schon durchgeführt wird.....)
    Und auch kein DES sondern AES....

    Lg Mokki
    ​Smartnotr - ein intelligentes Notizprogramm
    zum Thread