Autor |
Beitrag |
ChrisCross
Beiträge: 124
Erhaltene Danke: 12
Windows 10 64 bit
Delphi XE6 Starter
|
Verfasst: So 08.02.15 11:14
Hallo,
ich habe ein Problem mit der Lösung eines Loginsystemes. Meine Idee war folgende:
Auf einem FTP Server liegt in einem Verzeichnis eine ini Datei mit den Benutzernamen und den Kennwörtern. Das Verzeichnis ist per .htaccess und .htpasswd vor direkten Zugriffen geschützt. Mein Programm liest jetzt über idhttp die Datei aus und Überprüft den Benutzernamen und das Passwort. Ich kann mir jetzt nur nicht vorstellen, das das so sicher ist
Eine Datenbank wäre wahrscheinlich sicherer, aber die MySQL Datenbank auf dem Server erlaubt keine externen Zugriffe und somit kann ich darauf auch nicht zugreifen?!
Zweite Idee war eine Webseite mit einem Loginformular, das mit der Datenbank kommuniziert. Aus meinem Programm könnte ich die Felder ausfüllen und überprüfen ob der Login richtig war. Die Datensicherheit sieht hier aber wahrscheinlich noch schlechter aus.
Ich habe jetzt keine weiteren Ideen wie ich das sonst lösen soll. Vielleicht hat ja jemand einen Denkanstoß für mich
Christoph
|
|
FinnO
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: So 08.02.15 13:04
Moin,
Passwörter dürfen niemals unverschlüsselt gespeichert werden. Ich entnehme deinem Post mal, dass du eine Delphi-Anwendung hast, für die sich Nutzer mit einem im Internet hinterlegten Passwort anmelden sollen. Was du hier tun möchtest, ist einen Authentifizierungsdienst zu verwenden.
Im Fall eins bedeutet das, dass du dir eine Anwendung schreibst, die auf deinem Server läuft und deine Anmeldungen entgegennimmt und verifiziert - hier hast du dann auch Datenbankzugriff.
Der andere - und vernünftigere Weg wäre, auf einen Drittanbieter wie das kleine Softwareunternehmen Google zurückzugreifen. So können Nutzer ihren Google-Account verwenden, den sie eh bereits besitzen. Ob du denen dann Zugriff auf deine Software gewährst, musst du dann zu einem anderen Zeitpunkt entscheiden.
Das waren erstmal zwei Denkanstöße von mir.
Gruß
Für diesen Beitrag haben gedankt: ChrisCross
|
|
ChrisCross
Beiträge: 124
Erhaltene Danke: 12
Windows 10 64 bit
Delphi XE6 Starter
|
Verfasst: So 08.02.15 17:54
Vielen Dank für deine Antwort, jetzt weiß ich schon mal die Richtung
Zitat: | Im Fall eins bedeutet das, dass du dir eine Anwendung schreibst, die auf deinem Server läuft und deine Anmeldungen entgegennimmt und verifiziert - hier hast du dann auch Datenbankzugriff. |
Also in der Art eine Datei, die aus meiner Anwendung einen Befehl gesendet bekommt (per indy?) und dann in der Datenbank nachsieht und das ausgibt und mein Programm liest das aus?
Hast du vielleicht dazu ein gutes Tutorial?
|
|
FinnO
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: So 08.02.15 21:40
Moin,
das kommt darauf an, welche Programmiersprache du Serverseitig einsetzen möchtest. Googlen solltest du auf jeden Fall mal RESTful Service.
Gruß
Finn
Für diesen Beitrag haben gedankt: ChrisCross
|
|
ChrisCross
Beiträge: 124
Erhaltene Danke: 12
Windows 10 64 bit
Delphi XE6 Starter
|
Verfasst: Fr 13.02.15 15:46
Danke für deine Antwort. Bisher habe ich mir folgendes Überlegt:
Im Delphi Programm
Delphi-Quelltext 1: 2: 3: 4:
| procedure TForm1.Button1Click(Sender: TObject); begin Memo1.Text := IdHttp1.Get('http://www.meine-seite.de/service.php?Benutzername=test&Kennwort=test'); end; |
Die PHP Datei:
PHP-Quelltext 1: 2: 3: 4: 5: 6: 7:
| <?php $benutzername = $_GET["Benutzername"]; $kennwort = $_GET["Kennwort"];
?> |
Un das Ergebnis kann ich ja dann auswerten
Natürlich gibst bisher mit der Sicherheit wieder Probleme. Ist es sicherer wenn ich die Datei per .htpasswd schütze? Und wie sieht es mit IdHttp1 aus?
Oder muss ich ganz anders herangehen. Ich hoffe was ich mir überlegt habe, kommt nicht ganz so stümperhaft herüber
|
|
BenBE
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Fr 13.02.15 19:06
ChrisCross hat folgendes geschrieben : | Hallo,
ich habe ein Problem [...]
[...] einem FTP Server [...] |
Okay, den möchte man loswerden
ChrisCross hat folgendes geschrieben : | [...] eine Datei mit den Benutzernamen und den Kennwörtern. |
Du möchtest mindestens SCrypt-SHA2-512 für die Sicherung der Passworte nutzen ...
ChrisCross hat folgendes geschrieben : | Das Verzeichnis ist per .htaccess und .htpasswd vor direkten Zugriffen geschützt. Mein Programm liest jetzt über idhttp die Datei aus und Überprüft den Benutzernamen und das Passwort. |
Ich frag jetzt lieber NICHT nach, ob da sowas wie "Verschlüsslung" verwendet wird. Das wird mir sonst zu deprimierend ...
ChrisCross hat folgendes geschrieben : | Ich kann mir jetzt nur nicht vorstellen, das das so sicher ist |
Captain Obvious ruft grad an, er möchte seinen Job wieder.
ChrisCross hat folgendes geschrieben : | Eine Datenbank wäre wahrscheinlich sicherer, aber die MySQL Datenbank auf dem Server erlaubt keine externen Zugriffe und somit kann ich darauf auch nicht zugreifen?! |
Script drauf, was für einen Nutzernamen den zugehörigen Salt/SCrypt-Parameter und für Nutzernamen + SCrypt-Hash (mit diesen Parametern) den Erfolgsstatus zurückgibt. Das ganze über eine entsprechend gesicherte TLS 1.2+-Verbindung mit CAMELLIA256/AES256 GCM/CCM und SHA2-384 garniert mit nem vernünftigen Zertifikat (RSA 4096 für nahe Zukunft, RSA 8192 für Mittelfristig und RSA 15364 für was, was länger halten darf) welches mit SHA2 (SHA2-512 FTW) oder SHA3 signiert ist.
ChrisCross hat folgendes geschrieben : | Zweite Idee war eine Webseite mit einem Loginformular, das mit der Datenbank kommuniziert. Aus meinem Programm könnte ich die Felder ausfüllen und überprüfen ob der Login richtig war. Die Datensicherheit sieht hier aber wahrscheinlich noch schlechter aus. |
Kommt drauf an. Simples REST, was einfach per POST zwei Parameter nimmt und mit 0 Bytes bei Fehler antwortet ist sicherlich sehr rudimentär, aber tut seinen Job. Und solange Du nicht bei Robert's Schule den Code klaust, sollte auch der Schutz der DB zu schaffen sein. BTW: MySQL kann für die Connection auch TLS, nutzt nur meist keiner.
ChrisCross hat folgendes geschrieben : | Ich habe jetzt keine weiteren Ideen wie ich das sonst lösen soll. Vielleicht hat ja jemand einen Denkanstoß für mich
Christoph |
Wieviel Wert schätzt Du die Daten?
Was sichern sie denn ab?
Alternativ, solltest Du Dir einmal OAuth anschauen.
FinnO hat folgendes geschrieben : | Moin,
Passwörter dürfen niemals unverschlüsselt gespeichert werden. |
Hausaufgabe für den Threadersteller: Diesen Satz bis morgen 100 Mal an die Tafel schreiben.
FinnO hat folgendes geschrieben : | Ich entnehme deinem Post mal, dass du eine Delphi-Anwendung hast, für die sich Nutzer mit einem im Internet hinterlegten Passwort anmelden sollen. Was du hier tun möchtest, ist einen Authentifizierungsdienst zu verwenden. |
Oder es wie oben beschrieben abgesichert selber bauen. Wobei noch hinzu kommt, dass man auf einige Side-Channel achten muss (und z.B. nicht leaken sollte, ob es einen Nutzer gibt oder nicht), aber das ist Schritt 2.
FinnO hat folgendes geschrieben : | Im Fall eins bedeutet das, dass du dir eine Anwendung schreibst, die auf deinem Server läuft und deine Anmeldungen entgegennimmt und verifiziert - hier hast du dann auch Datenbankzugriff. |
Bitte Anmerkungen von oben beachten.
FinnO hat folgendes geschrieben : | Der andere - und vernünftigere Weg wäre, auf einen Drittanbieter wie das kleine Softwareunternehmen Google zurückzugreifen. So können Nutzer ihren Google-Account verwenden, den sie eh bereits besitzen. Ob du denen dann Zugriff auf deine Software gewährst, musst du dann zu einem anderen Zeitpunkt entscheiden. |
Wobei hier die ToS von diesem Kleinunternehmen aus Kalifornien gelten, was die hiesigen Datenschutzbestimmungen und die daraus resultierenden Datenschutzerklärungen deutlich verlängert ...
ChrisCross hat folgendes geschrieben : | Danke für deine Antwort. Bisher habe ich mir folgendes Überlegt:
Im Delphi Programm:
Delphi-Quelltext 1: 2: 3: 4:
| procedure TForm1.Button1Click(Sender: TObject); begin Memo1.Text := IdHttp1.Get('http://www.meine-seite.de/service.php?Benutzername=test&Kennwort=test'); end; | |
Sensible Daten wie Logins NIE! mit GET übertragen, da diese ansonsten ins Access Log des Servers geleakt werden (könnten).
Für sowas nimmt man immer POST.
ChrisCross hat folgendes geschrieben : | Die PHP Datei:
PHP-Quelltext 1: 2: 3: 4: 5: 6: 7:
| <?php $benutzername = $_GET["Benutzername"]; $kennwort = $_GET["Kennwort"];
?> |
Und das Ergebnis kann ich ja dann auswerten |
Jup, implementierungsdetails siehe weiter oben in meinem Post.
ChrisCross hat folgendes geschrieben : | Natürlich gibst bisher mit der Sicherheit wieder Probleme. |
Ich seh bei dieser PHP-Datei erstmal nur das Problem, dass dieser Quelltext eine Konstante Funktion implementiert, du aber eine Punkt-Funktion zum Funktionieren brauchst
ChrisCross hat folgendes geschrieben : | Ist es sicherer wenn ich die Datei per .htpasswd schütze? |
Nein.
ChrisCross hat folgendes geschrieben : | Und wie sieht es mit IdHttp1 aus? |
Nein.
ChrisCross hat folgendes geschrieben : | Oder muss ich ganz anders herangehen. |
Verschlüsselte Verbindung oder PAKE.
ChrisCross hat folgendes geschrieben : | Ich hoffe was ich mir überlegt habe, kommt nicht ganz so stümperhaft herüber |
Entspricht dem Stand der Technik auf den meisten Selbstbau-Websites ...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Für diesen Beitrag haben gedankt: ChrisCross
|
|
Xearox
Beiträge: 260
Erhaltene Danke: 3
|
Verfasst: Sa 14.02.15 08:31
Also mein Denkansatz wäre folgender:
Mit deinem Delphi Programm auf den MySQL Server Verbinden und dort entsprechend den Usernamen und Passwort abfragen.
Das Passwort selbstverständlich als MD5 in der Datenbank hinterlegen das vom User eingegebene Passwort entsprechend mit dem in der Datenbank vergleichen.
Passt alles, kann man fortfahren. Stimmt was nicht, also ist das Passwort falsch, schickste einfach ein SWAT Team beim User vorbei, die Regeln das schon für dich
Aber im ernst, eine User und Passwort Liste auf einem Server packen ist keine gute Idee, vor allem nicht, wenn es sich um Klartext Passwörter handelt. Was machste, wenn dein Server gehackt wird und der Hacker dann diese Liste mit den ganzen Passwörtern sieht? Da freuen sich dann deine User
Also, wie schon oben geschrieben.
Login Daten auf MySQL Server schmeißen, mit deinem Delphi Programm entsprechend eine Datenbank Verbindung aufbauen, den Usernamen in der Datenbank suchen und das MD5 Passwort mit dem im Programm eingegeben Passwort vergleichen. Passt alles, kann der Zugang gewährt werden.
So ist es sicherlich sicherer als dein Weg.
|
|
BenBE
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mo 16.02.15 08:18
Xearox hat folgendes geschrieben : | Also mein Denkansatz wäre folgender:
Mit deinem Delphi Programm auf den MySQL Server Verbinden und dort entsprechend den Usernamen und Passwort abfragen. |
M(
Und wie schützt Du den Login zur DB?
Xearox hat folgendes geschrieben : | Das Passwort selbstverständlich als MD5 in der Datenbank hinterlegen das vom User eingegebene Passwort entsprechend mit dem in der Datenbank vergleichen. |
Nein!
MD5 macht man nicht, Salted MD5 nur, wenn man nicht weiß, was man tut und ansonsten nimmt man was geeignetes: SCrypt, wie ich oben bereits schrieb.
Xearox hat folgendes geschrieben : | Passt alles, kann man fortfahren. Stimmt was nicht, also ist das Passwort falsch, schickste einfach ein SWAT Team beim User vorbei, die Regeln das schon für dich |
Ich freu mich schon auf das SWAT, weil die Verbindung abgerissen ist
Xearox hat folgendes geschrieben : | Aber im ernst, eine User und Passwort Liste auf einem Server packen ist keine gute Idee, vor allem nicht, wenn es sich um Klartext Passwörter handelt. |
Der erste (halbwegs) korrekte Satz in deinem Posting.
Xearox hat folgendes geschrieben : | Was machste, wenn dein Server gehackt wird und der Hacker dann diese Liste mit den ganzen Passwörtern sieht? |
Das wird schon keinem Auffallen. Und die Chinesen freuen sich sicherlich darüber
Xearox hat folgendes geschrieben : | Da freuen sich dann deine User |
Die natürlich auch!
Xearox hat folgendes geschrieben : | Also, wie schon oben geschrieben. |
Bei Xearox sieht man, wie man's möglichst nicht macht
Xearox hat folgendes geschrieben : | Login Daten auf MySQL Server schmeißen, mit deinem Delphi Programm entsprechend eine Datenbank Verbindung aufbauen, den Usernamen in der Datenbank suchen und das MD5 Passwort mit dem im Programm eingegeben Passwort vergleichen. Passt alles, kann der Zugang gewährt werden. |
Und das Passwort zum MySQL wird Klartext über die Verbindung gejagt, damit der Angreifer gleich mitlesen kann
Xearox hat folgendes geschrieben : | So ist es sicherlich sicherer als dein Weg. |
Nein.
P.S.: BSI TR-02102-1 v2015-01 Kapitel 4 und 6.3, sowie dieses hier.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Für diesen Beitrag haben gedankt: ChrisCross
|
|
ChrisCross
Beiträge: 124
Erhaltene Danke: 12
Windows 10 64 bit
Delphi XE6 Starter
|
Verfasst: So 22.02.15 15:02
Vielen Dank für eure Antworten, besonders von BenBE ,
Zitat: |
Sensible Daten wie Logins NIE! mit GET übertragen, da diese ansonsten ins Access Log des Servers geleakt werden (könnten).
Für sowas nimmt man immer POST.
|
und
Zitat: |
Zitat: | Zweite Idee war eine Webseite mit einem Loginformular, das mit der Datenbank kommuniziert. Aus meinem Programm könnte ich die Felder ausfüllen und überprüfen ob der Login richtig war. Die Datensicherheit sieht hier aber wahrscheinlich noch schlechter aus. |
Kommt drauf an. Simples REST, was einfach per POST zwei Parameter nimmt und mit 0 Bytes bei Fehler antwortet ist sicherlich sehr rudimentär, aber tut seinen Job. Und solange Du nicht bei Robert's Schule den Code klaust, sollte auch der Schutz der DB zu schaffen sein. BTW: MySQL kann für die Connection auch TLS, nutzt nur meist keiner. |
Ich habe mich jetzt noch mal kurz mit beschäftig:
Delphi Code:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| procedure TForm1.btn1Click(Sender: TObject); var data: TStringList; s: String; begin data := TStringList.Create; try data.Values['name'] := 'test'; data.Values['pwd'] := 'test'; try s := IdHTTP1.Post('http://webseite.de/delphi-login.php', data); ShowMessage(s); except on E: Exception do ShowMessage('Fehler: ' + E.Message); end; finally data.Free; end; end; |
und PHP Code:
PHP-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| <?php session_start(); ?>
<?php $verbindung = mysql_connect("host", "benutzer" , "kennwort") or die("Verbindung zur Datenbank konnte nicht hergestellt werden"); mysql_select_db("datenbankname") or die ("Datenbank konnte nicht ausgewählt werden");
$username = $_POST["name"]; $passwort = md5($_POST["pwd"]);
$abfrage = "SELECT Benutzername, Kennwort FROM tabelle WHERE Benutzername LIKE '$username' LIMIT 1"; $ergebnis = mysql_query($abfrage); $row = mysql_fetch_object($ergebnis);
if($row->Kennwort == $passwort) { $_SESSION["username"] = $username; echo 'LOGIN'; exit; } else { echo 'FALSCH'; }
?> |
Ich hoffe ihr reißt mit jetzt dafür nicht den Kopf ab
Sicherheit ist jetzt besser? Die Passwörter werden ja jetzt noch im Klartext versendet?! Also müsste ich das vorher noch verschlüsseln.
|
|
jfheins
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: So 22.02.15 16:39
Ohhhmmmm ... besser vielleicht, aber noch nicht gut
1. Du verwendest die alte mysql-Bibliothek in PHP. Du solltest besser mysqli einsetzen. (Im einfachsten Fall einfach alle Aufrufe um das 'i' ergänzen, ist aber Sicherheitstechnisch noch nicht so schlimm)
2. Du verwendest MD5? Falls du nicht PCs von 1992 zum berechnen verwendest, darf es ruhig etwas besseres sein.
Zitat: | Nein! MD5 macht man nicht |
Mindestens sha1 verwenden! Besser noch (falls du ein halbwegs aktuelles PHP hast) SHA2, also z.B.: $passwort = hash('sha384', $_POST["pwd"]);
3. Und hier:
PHP-Quelltext 1:
| Benutzername LIKE '$username' |
Ich würde da das like streichen und stattdessen auf Gleichheit prüfen (ggf. case-insensitive) weil ich mit like a% schreiben kann und alle Benutzernamen matchen die mit a anfangen.
4. Wenn du die Kennwörter nicht im Klartext übertragen willst: Rufe zuerst eine PHP-Funktion auf, die eine Zufallszahl generiert. Diese wird in der Session gespeichert und zurückgegeben (nennen wir ihn 'token'). Im Delphi-Programm bildest du nun folgenden Hashwert:
Delphi-Quelltext 1:
| data.Values['pwd'] := sha382(token + sha384('test')); |
Am Server mit PHP holst du dir den token wieder aus der session und vergleichst so: PHP-Quelltext 1: 2: 3:
| $passwort = $_POST["pwd"]; hash('sha384', token + $row->Kennwort) === $passwort |
Die drei Gleichheitszeichen sind WICHTIG!!
Für diesen Beitrag haben gedankt: ChrisCross
|
|
ChrisCross
Beiträge: 124
Erhaltene Danke: 12
Windows 10 64 bit
Delphi XE6 Starter
|
Verfasst: Di 24.02.15 16:22
Vielen vielen Dank für deine Hilfe,
du hast mir ganz doll weitergeholfen
|
|
Narses
Beiträge: 10181
Erhaltene Danke: 1254
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 24.02.15 16:42
Moin!
jfheins hat folgendes geschrieben : | 1. Du verwendest die alte mysql-Bibliothek in PHP. Du solltest besser mysqli einsetzen. (Im einfachsten Fall einfach alle Aufrufe um das 'i' ergänzen, ist aber Sicherheitstechnisch noch nicht so schlimm) |
Das würde ich konkret "sicherheitstechnisch" für völlig egal halten es sei denn, der MySQL-Server ist nicht auf der gleichen Maschine oder du rechnest damit, dass diese Maschine jeden Tag 3x gehacked wird. Oder hast du konkrete Referenzen, was die Sicherheitsbedenken angeht (Links zur Hand)?
Was du aber in dem Zusammenhang auch erwähnen solltest: wenn man mit mysql i arbeitet, sollte man auch mit persistenten Sessions arbeiten, sonst handelt man sich für jeden Request eine Straf-Sekunde Wartezeit ein...
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
jfheins
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Di 24.02.15 19:17
Dann weißt du da mehr als ich.
Ich habe irgendwo gelesen , dass die mysql-Bibliothek (ohne i) veraltet sei, und man sie nicht mehr benutzen solle, und dass sie möglicherweise in Zukunft entfernt wird.
Konkreter also vielleicht "sicherheitstechnisch völlig egal, aber best practise" ?
|
|
Martok
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Di 24.02.15 20:59
Mysqli ist vor allem deswegen sinnvoll, weil man damit Prepared Statements bekommt. Wenn man die dann auch konsequent benutzt, sind einfach keine SQL-Injections mehr möglich und man braucht sich über sehr viel Validation keine Gedanken mehr zu machen.
Das was jfheins da unter "4." vorschlägt ist übrigens eine Variante eines HMAC und eine der wenigen Möglichkeiten, wie man ein Passwort prüfen kann ohne es an irgend einer Stelle gekannt haben zu müssen.
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
|