Meine Erfahrung ist, dass Kunden nie wissen, was sie wollen, also mach dir nichts draus.
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.
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.
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.Zitat
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.
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 19:48 Uhr)
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![]()
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.