Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 20 von 30

Thema: Passwörter in einer SQL Datenbank speichern

  1. #1

    Passwörter in einer SQL Datenbank speichern

    Moin.

    Ich muss eine kleine Webseite basteln, die von unterschiedlichen SQL Servern Daten abfragt. Dafür brauch ich bekannterweise Benutzernamen und Passwort, um mich an den jeweiligen Servern anzumelden.
    Nun hatte ich die Idee, die IP/DNS des Servers, Benutzernamen und Passwort in eine SQL Datenbank zu speichern und sie dann mittels eines php-Skriptes abzuarbeiten. Das Problem allerdings ist, dass ich das Passwort ja dann in Klarschrift speichern muss.
    Nun stellt sich für mich die Frage, wie sicher das Ganze doch ist?
    Oder macht es eher sinn, die ganzen Daten als Array in php zu speichern?
    Oder gibt es da eine bessere Methode?

  2. #2
    Klartext würde ich auf jeden Fall vermeiden, auch in PHP. Denn der Variablenwert steht dann ja auch so im Speicher und ist auslesbar - bzw wer Zugriff auf die PHP-Datei hat kennt dann auch die Passwörter etc. Du könntest das Passwort aber verschlüsseln. Du speicherst dann im PHP-Array oder in der Datenbank nur die verschlüsselten Passwörter und den Schlüssel zum Entschlüsseln muss man sozusagen als Master-Passwort beim Laden der Website eingeben. Mit diesem Schlüssel werden die Passwörter entschlüsselt und an den Server weitergegeben. Je nachdem, ob der Schlüssel korrekt war oder nicht, kommt dann das richtige Passwort dabei heraus und gibt den Zugriff frei.
    Man muss damit zwar einen Schlüssel zu Beginn eingeben, dafür reicht hier ein Schlüssel aus für alle Datenbanken, egal wie viele es werden. Und du hast eine eingebaute Zugriffskontrolle, dass nur autorisierte Nutzer die Datenbank nutzen können.
    Den Verschlüsselungsvorgang nimmst du natürlich nicht in der PHP-Datei vor, sonst liegen da die Ursprungspasswörter ja auch vor. Da musst du dir infach ein kleines Tool schreiben, welches die Passwörte verschlüsselt und dir die verschlüsselten Passwörter anzeigt. Diese speicherst du dann so im Klartext in der PHP-Datei und merkst dir den Schlüssel zum Entschlüsseln.
    Gute und sichere Algorithnmen zur Verschlüsselung sind meist open source und offengelegt und im Internet zu finden.

    Achso: IP und DNS kannst du durchaus im Klartext speichern. Jemand, der weiß was er tut, findet die Rechner sowieso, da die nicht unbedingt unsichtbar sind und ihre Identität im Netz eh offenlegen, wenn sie nicht hinter ser guten Firewalls sitzen. Den Benuternamen kannst du, wenn du magst, natürlich auch verschlüsseln. So wird es selbst mittels Brute Force nahezu unmöglich, einen erfolgreichen Login hinzubekommen, wenn Username und Passwort unbekannt und passend gesucht werden müssen. Die Möglichkeit der Kombinationen von 2 Zeichenketten ist natürlich deutlich höher als nur bei einer unbekannten Zeichenkette.

    Geändert von Ynnus (25.02.2010 um 02:52 Uhr)

  3. #3
    mmh, das ist schonmal keine schlechte Idee. Danke.
    Allerdings gibt es da einen Haken. Die Seite ist zwar nur für interne Zwecke gedacht aber es soll ein Frontend und ein Backend geben. Dann müsste man in beiden Bereichen zwei Passwörter eingeben. Erstmal für den Account und dann das Masterpasswort und ich kann mir vorstellen, dass der Kunde dies nicht haben möchte.
    Ich müsste sowieso erstmal schauen, ob mcrypt installiert worden ist. Für einen eigenen verschlüsselungsalgorithmus ist eigentlich keine Zeit, da der Kunde morgen schon was sehen möchte ...

  4. #4
    Falls du Shellzugriff auf die Zielrechner hast, könntest dus mit einem SSH Tunnel probieren, den du per Public Key Verfahren öffnest. Damit hättest du auch den Vorteil, dass keine Daten unverschlüsselt zwischen den Servern übertragen werden. Eine grobe Anleitung gibts unter http://docu.sbsbavaria.de/54.html

  5. #5
    Ich müsste ja dann die SSH Verbindung über php starten, oder nicht? (hab mich mit Remotezugriffen noch nicht großartig auseinandergesetzt)
    Shellzugriff hab ich zwar aber das ssh2-Modul für php existiert nicht.

  6. #6
    Nein, du kannst die Sache so aufbauen, dass du den Tunnel dauerhaft offen hast (oder per cronjob, aus PHP per system() oder sonst wie öffnest) und PHP auf den jeweiligen Server über localhost:$port zugreift, wobei du jedem Server einen anderen Port verpasst. Lies dir die Anleitung einfach mal durch.

    Edit:
    Ach ja, das Ganze ist für einen Linux Server und Windows Client geschrieben, aber mit einem kurzen Blick in die man Pages solltest du recht schnell rausfinden, wie das auf einem Linux Client funktioniert. Hat bei mir auch geklappt, ist aber schon länger her, deshalb hab ichs nicht mehr im Kopf.

  7. #7
    Momentan ist hier sowieso dicke Luft und ich könnte quer durch den Raum kotzen.
    Ich hasse es, wenn der Kunde nicht weiß, was er will.

  8. #8
    Meine Erfahrung ist, dass Kunden nie wissen, was sie wollen, also mach dir nichts draus.

  9. #9
    Mag sein, dass ich keine Ahnung habe, aber ich finde Ynnus Vorschlag mit Masterkey etc. etwas bloated.

    Sicherheit ist gut und schön, aber a) geht das doch massiv zu Lasten der Usability und außerdem muss man ein Mindestmaß an Sicherheit auf dem Server, auf dem das läuft, voraussetzen, ansonsten kann man die Anwendung gleich in die Tonne kloppen.

    Wenn ich das Passwort im Klartext in einer PHP Datei speichere und ihr entsprechende Rechte gebe, muss ich davon ausgehen können, dass diese Datei keiner außer mir und dem Administrator lesen kann. Wenn diese Annahme falsch ist, ist meine Anwendung per Definition kompromittiert, da dann vermutlich auch andere Personen in meine Dateien schreiben können und damit noch ganz andere Sachen anstellen können, als nur mein SQL PW auszulesen.

    Ich sehe ein, dass unverschlüsselte Passwörter im Speicher unschön sind (hilft da kein unset/free?), da kann man sie dann aber meinetwegen verschlüsselt speichern, in ner anderen Variable und Datei den Schlüssel und dann zur Laufzeit on demand entschlüsseln - eher Obfuscation, aber geht nicht zu Lasten der Usability.

    Was die Sicherheit der Kommunikation zwischen App und DB angeht, da ist nicht der Programmierer für verantwortlich. Dafür hat der Server-Admin zu sorgen durch VPN, SSH-Tunnel oder SQL über SSL.

  10. #10
    Dito mit dead_orc, zumal man es so oder so nicht vermeiden kann, unverschlüsselte Passwörter im Speicher zu haben – um sie an den Server zu schicken muß man sie ja irgendwann entschlüsseln und dann sind sie da. Das ganze "ich verschlüssele die Daten, liefere aber alles zum Entschlüsseln Benötigte mit"-System ist der Grund, warum frühe DRM-Systeme schnell umgangen waren.
    Effektiv läuft der ganze Schutz darauf hinaus, daß der Angreifer nicht weiß, an welcher Adresse im Speicher der Schlüssel, bzw. der Plaintext liegt. Security through obscurity.

    Sicherheit würde ich beim Host ansetzen. Ein gehärtetes Linux mit sinnvollen Permissions sollte schon einiges an Schutz bieten. Wenn man vor Speichersniffern Angst hat, könnte ASLR rudimentären Schutz bieten (und da ein ordentlich gehärtetes Linux ohnehin ExecShield oder PaX eingebaut hat, kommt es gratis). Letztenendes gilt aber: Wenn der Angreifer Zugriff auf die Maschine hat, ist der Kampf bereits verloren.

    Natürlich muß das Programm sauber geschrieben sein, um Angriffe zu vermeiden. Ich würde aber im Programm selbst auf obfuszierende Maßnahmen verzichten, weil sie effektiv nichts tun, aber Ressourcen kosten.
    Und natürlich muß die Kommunikation mit den Servern verschlüsselt werden, aber das ist auch wieder nicht Sache des Programmierers.

    Insgesamt würde ich also sagen, daß die Sicherheit im Wesentlichen vom Administrator und nicht vom Programmierer kommen sollte. Der Programmierer muß sauberen, fehlerfreien Code schreiben und nicht versuchen, Daten im RAM abzulegen, ohne sie im RAM abzulegen.

  11. #11
    Zitat Zitat von DFYX Beitrag anzeigen
    Nein, du kannst die Sache so aufbauen, dass du den Tunnel dauerhaft offen hast (oder per cronjob, aus PHP per system() oder sonst wie öffnest) und PHP auf den jeweiligen Server über localhost:$port zugreift, wobei du jedem Server einen anderen Port verpasst. Lies dir die Anleitung einfach mal durch.
    Entweder kann ich momentan nicht klar denken oder du hast nicht verstanden, was ich wollte ^^"

    Ich versuch es nochmal zu erklären:
    Ich habe eine Webseite auf Server A.
    Von Server A möchte ich mehrere MySQL Server ansprechen.

    Erstes Problem: Ich weiß nicht, wie viele Server es werden und ich kenn auch nicht deren DNS/IPs. Da sie erst eingerichtet werden müssen. Ohne in dem Code rumpfuschen zu müssen, muss ich dann irgendwo die Serverdaten speichern. Kann also sein, dass es irgendwann über 20 und mehr Server sind.
    Dann 20 und mehr SSH Verbindungen aufzubauen, finde ich persönlich ganz schön heftig.

    Zweites Problem: Ich kann an diesen Servern weder nachträglich was verändern noch installieren.

    edit:
    Die einfachste Lösung wäre wohl, auf jedem Server die Webseite zu speichern und dass man per URL-Link die Seite wechselt.
    Ich weiß aber nicht, ob das dem Kunden gefällt ...

  12. #12
    Zitat Zitat
    Das ganze "ich verschlüssele die Daten, liefere aber alles zum Entschlüsseln Benötigte mit"-System ist der Grund, warum frühe DRM-Systeme schnell umgangen waren.
    Wo liefere ich denn bitte alles zum Entschlüsseln mit? Es ist gängige Praxis, dass der Verschlüsselungsalgorithmus offengelegt ist (z.B. durch Ausschreibungen wird der beste Algorithmus gesucht, sehr verbreitete Algorithmen wie RSA (ein bekanntes asymetrisches Public-Key Verfahren) sind sehr sehr sicher und dennoch öffentlich bekannt). Das Geheimhalten des Schlüssels reicht bei diesen Algorithmen aus, um die Sicherheit zu gewehrleisten. Denn ein Algorithmus kann durch Analyse des Codes und Disassembling herausgefunden werden. Ein offengelegter Algorithmus, bei dem man durch den Algorithmus und den verschlüsselten Wert nicht (bzw nur mit Jahren Rechenaufwand) auf den Schlüssel rückschließen kann, ist deutlich sicherer.
    Soviel dazu.
    Ob das nun oversized ist für dieses Projekt oder nicht muss jeder selbst wissen. Sicher gibt es andere Methoden der Realisierung, diese ist mir halt gestern so in den Sinn gekommen.

  13. #13
    Zitat Zitat von Whiz-zarD Beitrag anzeigen
    Zweites Problem: Ich kann an diesen Servern weder nachträglich was verändern noch installieren.
    Genau danach hatte ich gefragt:

    Zitat Zitat
    Falls du Shellzugriff auf die Zielrechner hast, könntest dus mit einem SSH Tunnel probieren
    Dazu musst du diesen eben auch auf den Servern einrichten können. Falls das nicht gegeben ist, musst du dir andere Methoden einfallen lassen.

    Allerdings bin ich der gleichen Meinung wie einige Personen über mir: wenn ein Angreifer so weit kommt, dass er deinen Arbeitsspeicher auslesen kann, ist es ohnehin zu spät, also kannst du die Passwörter auch im Klartext ablegen.

  14. #14
    Shellzugriff habe ich ja. Wie ich grad festgestellt habe, kann ich eh nur über SSH auf den MySQL Server von aussen zugreifen.
    Mein Problem ist dann aber, wie übermittel ich dann die Daten nach php?
    Die Daten werden noch von php weiterverarbeitet. Deswegen meinte ich auch, dass ich doch das ssh2-Modul brauche, was aber nicht aktiviert ist.

    Sorry aber ich hab nunmal keine Ahnung von SSH.

  15. #15
    Hast du eigentlich GELESEN, was in dem Tutorial steht?

    SSH Tunnels funktionieren grob gesagt so, dass du auf dem Clientrechner einen Prozess hast, der auf einen Port hört. Alles, was an diesen Port geschickt wird, wird verschlüsselt an den Server geschickt, dort entschlüsselt und weiter geschickt. Auf dem Client rufst du also zum Beispielmysql_connect("localhost:$port", $user, ""); auf, wobei $port der Port ist, den du deinem SSH Tunnel gegeben hast. Auf dem Server stellst du dann noch ein, dass dieser User ohne Passwort zugreifen darf, wenn er von localhost kommt (was er tut, weil der Endpunkt des SSH Tunnels eine neue Verbindung herstellt) Um Schaden anzurichten, bräuchte er dann erstmal den Private Key für die SSH Verbindung, der an einer Stelle auf dem Client liegt, wo er zumindest über eine Sicherheitslücke in der Website nicht rankommen sollte.

    Außerdem hast du damit gleich noch deine Übertragung zwischen Client und Server verschlüsselt, wobei das vermutlich auch anderweitig gehen sollte. Ich gehe davon aus, dass MySQL von sich aus SSL kann.

    Edit: es ist im Übrigen auch keine schlechte Idee, zusätzlich zum SSH Tunnel ein Passwort zu verwenden, schon allein, damit niemand vom Server aus Unsinn anstellen kann, falls er irgendwie Zugang bekommt. Allerdings solltest du auch dann sicher stellen, dass dieses Passwort nur von localhost aus gültig ist. (Allgemein halte ich es für eine schlechte Idee, Datenbankserver für jemand anderen als localhost verfügbar zu machen)

    Geändert von DFYX (25.02.2010 um 19:32 Uhr)

  16. #16
    Zitat Zitat von Ynnus Beitrag anzeigen
    Wo liefere ich denn bitte alles zum Entschlüsseln mit? Es ist gängige Praxis, dass der Verschlüsselungsalgorithmus offengelegt ist[...]
    Ich spreche nicht vom Algorithmus. So wie du dein System beschrieben hast interpretiere ich es wie folgt:

    - Die Passwörter liegen verschlüsselt lokal vor.
    - Der Schlüssel liegt ebenfalls lokal vor oder werden vom Anwender eingegeben.
    - Um ein Passwort zu benutzen, wird es entschlüsselt. In diesem Moment liegt es unverschlüsselt im Speicher.

    Wenn jemand lokalen Zugriff hat, bieten sich zwei Angriffsflächen: Er kann sich Schlüssel und Passwörter schnappen und hat damit die Passworter im Klartext. Oder er findet heraus, wo im Speicher du das Klartext-Passwort ablegst und liest es direkt aus.
    Selbst, wenn der Schlüssel selbst nicht einfach so gespeichert ist, mußt du ihn auch irgendwann im Speicher haben und dort kann er dann ausgelesen werden. Ein Angriff auf AACS funktionierte so; der Speicher des Abspielprogramms wurde nach den Title Keys durchsucht.

    Letztenendes ist die Sicherheit gegenüber einer lokalen Speicherung im Klartext nur insofern größer, daß der Angreifer den Schlüssel extrahieren muß. Da jemand mit nennenswertem Lokalzugriff sich einfach sämtliche Dateien kopieren kann und dann effektiv unendlich viel Zeit (und Prozessorzyklen) für den Angriff hat, ist dieser Schutz nicht wirklich relevant. Zumal es nicht gerade einfach ist, Schlüssel und Klartextdaten so im Speicher zu verstecken, daß ein Angreifer sie nicht schnell finden kann.


    Effektiver Schutz muß (so weit wie möglich) gewährleisten, daß alle involvierten Rechner vor Angriffen geschützt und die Verbindungen zwischen ihnen verschlüsselt werden. Sobald der Angreifer signifikanten Zugriff auf den lokalen Rechner hat, ist davon auszugehen, daß er jede weitere Sicherheitsvorkehrung umgehen kann, da er alles kann, was der Rechner kann – und der Rechner soll ja gerade auf die Passwörter zugreifen können.

    Ein paar elementare Weisheiten der Sicherheit:
    - Das Internet ist böse; jede unverschlüsselte Verbindung muß bei der Planung der Sicherheitsvorkehrungen als automatisch kompromittiert angesehen werden. (Korrolar: Sensible Daten dürfen unter keinen Umständen unverschlüsselt übertragen werden.)
    - Wer lokalen Zugriff hat, der kann alles tun, was sein Account tun kann. (Wenn also deine Webanwendung kompromittiert wird, dann wird alles kompromittiert, auf das die Webanwendung Zugriff hat; hier also die Passwörter.)

    Geändert von Jesus_666 (25.02.2010 um 20:48 Uhr)

  17. #17
    Um nochmal was zu Whiz ursprünglicher Frage zu sagen (wieso ist das eigentlich auf einmal zu ner Sicherheits-Diskussion explodiert?):

    Ich würde die Speichermethode der Serverdaten davon abhängig machen, wie die Anwendung später benutzt wird. Wenn die Server für immer und ewig (oder wenigstens ne lange Zeit [einige Jahre]) die selben bleiben (bzw. deren IPs/deren DNS-Adressen), würde ich sie in einer Config-PHP-Datei in ein Array klatschen. Wenn es durchaus mal vorkommen kann, dass n Server dazu kommt, einer wegfällt und dergleichen würde ich sie versuchen, in ne DB zu lagern. Dafür dann aber NOCH eine MySQL DB zu nehmen, halte ich für unschlau. Vielleicht wäre da sqlite o.Ä. angebracht. Vielleicht sogar einfach nur ne CSV-Datei, aber halt was, was du maschinell lesen und schreiben kannst, damit du auch ein nettes Webinterface zum Ändern der SQL-Server bereitstellen kannst.

    @Jeez: thx fürs Backup

  18. #18
    Speichere niemals Passwörter (verschlüsselt oder nicht) direkt in einer DB!
    Wenn jemand irgendwie doch an den Schlüssel kommt, hast du verloren.
    Wenn jemand auch ohne Schlüssel an deine DB kommt, ist es nur eine Frage der Zeit bis der Schlüssel rekonstruiert ist und die Passwörter im Klartext rausziehbar sind.

    Speichere stattdessen nur den *Hash* eines Passwords, idealerweise mit einem geheimen sog. Salt Wert, etwa:

    Salt = "lf34ha";
    pw = Hash(Salt + UnhashedPw);
    Store(pw);

    Selbst wenn dann jemand an deine gesamte Passwort-DB kommt, wird er so niemals das Klartext-Passwort rekonstruieren können.

    Meines Wissens nach ist das die gängigste Methode und Passwörter zu speichern.

  19. #19
    Ähm, du hast schon gelesen, was das Problem ist, oder? Er braucht das Passwort hinterher wieder im Klartext. Mit Hashes kommt er da nicht weit.

  20. #20
    So, nach einigen Hin- und Her hab ich mir erstmal ein Testaufbau, mit zwei Debian Server, aufgebaut. Hab für SSH einen Public- und Privatschlüssel eingerichtet. Wenn ich nun im root Terminal ssh -N -l <user> -L3306:127.0.0.1:3306 <Server-IP> eingebe, funktioniert auch der SSH Tunnel und php kann auch auf den MySQL Server zugreifen.

    Allerding möchte ich gern per php den Tunnel starten, sodass der Tunnel nur dann aufgebaut wird, wenn er gebraucht wird. Also hab ich zwei Zeilen geschrieben, die lauten
    Code (php):
     
    $str = shell_exec('ssh -N -l <user> -L3306:127.0.0.1:3306 <Server-IP> sleep 20');
    $db = mysql_connect('127.0.0.1', '<user>', '<passwort>' );


    Allerdings scheint php den Shell Befehl nicht auszuführen.
    shell_exec ist nicht deaktiviert, da andere Befehle, wie z.B. ls funktionieren.

    Weiß vielleicht einer, woran das liegen kann und ich dass verändern verändern kann?

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •