Eine Verbindung zur einer MySQL Datenbank sicher herstellen?



  • Genau, ich weiß nicht wirklich wie man das http(s)-Requests in C++ anwendet. Das Thema wird leider bei den ganzen Grundlagen nicht angeschnitten.
    Dabei bräuchte ich etwas Hilfe.


  • Mod

    Theoretisch müsstest du dafür einen Socket von deinem OS holen (was natürlich leider betriebssystemabhängig sein wird), dir die Anatomie eines HTTP-Requests ansehen und umsetzen (ein http-Request ist ja im Prinzip nur Text nach einem bestimmten Format), und das dann über den Socket versenden. Da das noch nicht verschlüsselt ist, müsstest du dir darum herum auch das https Protokoll ansehen und umsetzen.

    Da man das offensichtlich nichts alles selber in einer einzigen Lebenszeit schaffen kann (zumindest den Sicherheitsteil, einfache Requests bekommt man auch in einer Stunde mit rohen Sockets hin) , lässt du das aber bitte bleiben. Stattdessen suchst du dir eine Library, die das für dich macht. Da HTTP-Requests so gängig sind, ist das nicht schwer zu finden. Der Klassiker wäre libcurl, bzw. der C++-Wrapper curlpp. Google flüstert mir, dass heutzutage auch POCO einen Blick Wert sein kann, was sich wahrscheinlich etwas moderner anfühlen wird als libcurl.



  • Vielen lieben dank, das ist echt schon sehr Hilfreich.

    Das klingt ja schonmal nach einen Plan, aber curlpp klingt für mich etwas unsicher, da man ja über die URL den String rausliest oder habe ich das missverstanden?



  • Ein Blick auf Boost.Beast könnte da auch helfen, ich weiß allerdings nicht, wie hoch da die Einstiegshürden sind.


  • Mod

    @Lucius sagte in Eine Verbindung zur einer MySQL Datenbank sicher herstellen?:

    Das klingt ja schonmal nach einen Plan, aber curlpp klingt für mich etwas unsicher, da man ja über die URL den String rausliest oder habe ich das missverstanden?

    Der HTTP-Request (oder allgemein jede Form von Kommunikation) ist immer eine Abfolge von Zeichen, die natürlich einfach mitgelesen werden kann im Netzwerk. Ob das nun GET /meine/geheimen/daten HTTP/1.1 oder MEINEIGENESPROTOKOLL meine_geheimen_daten ist, macht da keinen wesentlichen Unterschied. Das hat auch nix mit der speziellen Request-Library zu tun. Deshalb ist es ja so wichtig, dass man den Verkehr verschlüsselt. Was halt leider unpraktikabel kompliziert ist, so dass man das nicht selber programmieren kann. Das ist eines der Hauptfeatures von https-Libraries, dass sie das übernehmen (wobei die das dann auch nicht selber machen, sondern wiederum Abhängigkeiten zu openssl oder ähnlichen Libraries haben).

    Wenn du Spaß hast, kannst du bei dir auf dem Rechner Wireshark oder ähnliches starten und dir den Verkehr bei einem verschlüsselten und einem unverschlüsselten Requests deines Browsers an eine einfache Webseite angucken. Unverschlüsselt ist das ein GET und eine Antwort darauf und du kannst genau mitlesen, was wie angefordert wird, und was die Antwort ist. Verschlüsselt geht es ein paar mal häufiger hin und her, aber es ist nur Zeichensalat und das einzige, was du mitlesen kannst, ist an welche IP und Port die Anfrage gerichtet ist. Was kein Geheimnis sein sollte.

    Request an Ressource '/' auf 127.0.0.1:5000 (die wirren Zeichen am Anfang sind der Ethernet/IP/TCP-Umschlag):

    Ev-à@â ¼P±
    iP'ùáGET / HTTP/1.1
    Host: 127.0.0.1:5000
    User-Agent: curl/7.55.1
    Accept: /

    Request an Ressource '/' auf 127.0.0.1:5000, aber TLS verschlüsselt (der Ethernet/IP/TCP-Teil am Anfang ist noch da und prinzipiell lesbar, das große 'E' repräsentiert z.B. IPv4 und ist auch oben zu finden):

    °DT'2REÒ¤Ò@/À¨"uíïÄ»´:ÙÒCP ¥¡da$ÖíÈüg¥DÓ£Hø®~ ÞirÂ6Ô¡õÈm Fú¶WX)þ¤Ä¤öm¦N
    5}²+ÇéÈÎr\ÚUÏóp«*Тºq²%ê˼ø·Ð2Q(µÒý³¿Àü¤ï
    æÑê(Ô´/d¸vjóKoô¨fÈÉcPÖôãÉ÷Îö¬ô³û

    (Nur ein mögliches Beispiel, die tatsächliche Zeichenfolge wird sich jedes Mal unterscheiden)

    Und das ist halt - im Gegensatz zu einem in der Anwendung selbst gespeicherten Passwort - nicht in den nächsten paar Jahrtausenden entschlüsselbar, es sei denn jemand kennt einen Angriff auf TLS 1.3 oder erfindet einen wesentlich besseren Computer.

    PS: Entschuldigung, der 2. Request ging gar nicht an 127.0.0.1, daher sah der TCP/IP Umschlag so anders aus als beim ersten Request. Da bin ich durcheinander gekommen, eben weil man den Request nicht lesen kann 😃
    Wer Spaß hat, kann ja herausfinden, wohin der 2. Request ging.



  • Vielen dank, das macht nichts, ich bin beim Lesen schon durcheinander gekommen 😁

    Aber das bringt mich echt weiter, kann ich den ohne weiteres über Curl oder POCO überhaupt mit TLS arbeiten? Ich musste ja erstmal eine Verbindung zu meinem Server über C++ hinbekommen, damit ich mir mit Wireshark das ganze ansehen kann.

    Man könnte doch gleich die GET Anfrage mit Verschlüsseln und auf dem Server wieder entschlüsseln oder bin ich da auf den Holzweg?


  • Mod

    @Lucius sagte in Eine Verbindung zur einer MySQL Datenbank sicher herstellen?:

    Man könnte doch gleich die GET Anfrage mit Verschlüsseln und auf dem Server wieder entschlüsseln oder bin ich da auf den Holzweg?

    Das ist doch genau das, was hier passiert. Ich glaube, du verstehst noch nicht so recht, wie der Vorschlag zur Architektur genau aussieht, noch wie HTTP-Requests und Verschlüsselung funktionieren. Lies am besten noch einmal ganz langsam und genau die Antworten, von dem Beitrag von hustbaer an. Schlag Begriffe nach, wenn sie dir nichts sagen.

    Ich musste ja erstmal eine Verbindung zu meinem Server über C++ hinbekommen, damit ich mir mit Wireshark das ganze ansehen kann.

    Ich dachte da eigentlich eher daran, einmal im Browser http://www.example.com/ und einmal https://www.example.com/ aufzurufen. So wirklich weiter wird dich das aber ehrlich gesagt nicht bringen. Es ist ungeheuer interessant (zumindest für mich), daher habe ich es erwähnt, aber letztlich ist die klare Empfehlung ja, dass du das auf gar keinen Fall selber implementieren sollst.

    kann ich den ohne weiteres über Curl oder POCO überhaupt mit TLS arbeiten?

    Liest du denn nicht die Anleitungen dazu?



  • Jetzt bin ich verwirrt? Die beiträge habe ich gelesen aber die Anleitung? Etwas eingelese habe ich mich in Curl und POCO, aber nicht ausreichend.

    Was ich hier oft raus lese ist, das ich dies und das nicht tun soll, aber wie ich es stattdessen tun soll ist immernoch ein rätsel…

    Ich lasse mich ja auch hier inspirieren, nur kann ich in moment nicht alle vorschläge testen, da mir der weg nicht ganz klar ist…



  • Ich würde dir davon abraten curl direkt zu nutzen. Das macht dir das Leben einfach schwerer. Verwende stattdessen eine benutzerfreundliche Library, die z.B. auf Curl aufbaut.

    Konkret würde ich https://github.com/libcpr/cpr empfehlen. Direkt am Anfang der README ist erklärt wie man z.B. einen GET Request macht. Und wie das ganze nur mit curl aussehen würde.



  • Da schon gesagt wurde, dass der Grund, wieso du C++ verwenden wolltest, so nicht haltbar ist und alternativen dazu geschildert wurden, wieso bleibst du dann nicht einfach bei C# /.Net für den Client?

    Das liefert auch gleich passende Klassen/Framworks für HTTP(s) Requests mit.

    Wobei mit ASP.Net bzw. die .Net Core version von ASP.Net man auch den http server part implementieren kann. Inklusive Kommunikation mit einer Datenbank.

    Wäre eventuell effektiver, wenn du dich mit C#/.Net besser auskennst.



  • @Lucius sagte in Eine Verbindung zur einer MySQL Datenbank sicher herstellen?:

    Vielen lieben dank für die Ausführlichen Infos. Natürlich wäre mir C# lieber, wegen der GUI/WPF, allerdings kann man die Exe ja noch viel leichter dekompilieren als C++.

    Der Trick ist ja eben dass das Programm welches du dem Endbenutzer gibst keine Geheimnisse mehr enthält. C# Anwendung für den Endbenutzer, C# Zwischenschicht am Server (die kann dann Geheimnisse enthalten), und Datenbank am Server halt für die Persistenz. Mit den aktuellen .NET Features ist das nicht wirklich sehr viel Aufwand. Und wenn du es Plattformübergreifend willst, dann gibt es da auch Möglichkeiten. Am Server sowieso, aber auch für den Client gibt es cross-plattform .NET GUI Frameworks.

    Ich wollte eine Programmiersprache wählen die zum einem Schwerer ist zu Dekompilieren und zum anderem Systemunabhängig verwendet werden kann.

    Und ich sage dir nochmal: das ist der falsche Ansatz. Um die Zugangsdaten aus einer EXE auszulesen muss man die nämlich nicht dekompilieren. Auf Linux reicht da ein einfaches strings my_exe_file in der Konsole.

    Ich habe bis jetzt keine Brauchbaren Tools gefunden, meine C++ Exe zu dekompilieren, wenn jemand welche Kennt, würde ich gerne aus eigener Sache diese erfahren 🐕

    Ghidra soll ganz gut sein. Bzw. natürlich IDA Pro, aber das kostet halt mächtig $$$.

    Nur jetzt mal zu Thema Zurück, welcher Weg ist der einfachste und sinnvollste, in C++ eine MySQL Verbindung aufzubauen ohne erst bei Fort Knox nach einem Tutorial zu fragen 😃

    Es gibt keinen einfachen und sinnvollen Weg. Du kannst es einem Angreifer etwas schwerer machen das Passwort rauszufinden. Aber wenn er gut mit einem Debugger umgehen kann, dann wird er es immer rausbekommen.

    Wenn dir das reicht, also "etwas schwerer machen", dann:

    • Verschlüssel die Zugangsdaten und leg sie im Programm als byte-Array ab.
    • Vor dem Login entschlüsselst du die Daten in ein Stack-Array und verwendest diese zum Aufbau der Verbindung.
    • Danach überschreibst du die Daten im Stack-Array wieder - per volatile char*

    Zusätzlich richtest du am Server noch ein SSL Zertifikat ein. Das Zertifikat (ohne private Key natürlich) packst du mit in das Client-Programm rein, und gibst es beim Aufbau der DB-Verbindung mit an - so dass die DB Client Library die Verbindung nur akzeptiert wenn der Server auch das richtige Zertifikat hat.

    Dadurch wird es für potentielle Angreifer schonmal um einiges schwerer:

    • Die Zugangsdaten stehen nicht mehr unverschlüsselt in der EXE
    • Wenn du Glück hast stehen die Zugangsdaten nach dem Login auch nicht mehr im Speicher des Prozesses.
    • Der Endbenutzer kann deinem Programm nicht einfach einen anderen DB-Server unterjubeln um so Serverseitig an die Login-Daten zu kommen.

    Was trotzdem bleibt ist die Möglichkeit das Programm in einem Debugger laufen zu lassen, und dann z.B. einen Breakpoint auf send zu setzen. Mit dem an dieser Stelle angehaltenen Programm wird der Angreifer gute Chancen haben die Zugangsdaten im Speicher zu finden - weil diese zu dem Zeitpunkt eben unverschlüsselt im Speicher stehen müssen, und noch dazu als Parameter im aktuellen Callstack zu finden sind.

    Also nicht gerade super schwer. Daher nochmal zum Abschluss: lass das bleiben. Mach es ordentlich, so dass das an den Endbenutzer ausgelieferte Programm einfach nichts mehr enthält was geheim bleiben müsste.



  • Die Form von Verschlüsselung macht es aber auch nur minimal schwerer. Man muss letztlich nur schauen welche Funktion die Daten sendet und geht mit einem Debugger den Fahrplan rückwärts. Früher oder später landet man in der Funktion, welche das bytearray liest (solche konstant definierten Daten findet Ghidra übrigens auch so schnell wie definierte Strings). Nun könnte man die Verschlüsselung versuchen zu verstehen, aber weil das keinen Spaß macht schaut man besser was am Ende der Funktion dabei rauskommt. Dort sieht man ja dann die Daten im Klartext. Noch schnell MySql downloaden und schon hat der Angreifer viel Spaß. Wie also @hustbaer schon gesagt bringt sowas wenig. Es ist nur eine Frage der Zeit bis das schiefgeht. Daher empfehle ich diesen Ansatz auf keinen Fall zu wählen. Schreib den Rest in einer Sprache die du kannst und verfolge den Ansatz einer MiddleWare wie hier geschrieben wurde.



  • Ich verstehe eure bedenken ja und stimme euch auch zu. Ich würde ja auch auf C# bleiben, allerdings finde ich keinen anständigen Obfuscator der .NET 6/7 kann.
    Klar kann ich meine Anwendung: Auf Deutsch gesagt Strohdumm Programmieren, damit es keine Angriffsziele gibt und das alles natürlich über den MiddleWare lösen, aber mich stört es einfach, das man den kompletten Sourcecode über dotpeek ohne Probleme eins zu eins raus kopieren kann.

    Wie schon oben beschrieben habe, gibt es derzeit keine Möglichkeit die mir bekannt ist: Free einen Obfuscator für .NET 6 zu nutzen um zu mindestens meinen Code etwas zu verschleiern.

    Natürlich würde ich unter C++ auch keinen direkten Weg verwenden, sondern dort auch über den MiddleWare eine Möglichkeit nutzen, um
    einen Angreifer in den Wahnsinn zu treiben, allerdings bietet C++ zu mindestens soviel "Schutz" das nicht jede voll Nase mein Code eins zu Eins klauen kann.

    Ich habe mich ja sogar schon mit der WinAPI angefreundet ☺



  • Nur ist die WinApi halt kacke 😂 . Klar, jeder Client kann den Clientcode dann lesen, aber was den Server und deine Datenbank betrifft bleibt alles vor neugierigen Augen geschützt. Und Clientcode klauen bringt halt nicht viel wenn man den Servercode nicht hat.



  • Ja das Stimmt, WinAPI ist schon echt scheiße aber es gibt ja auch wxWidgets, man könnte zwar mit beiden Arbeiten, aber naja. Kann man eigentlich sein Code selbst auch Verschleiern? ohne ein Obfuscator zu verwenden?



  • Ich weiss nicht wieviele leute dir noch erzaehlen muessen, dass security through obscurity einfach nunmal NICHT funktioniert...?
    Willst du das einfach nicht verstehen, oder tust du es wirklich nicht?

    Du willst client-specific krams aus deiner db haben. Jetzt gehst du zu deiner API, gibst der die credentials die den user authentifizieren. Deine API fragt die db nach dem krams, und schickt es zurueck. Das ganze machst du selbstverstaendlich mit TLS, was jede lib aus diesem jahrhundert unterstuetzt.

    und schon ist der ganze bums fertig.
    bonuspunkte wenn du den client->api auth prozess mit JWT realisierst.



  • @Cardiac sagte in Eine Verbindung zur einer MySQL Datenbank sicher herstellen?:

    security through obscurity

    Lieber Cardiac, es wäre vielleicht etwas Netter, auch meine Beiträge zu Lesen statt mich hier unfreundlich anzufahren.
    Wenn du meine Beiträge gelesen hättest, dann würdest du direkt verstehen, das mir es nicht um die Sicherheit beim Verschleiern geht,
    das habe sehr häufig geschrieben.



  • Sei es drum, C# kommt für mich erstmal nicht infrage. Ich werde so schnell auch nicht aufgeben,
    ich werde jetzt mal versuchen die Tipps hier umzusetzen und zu Testen. Nur so kann ich lernen.

    Das einzige was mich wirklich nervt an C++ ist die WinAPI, aber da finde ich eine Lösung. QT kann ich nicht wirklich verwenden, da die Lizenz blöd ist und wxWidgets weiß ich ehrlich gesagt noch nicht, ob ich das verwenden soll.



  • @Lucius sagte in [Eine Verbindung zur einer MySQL Datenbank sicher herstellen?]

    Das einzige was mich wirklich nervt an C++ ist die WinAPI, aber da finde ich eine Lösung. QT kann ich nicht wirklich verwenden, da die Lizenz blöd ist und wxWidgets weiß ich ehrlich gesagt noch nicht, ob ich das verwenden soll.

    C++ kann aber nix für die WinAPI. Und was ist an der Lizenz von QT falsch?



  • Das stimmt, C++ kann wirklich nichts für die WinAPI. Nur stört mich an C++ das diese Sprache keine eigene GUI mitbringt die besser anpassbarer ist.

    Naja, wie ich das verstanden habe, ist QT nur für Open Source User Kostenlos, die Preise sind meiner Meinung nach Unverschämt, nicht weil es im Jahr Summe X kosten würde, sondern, das man Monatlich eine Hohe Summe bezahlen soll.


Anmelden zum Antworten