Eine Verbindung zur einer MySQL Datenbank sicher herstellen?



  • Hallo zusammen, ich bin noch neu hier im Forum und auch noch nicht Lange mit C++ dran.

    Ich habe bezüglich MYSQL Verbindung eine Frage:
    Normalerweise kenne ich das aus anderen Sprachen, das man eine MySQL Verbindung am besten über eine PHP Datei aus realisiert, damit man die Zugangsdaten nicht im Programm Code speichert wird. Jetzt habe ich hier und auch im Internet des Öfteren gesehen, das man direkt eine MySQL Verbindung über C++ aufbaut. Allerdings frage ich mich, wie man das dann mit den Zugangsdaten der Datenbank macht?

    Ich würde gerne eine Datenbankverbindung über C++ aufbauen, um Zugangsdaten eines Users der in einer Datenbank gespeichert ist abzufragen.

    Vielleicht könnt ihr mir ein paar Tipps geben, wie ich dies am besten sicher umsetzen kann.

    PS. Man sagt auch oft, das C++ sehr schwer sei, zu dekompilieren, wie weit das stimmt weiß ich nicht?
    Würde dann nämlich verstehen, warum man dann ohne weiteres die Zugangsdaten der Datenbank im Programm ablegen kann 🙂

    Liebe Grüße



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

    Hallo zusammen, ich bin noch neu hier im Forum und auch noch nicht Lange mit C++ dran.

    Ich habe bezüglich MYSQL Verbindung eine Frage:
    Normalerweise kenne ich das aus anderen Sprachen, das man eine MySQL Verbindung am besten über eine PHP Datei aus realisiert, damit man die Zugangsdaten nicht im Programm Code speichert wird.

    Äh. Die "PHP Datei" ist der "Programm Code". Der Unterschied bei PHP ist bloss dass man die PHP Files normalerweise nicht an den Endbenutzer ausliefert. Und idealerweise hängt der Datenbank-Server dann auch nicht mit dem nackten Hintern im Internet. Wenn der hinter einem VPN hängt, dann ist es weit weniger tragisch wenn jmd. an die Zugangsdaten kommt.

    Jetzt habe ich hier und auch im Internet des Öfteren gesehen, das man direkt eine MySQL Verbindung über C++ aufbaut. Allerdings frage ich mich, wie man das dann mit den Zugangsdaten der Datenbank macht?

    Ich würde gerne eine Datenbankverbindung über C++ aufbauen, um Zugangsdaten eines Users der in einer Datenbank gespeichert ist abzufragen.

    Das wird schwierig wenn du nicht willst dass andere die Zugangsdaten rausbekommen können. Und das wirklich schlimme daran ist: wenn du es so einfach machst, dann können sie mit den Zugangsdaten zur DB auch die Usernamen & Passwörter von allen Benutzern auslesen. Das wäre ziemlich übel.

    Vielleicht könnt ihr mir ein paar Tipps geben, wie ich dies am besten sicher umsetzen kann.

    Die einzige Möglichkeit das sicher zu bekommen ist alles so einzurichten dass jemand der die Zugangsdaten zur DB rausbekommt trotzdem nichts unerwünschtes anstellen kann.

    Dazu kann man z.B. stored procedures verwenden. Dabei gibst du dem DB Benutzeraccount nur Rechte bestimmte stored procedures auszuführen, nicht aber die Rechte direkt auf die Tabellen zuzugreifen. Dazu muss der DB-Server es aber unterstützen dass stored procedures mit einem anderen Account ausgeführt werden als dem der "execute" gesagt hat. MSSQL z.B. kann das. Ob MySQL es kann weiss ich nicht.

    Und natürlich ist das alles recht mühsam. Bleibt die Frage ob es dann nicht einfacher wäre über HTTP/JSON mit einer Zwischenschicht zu kommunizieren, die am Server läuft, und direkt auf die DB zugreift.

    PS. Man sagt auch oft, das C++ sehr schwer sei, zu dekompilieren, wie weit das stimmt weiß ich nicht?
    Würde dann nämlich verstehen, warum man dann ohne weiteres die Zugangsdaten der Datenbank im Programm ablegen kann 🙂

    Strings landen 1:1 so in der .EXE wie sie auch im Source-Code stehen(*). Und es gibt da sehr einfache Tools mit denen man sämtliche Strings die in einer .EXE vorkommen anzeigen lassen kann. Natürlich könnte man es dem potentiellen Angreifer etwas erschweren, indem man die Zugangsdaten verschlüsselt in der .EXE ablegt. Nur sicher ist das auch nicht. Jmd. der weiss wie man einen Debugger bedient hat das trotzdem ganz schnell heraussen.

    ps: Muss es denn C++ sein? So Internet-Zeugs ist viel einfacher mit C# oder java zu machen als mit C++. Bei C++ musst du dir mühsam die ganzen Libraries zusammensuchen die man dazu braucht -- und sich dann damit rumschlagen wie man diese baut und einbindet. Bei C# oder Java kommt vieles schon in der Standard-Library mit, und was fehlt kann man einfach und komfortabel über diverse Package-Manager installieren.

    *: Ja, jaaaaaaa, Escape-Sequenzen. Aber darum geht's hier nicht.


  • Mod

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

    Und natürlich ist das alles recht mühsam. Bleibt die Frage ob es dann nicht einfacher wäre über HTTP/JSON mit einer Zwischenschicht zu kommunizieren, die am Server läuft, und direkt auf die DB zugreift.

    Das hier. Weitere Argumente dafür (auch wenn mich irgendwelche Datenbankcracks jetzt auslachen werden, weil das bestimmt auch alles nativ ganz einfach ginge, wenn man sich nur auskennen würde):

    • Ich betreue lieber einen Server, den ich in meiner Lieblingssprache schreiben kann, anstatt mich in alle Feinheiten einer Datenbank einzuarbeiten
    • Ich kann zur Not die Datenbanktechnik wechseln, ohne groß etwas neues über die Feinheiten der neuen Datenbank lernen zu müssen
    • Das Prinzip lässt sich auch auf andere Dinge übertragen. Das kann ja auch ganz etwas anderes sein, mit dem die Zwischenschicht redet, irgendein technisches Gerät im gleichen Netzwerk, bei dem man nur bestimmte Befehle zulassen möchte.


  • 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++. Mit der WinAPI komm ich so langsam klar. Ich wollte eine Programmiersprache wählen die zum einem Schwerer ist zu Dekompilieren und zum anderem Systemunabhängig verwendet werden kann.

    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 😃
    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 😃


  • Mod

    Wenn der Schutz deiner Passwörter ist, dass du es nicht schaffst sie zu entschlüsseln, oder dass du denkst wegen der Sprache wäre es irgendwie einfacher oder schwieriger, dann bist du auf einen ganz gefährlichen Weg. Ist das Passwort in der Anwendung enthalten, dann ist es vollkommen egal wie leicht oder schwer es zu entschlüsseln ist, ein Angreifer kommt da ohne große Probleme dran. Mit vermeintlicher Schwierigkeit schützt du dich höchstens vor deinem kleinen Bruder. Ein erfahrener Angreifer braucht dein Programm nicht zu dekompilieren. Er braucht nicht einmal deine "Verschlüsselung" zu verstehen. Er kann einfach in den Speicher gucken, was dein Programm Schritt für Schritt macht. Zu irgendeinem Zeitpunkt muss das Passwort im Klartext durch den Prozessor gehen, damit der Zeichenstrom für die Serverkommunikation berechnet werden kann. Dein kleiner Bruder würde halt vielleicht an fehlender Erfahrung im Umgang mit einem Debugger für Maschinensprache scheitern, aber für jeden mit einem kleinen bisschen Ahnung ist das Alltag.

    Wenn du einen mathematischen Bezug zwischen der Kommunikationsverschlüsselung und deinem Passwort herstellen kannst, dann könnte das vielleicht interessant werden, und jemanden stoppen, der diesen Bezug nicht versteht. Ob das überhaupt theoretisch möglich ist, oder wie das funktionieren könnte, wird hier aber wohl niemand wissen.



  • Wie bereits gesagt wurde kannst du das Argument mit "Schwer du decompilieren" vergessen. Ich bin Anfänger im ReverseEngineering und habe mit kostenlosen OpenSource Tools fast immer gefunden was ich gesucht habe. Ich würde ebenfalls wie schon gesagt wurde dazu raten dir nen Server in einer Sprache deiner Wahl zu basteln und einzig dem Server die Berechtigungen geben auf deine DB zuzugreifen. Du solltest dich auch damit beschäftigen wie man das alles absichert. Verbindung per TLS, keine Passwörter als Klartext abspeichern (hashen + "salzen"), ReverseProxy nutzen, etc... Außerdem solltest du dein Interface vom Server so bauen, dass es niemand für seine Zwecke missbrauchen kann. Irgendjemand hat mal gesagt man solle es so betrachten das " Vom Client nichts Gutes kommt". Also überlege dir was man anstellen könnte wenn man eigene Requests erstellt und ob dein Server dann vertraulisches ausspuckt oder Daten editiert/löscht die er nicht soll. Ebenfalls solltest du überlegen ob Sessions erhalten bleiben sollen (Json Web Token?) oder ob der Server alles wieder vergessen sollte. Du siehst, es gibt einiges zu beachten.



  • Guten morgen, das klingt ja alles nicht so rosig.

    Gehen wir mal ein Szenario durch:
    Ein geschriebenes Programm in C++ möchte sich auf einen MySQL server einloggen. Dazwischen eine PHP file die den request zur db erledigt. das programm kann nur dann ein request aufbauen, wenn der Username und das Password eines Users in der db stimmt, erst dann werden die informationen über den eingegeben User vollständig geladen. Das einzigste was im c++ code gespeichert ist, ist die URL zur PHP file und die funktion diese zu verarbeiten.

    könnte man die möglichkeit als eine gute lösung abspeichern?



  • So wild, wie hier beschrieben, ist das in deinem Szenario vermutlich nicht.
    Wie sieht denn dein Anwendungsfall aus, gibst du das fertige Programm weiter oder läuft das nur lokal auf einer Maschine?



  • Das würde dann frei zum Runterladen sein.



  • Naja, dann vielleicht doch mit ner Middleware.
    Was genau soll deine Software denn machen?



  • Vorstellen kann man sich das wie Steam, man loggt sich ein und bekommt sein ganzes Profil angezeigt,
    dadurch sind Zugänge für andere Software möglich die man geschrieben hat.

    Deshalb dachte ich eigentlich eher, das C++ auf PHP eine gute Lösung sei, denn ohne die Daten einen Nutzers, können keine anderen daten abgerufen werden. Auch wenn man den Speicher einer Programmierten Software auslesen würde, bekommt man nur das angezeigt, was man im Login Feld eingetragen hat.

    Als würde man auf eine Webseite gehen und sich dort einloggen. Das PHP Skript hat nur die Anweisung die Daten die eingegeben werden zu verarbeiten, ohne diese Daten bleibt es nur ein PHP-Skript.

    Eine Idee wäre über Webrequest (ob das unter C++ auch so heißt weiß ich nicht), zu nutzen und über POST vom C++ Login zur PHP zu senden um zu prüfen ob die Daten die man zuvor im C++ Login eingegeben hat, korrekt in der Datenbank vorkommen. Wenn Ja, gib dann die komplette row des Nutzer aus.

    Da ich eigentlich von PHP und C# her komme, weiß ich nicht, wie man das am besten in C++ umsetzen soll. Ich habe schon einige Grundlagen der C++ Programmierung hinter mir, nur die beschreiben solche dinge nicht. C# ist für mich keine Option mehr, da mein Programm dann ohne weiteres Ausgelesen werden kann. Unter Net. 6 ist das Verschleiern leider nicht so einfach kostenlos möglich. Aber nicht nur deshalb wollte ich von .NET weg, sondern eher, das man C++ wesentlich besser anpassen kann und mir mehr Möglichkeiten gibt als C# (Arduino und Co.)



  • Das hört sich für mich doch eher wie eine zweistufige Benutzerverwaltung an:

    Layer 1: db-Zugriff
    Es gibt min. einen db-Benutzer, der auf die db zugreift. Dieser Benutzer sollte halt so wenig Rechte wie möglich und nur so viele Rechte wie nötig bekommen. Von diesem Benutzer weiß der Rest der Welt nichts, weil er nur in der Middleware benutzt wird.

    Layer 2: Zugriff auf Benutzerdaten
    Ich denke, der Zugriff auf jedes Benutzerprofil ist durch ein Kennwort geschützt, dass der Benutzer selbst vergeben kann (halt klassisch mit Benutzername + Kennwort).

    Der Ablauf der Kommunikation sähe dann so aus:
    Der Benutzer gibt im Client seinen Benutzernamen und Kennwort ein, das wird per TCP/IP, HTTP(s) oder was auch immer an die Middleware gesendet. Die Middleware läuft lokal auf einem Rechner, auf den der Benutzer keinen Zugriff hat, daher kannst du dir hier frei überlegen, wie das Kennwort abgelegt wird. Das Passwort ist sicher, weil der Benutzer keinen Zugriff auf die Programmdatei hat, daher könnte es sogar in der Anwendung abgelegt werden. Weil deine ganze Anwendung als Service läuft kannst du dir ja sogar überlegen, ob das db-Passwort beim Start der Middleware eingegeben werden muss, dann musst du es nirgendwo hinterlegen. Macht natürlich einen automatischen Restart unmöglich.
    Oder du lädst es aus einer verschlüsselten Datei. Oder noch was anderes.

    Die Middleware verbindet sich mit den ihr gegebenen mySQL-Benutzernamen und Kennwort mit der mySQL Datenbank und überprüft die Gültigkeit der Benutzerdaten aus Schritt 1.

    Im Prinzip ist die Middleware nur ein Proxy für die Datenbank, vielleicht noch mit ein paar weiteren Funktionen für´s Logging, etc.
    Aber das haben meine Vorredner ja alle schon vorgeschlagen/erklärt.



  • Richtig, außer das die C++-APP auf dem Rechner des Benutzer installiert/abgelegt wird.
    Deine Vorredner haben mich eher ein wenig verwirrt 😀

    Nur wie Bewerkstellige ich das mit C++ das ich auf eine PHP Datei zugreife und die Daten übermittle von C++ Login auf PHP übermittle.
    Gibt es da sowas wie eine Beschreibung oder Tutorial oder ähnliches das mich an meiner Lösung näher bringt.


  • Mod

    Nur wie Bewerkstellige ich das mit C++ das ich auf eine PHP Datei zugreife und die Daten übermittle von C++ Login auf PHP übermittle.

    Klassischerweise über http(s)-Requests. Prinzipiell hättest du die volle Freiheit, dir auch selber etwas ausdenken, aber http-Requests sind schön einfach und standardisiert, daher sind sie schön zuverlässig und portabel. Wenn du ohne State auskommst (was öfter der Fall ist, als man so denkt), hat sich die REST-Architektur bewährt.

    Oder ist die Frage so zu verstehen, dass du nicht weißt, wie man von C++ aus http-requests stellt?



  • 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?


Log in to reply