suit: Fragwürdige Literatur (web & mobile Developer, Ausgabe 11/2013)

Wir haben hier in der Agentur eine Latte an Fachzeitschriften aboniert - darunter auch "web & mobile Developer" (www.webundmobile.de) - darin ist in der Ausgabe 11/2013 ein Artikel zum Erstellen eines Zugriffschutzes drin.

Der Artikel strotzt nur so von fachlichen Fehlern und ist stellenweise auch ein nicht zu vernachlässigendes Sicherheitsrisiko.

In der MySQL-Tabelle wird die E-Mail-Adresse als Primärschlüssel verwendet und behauptet, damit wäre sichergestellt, dass sie eindeutig ist. Ein paar Zeilen Später wird gesagt, dass der Benutzername natürlich auch eindeutig sein soll und man das nachher im PHP-Script prüfen soll - wozu?

Warum kann man keinen Index über Benutzername + E-Mail ziehen und beide dann als Kombination eindeutig machen oder jeweils einzeln oder drauf pfeifen, dass es irgendwo Doppelungen gibt, Wurst wie - aber was hat das für einen Sinn die Hälfte in der Datenbank zu machen, die andere Hälfte in PHP?

Das Feld für die Passwörter ist als varchar(10) definiert und wird mit einem MD5-Hash befüllt - warum? Als Zeichenkette hat ein MD5-Hash 32 Zeichen, wie soll das funktioneren?

Dann werden im Script variablen herumkopiert $benutzer = $_POST['benutzer'].

Die (Un)gültigkeit der Eingaben wird mit == "" geprüft - von isset() oder empty() hat der Autor noch nichts gehört.

Nebenbei sollte man erwähnen, dass der Autor auch von Zeichenkodierung oder HTML nicht viel versteht - in den Codebeispielen stehen tolle Konstrukte wie "Bitte F&uuml;llen Sie alle felder aus</br>" drin.

Für das Passwort-Eingabefeld wird ein maxlenth-Attribut gesetzt, 10 Zeichen (na, klingelts). Man soll das Passwort nach bestimmten Kriterien auf seine Sicherheit prüfen m(

MD5 wird als Verschlüsselung bezeichnet und auch noch behauptet, das Passwort wäre damit Optimal geschützt - gehts noch? MD5 war nie zum Hashen von Passwörtern gedacht und der Hash eines 10-stelliges Passwort ist ratz-fatz geknackt.

Na wenigstens schlägt der Autor die Nutzung von mysqli im objektorientierten Stil vor.

Jetzt wird es wieder Gruselig bei der Registrierung: es wird geprüft, ob der gewünschte Benutzername schon existiert - man holt sich also eine Liste _aller_ Benutzer und geht die in einer Schleife durch und prüft in jedem Durchauf ob diese mit dem eigengebenen Benutzernamen übereinstimmt - wenn ja, wird eine Fehlermeldung ausgegeben - inklusive dem ungeprüften Benutzernamen: offene Lücke für eine XSS-Attacke.

Wenn die Schleife ohne "fehler" durchgelaufen ist, wird der neue Benutzer eingefügt - wobei die zuvor "umkopierten Werte" 1:1 im Klartext übernommen werden (mit Ausnahme des Passworts, das wurde ja in MD5 überführt) - hier gibts also gleich 2 gelegenheiten für eine SQL-Injection.

Es wird nur in einem kleinen absatz drauf hingewisen, dass man real_escape_string() verwenden soll, wenn man im Benutzer "Sonderzeichen" erlauben will - die Mailadresse selbst wird weiterhin ungesichert übergeben - bleibt, falls man das möchte, immer noch eine Möglichkeit für eine Injection.

Einfach auf verdacht ein INSERT auszuführen und dann prüfen obs geklappt hat wäre (wir erinnern uns an den Anfang, wo die "Modellierung" schon scheitert) effizienter, man müsste nur schaun ob ein ERROR 1062 zurückkommt, dann weiß man dass der Key schon existiert.

Zusätzlich bietet der beschriebene Vorgang im Artikel auch die Möglichkeit einer Race Condition wenn man prüft ob ma einfügen darf und jemand "gleichzeitig" denselben Benutzernamen registrieren möchte.

Jetzt kommt ein kleiner Nebensatz zu unserer 10-Zeichen-Geschichte des Passworts - hier wird behauptet, dass das das "verschlüsselte" Passwort idR. länger ist als das Klartextpasswort und dieser verschlüsselte Text "oft" länger ist als 10 Zeichen - nein, nicht oft: immer ein MD5-Hash ist (egal wie man es dreht) 32 Zeichen (in hex) lang bzw. eine 128-Bit Ganzzahl.

Die Lösung für dieses Problem ist vergleichsweise einfach - nein, wenn man jetzt denkt "hey, machen wir das Feld einfach länger" irrt man gewaltig - der Autor des Artikels empiehlt, mit substr einfach nur die ersten 10 Zeichen abzuschneiden. WTF! Damit reduzieren wir also die mögliche Anzahl an unterschiedlichen Passwörtern/Hashes auf etwa 1 Billion Möglichkeiten - das ist gradezu lächerlich wenig und erleichtert einen möglichen Brute-Force-Angriff enorm, weil es sehr schnell zu Kollisionen kommt.

Jetzt gehts weiter mit Sessions: wenn man es _wirklich sicher_ haben möchte braucht man diese - wie das funktionieren soll wird sicher erklärt, aber ich will da jetzt garnicht mehr weiterlesen - allein die kleinen Codebeispiele die sich auf der Seite verteilen sind schon schrecklich genug.

Den Sourcecode kann man sich übrigens hier anschaunen:
http://www.webundmobile.de/content/download/10883/193874/file/0603_Listings.zip

Der Autor des Artikels gibt übrigens an, schon "zahlreiche Fachbücher und Beiträge in Computer-Fachzeitschriften" geschrieben zu haben - ich frag' mich immer wieder, wie das funktioniert. Das tut weh, ist unseriös, fahrlässig und irgendwie auch Betrug am Leser.

Mich ärgert sowas jedes mal Maßlos, wenn jemand mit derart schlechter arbeit Geld verdient und ich mir auf der anderen Seite immer wieder anhören muss, dass das was ich mache auch andere können, nur billiger. Oder dass in "Fachzeitschrift X" ein Artikel (wie z.B. dieser) zu finden ist wo steht, wie leicht das alles geht und man nicht immer die "Königslösung" anstreben solle. Ist denn heutzutage ordentliche Arbeit so aus der Mode gekommen?

  1. Tach!

    Der Artikel strotzt nur so von fachlichen Fehlern und ist stellenweise auch ein nicht zu vernachlässigendes Sicherheitsrisiko.

    Ich hoffe, du hast das auch dem Autor oder Verlag erzählt.

    dedlfix.

    1. Der Artikel strotzt nur so von fachlichen Fehlern und ist stellenweise auch ein nicht zu vernachlässigendes Sicherheitsrisiko.

      Ich hoffe, du hast das auch dem Autor oder Verlag erzählt.

      Selbstverständlich, bisher aber keine Reaktion - ich hab heute noch mal schnell einen Tweet nachgeschossen, mal schaun ob da was kommt.

  2. In der MySQL-Tabelle wird die E-Mail-Adresse als Primärschlüssel verwendet und behauptet, damit wäre sichergestellt, dass sie eindeutig ist.

    Eindeutig ist sie damit ja schon. Aber ob die unbedingt Kandidat für einen Primärschlüssel ist? Das sollte vielmehr ein Auto-Wert sein würd ich sagen.

    Ein paar Zeilen Später wird gesagt, dass der Benutzername natürlich auch eindeutig sein soll und man das nachher im PHP-Script prüfen soll - wozu?

    Eindeutige Benutzernamen machen das Einloggen um einiges einfacher :-) Prüfen ist doch ok, besser als wenn die DB einem das um die Ohren haut.

    Warum kann man keinen Index über Benutzername + E-Mail ziehen und beide dann als Kombination eindeutig machen

    Macht nicht wirklich Sinn, dann könnte eine Mailadresse mit mehreren Benutzernamen verknüpft sein und andersrum auch.

    Der Rest ist in der Tat ziemlich krass.

    man holt sich also eine Liste _aller_ Benutzer und geht die in einer Schleife durch

    Grad ist doch große Krankheitswelle, da kanns schon passieren dass man einen Buchhalter (nicht negativ gemeint!) über PHP schreiben lässt :-)

    Zusätzlich bietet der beschriebene Vorgang im Artikel auch die Möglichkeit einer Race Condition wenn man prüft ob ma einfügen darf und jemand "gleichzeitig" denselben Benutzernamen registrieren möchte.

    Da würde ich es drauf ankommen lassen dass die DB mir alle paar Jahre mal einen Fehler wirft und die Anmeldung dann zu wiederholen ist.

    Hast du denen geschrieben was du davon hältst? Da wäre ein Leserbrief angebracht, nicht nur eine Mail. Wenn sie mutig sind lassen sie das 1. prüfen und drucken 2. eine Reaktion drauf ab. Es kann nur besser werden.

    1. Hast du denen geschrieben was du davon hältst? Da wäre ein Leserbrief angebracht, nicht nur eine Mail. Wenn sie mutig sind lassen sie das 1. prüfen und drucken 2. eine Reaktion drauf ab. Es kann nur besser werden.

      Die Form meiner Meldung ist jetzt nicht wirklich leserbrieftauglich gewesen - sogar das hier im Forum ist besser - spannend wäre es, wenns wirklich eine Reaktion gäbe.

    2. Moin Encoder,

      In der MySQL-Tabelle wird die E-Mail-Adresse als Primärschlüssel verwendet und behauptet, damit wäre sichergestellt, dass sie eindeutig ist.
      Eindeutig ist sie damit ja schon. Aber ob die unbedingt Kandidat für einen Primärschlüssel ist? Das sollte vielmehr ein Auto-Wert sein würd ich sagen.

      Depends.

      Das Ziel von Datenbank-Design ist es, die natürliche Form der Daten abzubilden. Da ist die E-Mail-Adresse durchaus ein valider Primary Key. Man muss sich nur im klaren darüber sein, dass eine Änderung der E-Mail-Adresse dadurch ggfls. Problematisch wird, etwa bei vielen Foreign-Key-Constraints. Es kann sich also lohnen, einen künstlichen Primär-Schlüssel einzuführen. Muss aber nicht.

      Ein paar Zeilen Später wird gesagt, dass der Benutzername natürlich auch eindeutig sein soll und man das nachher im PHP-Script prüfen soll - wozu?
      Eindeutige Benutzernamen machen das Einloggen um einiges einfacher :-) Prüfen ist doch ok, besser als wenn die DB einem das um die Ohren haut.

      Selber prüfen (im Sinne von SELECT und nachfolgender Script-Verarbeitung) hat zur Folge, dass du entweder die Tabelle (sic! Nicht nur eine Reihe, sondern die ganze Tabelle) Schreib-Locken musst oder dass du eine Race Condition schaffst.

      Siehe auch [http://en.wikipedia.org/wiki/Isolation_%28database_systems%29@title=Isolation].

      LG,
       CK

  3. Hi!

    Spannend. Aber um mal auf deine Frage zu kommen:

    Mich ärgert sowas jedes mal Maßlos, wenn jemand mit derart schlechter arbeit Geld verdient und ich mir auf der anderen Seite immer wieder anhören muss, dass das was ich mache auch andere können, nur billiger. Oder dass in "Fachzeitschrift X" ein Artikel (wie z.B. dieser) zu finden ist wo steht, wie leicht das alles geht und man nicht immer die "Königslösung" anstreben solle. Ist denn heutzutage ordentliche Arbeit so aus der Mode gekommen?

    Ich fuerchte ja. Es gibt scheinbar nur 2 Faktoren: Zeit und Geld. Beides sollte so wenig wie moeglich verbraucht und soviel wie moeglich gespart werden.

    Wenn Du in 4 Stunden was zauberst, das 100.000 bringt waehrend deine Kollegen in 2 Stunden abliefern, und damit jeweils nur 40.000 bringen, wirst du nicht gelobt, dass du bei doppeltem Aufwand mehr als das doppelte reinbringst, sondern dir wird vorgerechnet was du reinholen koenntest wenn du mal schneller machen wuerdest. Ob Du jetzt was produzierst oder ne Dienstleistung erbringst, spielt dabei keine Rolle. Ich beobachte immer wieder, dass die Nullen das bessere Leben fuehren, waehrend Leistungstraeger gestresst werden ohne was davon zu haben. Hoechstens mehr Arbeit bei weniger Geld.

    --
    Signaturen sind bloed.
  4. hi,

    In der MySQL-Tabelle wird die E-Mail-Adresse als Primärschlüssel verwendet und behauptet, damit wäre sichergestellt, dass sie eindeutig ist. Ein paar Zeilen Später wird gesagt, dass der Benutzername natürlich auch eindeutig sein soll und man das nachher im PHP-Script prüfen soll - wozu?

    Nun, eine Emailadresse ist weltweit eindeutig. Grundsätzlich spricht nichts dagegen, die Emailadresse als Primärschlüssel zu verwenden. Es ist auch für den Benutzer einfacher, sich nur die Emailadresse merken zu müssen, als einen zusätzlichen Benutzernamen. Oft ists jedoch sinnvoller, in einer Tabelle einen vom Inhalt unabhängigen Primärschlüssel zu designen, beispielsweise ein auto-increment und auf das email-Feld einen Unique Key zu setzen.

    Unsittig ists freilich, irgendwelche Eindeutigkeiten mit PHP prüfen zu wollen, das überlassen wir selbstverständlich der DB-Engine, die macht sowas eindeutig performanter. Und es gibt für einen Benutzer keine beklopptere Meldung als die, dass sein Name schon anderweitig vergeben ist. Bei solchen u.ä. Datenerhebungen würde ich auch eine Kollation einstellen, die Case-Sensitive ist.

    Fatal jedoch, nicht machen: Das Passwort (Neueingabe Klartext) von der DB-Engine hashen zu lassen. Wenns Logging eingeschaltet ist, siehste, siehste ;)

    Viele Grüße,
    [Name schon anderweitig vergeben]

    1. Fatal jedoch, nicht machen: Das Passwort (Neueingabe Klartext) von der DB-Engine hashen zu lassen. Wenns Logging eingeschaltet ist, siehste, siehste ;)

      Idealerweise wird das Passwort schon am Client per JavaScript gehasht und dann an den Server weitergeben - mit der Info, ob es nun schon als Hash vorliegt oder dort noch gehast werden muss.

      Und dann blos nicht mit MD5 sondern gleich ordentlich, mit bcrypt:
      http://code.google.com/p/javascript-bcrypt/

      1. hi,

        Und dann blos nicht mit MD5 sondern gleich ordentlich, mit bcrypt:
        http://code.google.com/p/javascript-bcrypt/

        Ahh, gesalzen ;)
        Nun, das Salz müsste ja dann auch zum Server geschafft werden, oder kann das aus dem Hash extrahiert werden?

        Eine andere Lösung, wo ich einsetze, ist: Apache-MD5 (das ist auch gesalzen). Mit htpasswd erzeugte Passwort-Hashes haben ein extrahierbares salt und es gibt ein in Perl programmiertes Inferface (CPAN). Das wird in dem Moment interessant, wenn es sowohl eine Passwort-Datei geben muss (damit der Super-Admin überhaupt erstmal reinkommt in sein Backend) als auch in DB hinterlegte Passworte für weitere Benutzer in Gruppen.

        Mit Apache-MD5 und dem Perl-Interface ists möglich, sowohl einen Authorization-Basic-Realm zu schaffen als auch einen davon unabhängigen Login-Prozess auf eine bestehende Session zu setzen. Oder Beides. Oder für einen kleineren Benutzerkreis nur eine mit htpasswd erzeugte Passwortdatei für echte Login-Geschichte zu verwenden.

        Viele Grüße,
        [Name leider bereits anderweitig vergeben]

        1. Ahh, gesalzen ;)
          Nun, das Salz müsste ja dann auch zum Server geschafft werden, oder kann das aus dem Hash extrahiert werden?

          bcrypt selbst hat einen integrierten Salt

          Beispiel:

          $2a$10$tIatBEndedu&up.QvaR22mekupudakuGebuy7b9a5rayZ4a6u9afe

          2a sagt = ich bin bcrypt (vgl. Modular Crypt Standard)
          10 sagt = ich bin ein cost-factor von 10 also 2^10 Wiederholungen
          tIatBEndedu&up.QvaR22m ist der Salt (16 Byte in Base64)
          ekupudakuGebuy7b9a5rayZ4a6u9afe ist der Hash des Passworts (24 Byte in Base64

          1. Ahh, gesalzen ;)
            Nun, das Salz müsste ja dann auch zum Server geschafft werden, oder kann das aus dem Hash extrahiert werden?

            bcrypt selbst hat einen integrierten Salt

            Beispiel:

            $2a$10$tIatBEndedu&up.QvaR22mekupudakuGebuy7b9a5rayZ4a6u9afe

            2a sagt = ich bin bcrypt (vgl. Modular Crypt Standard)
            10 sagt = ich bin ein cost-factor von 10 also 2^10 Wiederholungen
            tIatBEndedu&up.QvaR22m ist der Salt (16 Byte in Base64)
            ekupudakuGebuy7b9a5rayZ4a6u9afe ist der Hash des Passworts (24 Byte in Base64

            hi danke!!

            So ähnlich sieht Apache-md5 aus.

            Gruß,
            $*

            1. So ähnlich sieht Apache-md5 aus.

              Apache MD5 ist aber ziemlich unsicher - es ist nur ein MD5 mit zufälligem Salt der in 1000-facher-Wiederholung durchgeführt wird - weil MD5 so schnell ist, macht es das ziemlich anfällig für Brute-Force-Angriffe.

              Es ist aber immer noch das sicherste was Apache zu bieten hat.

      2. Hallo,

        Idealerweise wird das Passwort schon am Client per JavaScript gehasht

        Idealerweise werden alle Daten SSL-verschlüsselt übertragen. Das Hashen auf dem Client ist eher ein Sicherheitsverlust, weil man von einer clientseitigen Implementierung abhängig ist, die auf tausenden unterschiedlichen Geräten läuft und viel einfacher angreifbar ist. In JavaScript habe ich nicht browserübergreifend Zugriff auf einen brauchbaren Seed für einen kryptographisch sicheren Zufallszahlengenerator. Math.random() ist kein guter Seed.

        Wenn ich Krypto zuverlässig auf dem Server machen kann, dann sollte ich das tun.

        Grüße,
        Mathias

        1. Idealerweise wird das Passwort schon am Client per JavaScript gehasht

          Idealerweise werden alle Daten SSL-verschlüsselt übertragen.

          SSL ist prinzipiell nicht mehr sicher.

          Das Hashen auf dem Client ist eher ein Sicherheitsverlust, weil man von einer clientseitigen Implementierung abhängig ist, die auf tausenden unterschiedlichen Geräten läuft und viel einfacher angreifbar ist.

          Die meisten verbreiteten und gebräuchlichen Streuwert-Algorithmen sind Quelloffen, das ist bei kryptologischen Funktionen ein essentielles Sicherheitsmerkmal - ob das jetzt MD5 oder Blowfish ist, spielt keine Rolle.

          In JavaScript habe ich nicht browserübergreifend Zugriff auf einen brauchbaren Seed für einen kryptographisch sicheren Zufallszahlengenerator. Math.random() ist kein guter Seed.

          Das ist in der Tat ein Angriffspunkt, ebenso ist ein möglicher Angriffspunkt ein infizierter Rechner, der den clientseitigen Hash-Algorithmus ersetzt und somit absichtlich ein bekanntes Passwort in die DB schreiben lässt.

          Wenn ich Krypto zuverlässig auf dem Server machen kann, dann sollte ich das tun.

          Ja, da stimme ich dir zu - bei _neu schreiben_ eines Passworts übernimmt das der Server, bei jedem Login kann der Hash aber durchaus vom Client erzeugt werden - da dies durchaus die Sicherheit erhöht, da das Passwort auf dem Übertragungsweg nicht verloren gehen kann.

          1. Hallo,

            Idealerweise werden alle Daten SSL-verschlüsselt übertragen.

            SSL ist prinzipiell nicht mehr sicher.

            Was willst du damit sagen? Dass SSL nunmehr sinnlos ist?

            Ich habe ja den Eindruck, die kürzlichen »Leaks« haben hauptsächlich Fear, Uncertainty & Doubt über IT-Security verbreitet.

            Das Hashen auf dem Client ist eher ein Sicherheitsverlust, weil man von einer clientseitigen Implementierung abhängig ist, die auf tausenden unterschiedlichen Geräten läuft und viel einfacher angreifbar ist.

            Die meisten verbreiteten und gebräuchlichen Streuwert-Algorithmen sind Quelloffen, das ist bei kryptologischen Funktionen ein essentielles Sicherheitsmerkmal - ob das jetzt MD5 oder Blowfish ist, spielt keine Rolle.

            Das ist korrekt, ich sehe aber nicht, inwiefern das auf meine Aussage eingeht. Der Browser ist keine sichere Umgebung für Kryptographie im Vergleich zum Server, bei dem Hard- und Software gegeben sind.

            bei _neu schreiben_ eines Passworts übernimmt das der Server, bei jedem Login kann der Hash aber durchaus vom Client erzeugt werden - da dies durchaus die Sicherheit erhöht, da das Passwort auf dem Übertragungsweg nicht verloren gehen kann.

            Mir scheint, du wirfst einiges durcheinander. Das Hashing mag vielleicht das Passwort während der Übertragung schützen, wenn ich davon ausgehe, dass die SSL-Verschlüsselung kompromittiert wurde. Es schützt z.B. nicht die Session bzw. den Account. Liest der Angreifer den Hash mit, so kann er sich damit beliebig oft authentifizieren. Es muss sogar erst der Salt zum Client übertragen werden, damit der Client denselben Hash produzieren und der Server beide Hashes vergleichen kann.

            Mathias

            1. Idealerweise werden alle Daten SSL-verschlüsselt übertragen.

              SSL ist prinzipiell nicht mehr sicher.

              Was willst du damit sagen? Dass SSL nunmehr sinnlos ist?

              Nein, selbstverständlich - es ist eine zusätzliche Hürde, aber es kam so rüber als würdest du sagen "Nimm SSL, dann brauchst du dich um den rest nicht mehr scheren" :)

              Ich habe ja den Eindruck, die kürzlichen »Leaks« haben hauptsächlich Fear, Uncertainty & Doubt über IT-Security verbreitet.

              Nein, ich spielte nicht auf die kürzlichen NSA-"Leaks" ab - da gehts ja schon seit ein paar Jahren rund - z.B. vor 2 Jahren die Geschichte mit dem ehrlichen Achmed: http://www.heise.de/security/meldung/Der-ehrliche-Achmed-bittet-um-Vertrauen-1231083.html (wobei hier nicht SSL zwingend schuld ist).

              Auf was ich angespielt habe sind Man-in-the-Middle-Angriffe über öffentliche WLAN-Verbindungen, die seit Jahren bekannt sind - es reicht hier einfach gesagt sich dazwischenzuhängen und den Handshake mitzuschneiden und schon kann man schaun, was hier so passiert. Eine recht verbreitete, fertige Lösung ist hier sslstrip von Moxie Marlinspike:
              http://www.thoughtcrime.org/software/sslstrip/

              Mir scheint, du wirfst einiges durcheinander.

              Ich habs nur kurz und sehr allgemein formuliert.

              Das Hashing mag vielleicht das Passwort während der Übertragung schützen, wenn ich davon ausgehe, dass die SSL-Verschlüsselung kompromittiert wurde. Es schützt z.B. nicht die Session bzw. den Account. Liest der Angreifer den Hash mit, so kann er sich damit beliebig oft authentifizieren. Es muss sogar erst der Salt zum Client übertragen werden, damit der Client denselben Hash produzieren und der Server beide Hashes vergleichen kann.

              Selbstverständlich - wenn nur noch der komplette crypt-String (mit Algorithmus, Salt und Hash) gemeinsam übergeben wird, kann man gleich das Klartextpasswort übergeben - das macht dann nicht mehr viel Unterschied. Da muss zwischenzeitlich etwas Ping-Pong stattfinden.

              Wenn es wirklich um Sicherheit geht kommt man mit einem "statischen Passwort" ohne hin nicht weit, üblich sind hier dann 2-Faktor-Systeme wo z.B. bei jedem Login ein Bestätigungs-SMS mit einem zusätzlichen Einmal-Passwort geschickt wird, welches nur in einem begrenzen Zeitfenster gültig oder aber man verwendet Token-Liste, die jeweils nur 1x verwendet werden kann (bzw. man hat einen Token-Generator wie z.B. SecurID).

              1. Moin!

                Auf was ich angespielt habe sind Man-in-the-Middle-Angriffe über öffentliche WLAN-Verbindungen, die seit Jahren bekannt sind - es reicht hier einfach gesagt sich dazwischenzuhängen und den Handshake mitzuschneiden und schon kann man schaun, was hier so passiert. Eine recht verbreitete, fertige Lösung ist hier sslstrip von Moxie Marlinspike:
                http://www.thoughtcrime.org/software/sslstrip/

                Das Tool greift nicht SSL an. Es verhindert, dass der Client HTTPS-Links in Webseiten sieht, und stattdessen nutzt der dann die mitlesbare HTTP-Variante, sollte er ihnen folgen.

                Verschlüsselung, die der Client direkt benutzt, wird dadurch also nicht betroffen. Und auch das Vortäuschen von SSL-Zertifikaten ist damit nicht möglich.

                Mir scheint, du wirfst einiges durcheinander.

                Ich habs nur kurz und sehr allgemein formuliert.

                Und falsch.

                SSL ist nach wie vor sicher. Die Verschlüsselung an sich wurde nicht geknackt.

                Was problematisch ist, ist die unabdingbare Infrastruktur:

                • der implizite Vertrauensvorschuss gegenüber allen im Browser vorinstallierten CA-Zertifikaten
                • das Browserverhalten bei Veränderung des Zertifikats eines zuvor schon besuchten Servers
                • die Angreifbarkeit des Browser-UI, die unerfahrene Benutzer über die tatsächliche Unsicherheit täuschen könnte
                • und sicherlich noch eine ganze Menge mehr

                Deine pauschale Aussage "SSL ist nicht mehr sicher" ist falsch.

                Das Hashing mag vielleicht das Passwort während der Übertragung schützen, wenn ich davon ausgehe, dass die SSL-Verschlüsselung kompromittiert wurde. Es schützt z.B. nicht die Session bzw. den Account. Liest der Angreifer den Hash mit, so kann er sich damit beliebig oft authentifizieren. Es muss sogar erst der Salt zum Client übertragen werden, damit der Client denselben Hash produzieren und der Server beide Hashes vergleichen kann.

                Selbstverständlich - wenn nur noch der komplette crypt-String (mit Algorithmus, Salt und Hash) gemeinsam übergeben wird, kann man gleich das Klartextpasswort übergeben - das macht dann nicht mehr viel Unterschied. Da muss zwischenzeitlich etwas Ping-Pong stattfinden.

                Es bringt nichts, clientseitig zu hashen. Zumal man, weil es für sowas nichts "out of the box" gibt, ja wieder selbst was stricken müsste.

                Außerdem steht der Aufwand in keinem Verhältnis. Wenn das, was man hinter dem Passwort versteckt, unverschlüsselt übertragen wird, braucht man sich kein komplexes Login-Hashing ausdenken. Wenn es hingegen Verschlüsselung gibt, braucht man sich kein komplexes Login-Hashing ausdenken.

                Wenn es wirklich um Sicherheit geht kommt man mit einem "statischen Passwort" ohne hin nicht weit, üblich sind hier dann 2-Faktor-Systeme wo z.B. bei jedem Login ein Bestätigungs-SMS mit einem zusätzlichen Einmal-Passwort geschickt wird, welches nur in einem begrenzen Zeitfenster gültig oder aber man verwendet Token-Liste, die jeweils nur 1x verwendet werden kann (bzw. man hat einen Token-Generator wie z.B. SecurID).

                Das ist aber nur dann implementierenswert, wenn man die Basis-Sicherheit durch SSL herstellt. Und durch all die ganzen weiteren Maßnahmen im Umfeld von SSL, die heutzutage Standard sein sollten. Beispielsweise das Senden von HSTS-Headern, um den Browser beim unverschlüsselten Zugriff darüber zu informieren, dass er grundsätzlich und in der Zukunft immer nur HTTPS benutzen soll.

                Mit HSTS wird das Angreifen mit SSLStrip schon extrem erschwert, würde ich meinen.

                - Sven Rautenberg

                1. Deine pauschale Aussage "SSL ist nicht mehr sicher" ist falsch.

                  Ja, diese Verallgemeinerung ist falsch - da hast du recht. Ich muss mich hier selbst an der Nase fassen und versuchen künftig Pauschalaussagen zu vermeiden.

                  Weil wir grade bei Hashes sind - es wird ja auch immer wieder gesagt, dass man MD5 nicht mehr für Passwörter verwenden soll, weil es unsicher/gebrochen ist. Diese Aussage trifft aber insbesondere für Passwörter nicht zu, da sämtliche bekannten Angriffe auf MD5 an stellen Ansetzen, die mit Passwörtern nicht das geringste zu tun haben. Der tatsächliche Grund ist, dass MD5 zu schnell und zu kurz ist, um damit effektiv kurze Zeichenketten wie Passwörter zu schützen - zudem fehlt ein Mechanismus, dass zwei gleiche Zeichenketten trotzdem unterschiedliche Ergebnisse liefern (aka Salt). Das liegt daran, dass MD5 mit einem völlig anderen Ziel entwickelt wurde. Warum es sich so lange gehalten hat, ist aber auch hier ein Rätsel - genauso wie die Tatsache, dass mit der nackten Hashfunktion gearbeitet wird und nicht mit einer Variablen Funktion wie crypt, die man später ohne Probleme auf andere Algorithmen anpassen ohne die alten Logins irgendwie zu verlieren.

                  Das ist aber nur dann implementierenswert, wenn man die Basis-Sicherheit durch SSL herstellt.

                  Daran scheitert es vielerorts aber - ich hab' schon Shops gesehen, die ein "riesiges" SSL-Logo hinplastern und dann durch die Bank ohne SSL arbeiten und sogar noch Kreditkartendaten inklusive CVC in eine Datenbank speichern.

                  1. Moin!

                    Das ist aber nur dann implementierenswert, wenn man die Basis-Sicherheit durch SSL herstellt.

                    Daran scheitert es vielerorts aber - ich hab' schon Shops gesehen, die ein "riesiges" SSL-Logo hinplastern und dann durch die Bank ohne SSL arbeiten und sogar noch Kreditkartendaten inklusive CVC in eine Datenbank speichern.

                    Die werden dann aber auch kaum clientseitiges Passworthashing einbauen... :)

                    - Sven Rautenberg

                    1. Daran scheitert es vielerorts aber - ich hab' schon Shops gesehen, die ein "riesiges" SSL-Logo hinplastern und dann durch die Bank ohne SSL arbeiten und sogar noch Kreditkartendaten inklusive CVC in eine Datenbank speichern.

                      Die werden dann aber auch kaum clientseitiges Passworthashing einbauen... :)

                      Nein, die bauen dann garnix ein :) zugegeben, dieser Fall ist ein Extrembeispiel aber ist mir tatsächlich so untergekommen. War ein Neukunde, dem wir dann nahegelegt haben diesen Shop umgehend vom Netz zu nehmen und die Daten sofort zu löschen - wurde dann mit Widerwillen auch gemacht.

                  2. Moin suit,

                    Weil wir grade bei Hashes sind - es wird ja auch immer wieder gesagt, dass man MD5 nicht mehr für Passwörter verwenden soll, weil es unsicher/gebrochen ist. Diese Aussage trifft aber insbesondere für Passwörter nicht zu, da sämtliche bekannten Angriffe auf MD5 an stellen Ansetzen, die mit Passwörtern nicht das geringste zu tun haben.

                    Naja, jain. Es ist richtig, dass es bisher keine verwertbaren Angriffe auf MD5 _bekannt_ sind, um Passwörter zu knacken. Es sind aber strukturelle Schwächen in MD5 bekannt. Und damit sollte der Algorithmus gemieden werden.

                    Der tatsächliche Grund ist, dass MD5 zu schnell und zu kurz ist, um damit effektiv kurze Zeichenketten wie Passwörter zu schützen

                    Das gilt für alle Hashing-Algorithmen.

                    zudem fehlt ein Mechanismus, dass zwei gleiche Zeichenketten trotzdem unterschiedliche Ergebnisse liefern (aka Salt).

                    Nein, das ist nicht richtig. PHPs md5() sieht vielleicht keinen Salt vor, aber es zwingt dich auch keiner, diese Funktion zu nutzen. Nutze halt crypt (http://php.net/manual/en/function.crypt.php) mit entsprechendem Salt. Oder salte von Hand.

                    Ein Hashing-Algorithmus muss per se kein Salting unterstützen, das gängige Vorgehen ist das Einstreuen des Salts an einer Stelle des Klartexts, meistens vorne weg. Wenn du z. B. 12345678 hashen wolltest, mit salt, dann würdest du nicht md5('12345678') aufrufen, sondern md5('$meinunglaublichersalt$12345678'). So funktioniert salting.

                    Nichts desto trotz hast du natürlich recht, dass man md5() nicht verwenden sollte, um Passwörter zu hashen.

                    LG,
                     CK

                    1. Naja, jain. Es ist richtig, dass es bisher keine verwertbaren Angriffe auf MD5 _bekannt_ sind, um Passwörter zu knacken. Es sind aber strukturelle Schwächen in MD5 bekannt. Und damit sollte der Algorithmus gemieden werden.

                      Die Schwächen sind aber für kurze Zeichenketten wie Passwörter völlig nebensächlich, da man hier mit Brute-Force wesentlich schneller zum Ziel kommt als mit einem Pre-Image-Angriff, der dann eine Zeichenkette liefert die ziemlich sicher nicht das gesuchte Passwort ist und noch dazu womöglich ewig lang. Grade bei einer vergleichsweise kurzen Zeichenkette ist ist eine Kollision mit einer anderen kurzen Zeichenkette sogut wie ausgeschlossen - wenn man also durch ausprobieren eine weitere kurze Zeichenkette findet, die denselben Hash produziert, ist das mit fast 100%iger Sicherheit das gesuchte Passwort.

                      Der tatsächliche Grund ist, dass MD5 zu schnell und zu kurz ist, um damit effektiv kurze Zeichenketten wie Passwörter zu schützen

                      Das gilt für alle Hashing-Algorithmen.

                      bcrypt erfüllt diese Kriterien (ja, im Grunde ist es kein blanker Hashing-Algorithmus, das ist Blowfish) aber das Gesamtpaket erfüllt diese Kriterien.

                      Nein, das ist nicht richtig. PHPs md5() sieht vielleicht keinen Salt vor, aber es zwingt dich auch keiner, diese Funktion zu nutzen. Nutze halt crypt (http://php.net/manual/en/function.crypt.php) mit entsprechendem Salt. Oder salte von Hand.

                      Es ging mir um die blanke Verwendung von MD5 die vielerorts gang und gäbe ist - in meinem ursprüngliche Beitrag steht ja bereits, dass es mir ein rätsel ist, warum man nicht mit crypt arbeitet.

                      Ein Hashing-Algorithmus muss per se kein Salting unterstützen, das gängige Vorgehen ist das Einstreuen des Salts an einer Stelle des Klartexts, meistens vorne weg. Wenn du z. B. 12345678 hashen wolltest, mit salt, dann würdest du nicht md5('12345678') aufrufen, sondern md5('$meinunglaublichersalt$12345678'). So funktioniert salting.

                      Der Salt allein macht die Sache aber nicht signfikant sicherer - er verhindert nur das massenhafte "Entschlüsseln" von Passwörtern unter Zuhilfenahme vorgenerierte Listen oder Rainbow-Tables. MD5 ist einfach zu schnell dafür und kann auf modernen GPUs in jeder Sekunde Millardenfach erzeugt werden - selbst wenn man das ganze dann durch 1000 Iterationen schickt, wie das Apache-MD5 macht, wird es dadurch nur unwesentlich sicherer.

                      Darum gibt es ja Algorithmen wie bcrypt die mit dem Ziel in die Welt gesetzt wurden absichtlich extrem langsam zu sein, damit man sie eben nicht per Brute-Force schnell mal durchprobieren kann.

                      1. Moin suit,

                        Naja, jain. Es ist richtig, dass es bisher keine verwertbaren Angriffe auf MD5 _bekannt_ sind, um Passwörter zu knacken. Es sind aber strukturelle Schwächen in MD5 bekannt. Und damit sollte der Algorithmus gemieden werden.

                        Die Schwächen sind aber für kurze Zeichenketten wie Passwörter völlig nebensächlich, […]

                        Das ist doch egal. Wenn eine Schwäche in einem Algorithmus nachgewiesen wurde, gilt er als (kryptographisch) unsicher und sollte gemieden werden. Unwichtig, ob die Schwäche für einen selbst relevant ist oder nicht.

                        Ein Hashing-Algorithmus muss per se kein Salting unterstützen, das gängige Vorgehen ist das Einstreuen des Salts an einer Stelle des Klartexts, meistens vorne weg. Wenn du z. B. 12345678 hashen wolltest, mit salt, dann würdest du nicht md5('12345678') aufrufen, sondern md5('$meinunglaublichersalt$12345678'). So funktioniert salting.

                        Der Salt allein macht die Sache aber nicht signfikant sicherer […]

                        Das habe ich auch nicht behauptet :) Mir sind die Probleme und Schwächen bei der Verwendung von Hashing-Algorithmen zur Speicherung von Passwörtern durchaus bewusst. Es ging mir um deine Aussage, dass MD5 über kein Salting verfüge.

                        LG,
                         CK

                        1. Es ging mir um deine Aussage, dass MD5 über kein Salting verfüge.

                          MD5 verfügt über keinen Integrierten Salting-Mechanismus - crypt lasse ich hier nicht zählen, ist kein blankes MD5 :D

            2. Liest der Angreifer den Hash mit, so kann er sich damit beliebig oft authentifizieren. Es muss sogar erst der Salt zum Client übertragen werden, damit der Client denselben Hash produzieren und der Server beide Hashes vergleichen kann.

              Das unterschreib ich voll mit.

              Wenn SSL unsicher ist, dann ist es kein Stück besser, einen Hash per JS zu erzeugen und den im Klartext zu übertragen - denn dem Angreifer ist es schlicht egal, ober das per tcpdump mitgeschnittene Passwort oder dessen (halt auch per tcpdump mitgeschnittenen) Hash für die Authentifizierung überträgt.

              Solange es nichts besseres als ssl/https für eine verschlüsselte Übertragung hat sollte man das auch nutzen.

              Die browserseitig verwendete crypto-js nutzt in meinen Augen also nicht wirklich viel, für Authentifizierungen ist sie sogar nahezu unbrauchbar.

              Brauchbar für Authentifizierungen wäre sie allenfalls, wenn der Server z.B. einen zufälligen Key für jede zu authentifizierende Sitzung sendet, der Benutzer diesen in JS mit einem beiden(!) Seiten bekannten(!) Passwort verschlüsselt...

              var encrypted = CryptoJS.TripleDES.encrypt("zufälliger Key für Sitzung", "Passwort");

              der Server dann wieder - mit dem bekanntem Passwort - entschlüsselt und den zuvor erzeugten Key ("zufälliger Key für Sitzung") vergleicht.

              Aber auch hier müsste das Passwort auf einem sicheren Weg übertragen werden. Das dürfte bei Webanwendungen ein Schwachpunkt sein - es sei denn, es ist nicht zu teuer, z.B. dem Anwender das Passwort per Bote zu senden (oder so von diesem zu empfangen).

              Natürlich könnte der Server mit einem Passwort (oder shared key) auch Daten verschlüsseln, die dann clientseitig entschlüsselt werden. Aber auch hier müsste das Passwort beiden Seiten bekannt sein. Für die Übertragung gilt das oben gesagte.

              Da wäre eine asynchrone Verschlüsselung mit privaten und öffentlichen Schlüsseln aber deutlich besser... weil die privaten Schlüssel sogar öffentlich bekannt sein können ohne die Sicherheit zu gefährden. Dann kann man die Daten aber auch gleich mit gpg oder pgp ver- oder entschlüsseln.

              Jörg Reinholz

              1. Wenn SSL unsicher ist, dann ist es kein Stück besser, einen Hash per JS zu erzeugen und den im Klartext zu übertragen - denn dem Angreifer ist es schlicht egal, ober das per tcpdump mitgeschnittene Passwort oder dessen (halt auch per tcpdump mitgeschnittenen) Hash für die Authentifizierung überträgt.

                Zumindest wird aber das Klartextpasswort geschützt - das spezifische Login natürlich nicht. Es soll ja Menschen geben, die bei jedem Dienst dasselbe Passwort verwenden, da kommt man dann mit dem Hash nicht so schnell ans Ziel als mit dem Klartext-Passwort.

        2. Tach!

          Das Hashen auf dem Client ist eher ein Sicherheitsverlust, weil man von einer clientseitigen Implementierung abhängig ist, die auf tausenden unterschiedlichen Geräten läuft und viel einfacher angreifbar ist. In JavaScript habe ich nicht browserübergreifend Zugriff auf einen brauchbaren Seed für einen kryptographisch sicheren Zufallszahlengenerator.

          Braucht man für das Hashen Zufall? Ich dachte, das sei eine nachvollziehbare Berechnung.

          dedlfix.

          1. Hallo,

            der Salt sollte zufällig sein. Die von suit verlinkte JavaScript-Implementierung von Blowfish verwendet dazu isaac.js, welches mit Math.random() geseeded wird.

            Klar, wenn ich den Salt initial auf dem Server erzeuge und vor dem Logins zum Client übertrage, habe ich das Problem nicht – aber damit wird der Salt, der normalerweise nur in der Datenbank steht, anstelle des Passworts ständig per HTTP herumgeschickt.

            Mathias

      3. hi again,

        Und dann blos nicht mit MD5 sondern gleich ordentlich, mit bcrypt:
        http://code.google.com/p/javascript-bcrypt/

        Es gibt immer Gründe für Entscheidungen. Z.B. in einer Entscheidung, welcher Algorithmus zum Einsatz kommen soll. Neben der Hacksicherheit (Brutforce) gibt es weitere Aspekte, die eher praktischer Natur sind.

        Vor einiger Zeit habe ich dieses Thema auch mal aufgearbeitet, hier der Artikel. Da gehts nicht um so Fragen, ob ein paar Bytes mehr oder weniger im Hauptspeicher rumliegen sondern um die Sache an sich.

        Viel Spaß damit,
        [Name leider schon anderweitig vergeben]

  5. Hallo,

    Mich ärgert sowas jedes mal Maßlos, wenn jemand mit derart schlechter arbeit Geld verdient und ich mir auf der anderen Seite immer wieder anhören muss, dass das was ich mache auch andere können, nur billiger. Oder dass in "Fachzeitschrift X" ein Artikel (wie z.B. dieser) zu finden ist wo steht, wie leicht das alles geht und man nicht immer die "Königslösung" anstreben solle. Ist denn heutzutage ordentliche Arbeit so aus der Mode gekommen?

    Full ACK. Wir sind leider alle in einer Branche unterwegs, in der Qualität nicht auf den ersten Blick ersichtlich ist. Die wenigsten Kunden machen eine QA, die den Namen wirklich verdient, oder gar Code-Reviews.
    Eine völlig grottige Web-Anwendung, die offen wie ein Scheunentor ist, kann jahrelang stabil laufen, ohne dass irgend jemand bemerkt, was für ein Schrott dahintersteckt.
    Sie kann aber auch bei der ersten Skript-Kiddie-Attacke oder dem ersten Traffic-Ansturm auseinander fallen. Und wenn dann das Kind in den Brunnen gefallen ist, lernt man nicht draus, sondern lässt natürlich wieder den Honk, der den Mist ursprünglich verbrochen hat, das ganze fixen. Denn jeder kompetente, vernünftige Entwickler wird einem sagen, dass das alles Müll ist und von Grund auf neu gebaut werden muss, wenn es wirklich stabil und robust sein soll. Und neu bauen will man nicht...man hat ja schliesslich schon eine Lösung, die nur noch etwas "optimiert" werden muss...und man brauht ja auch nicht 100%tige Stabilität, 80% reicht ja vielleicht auch...

    Kunden wieder und wieder und immer wieder vorzurechnen, dass sie mit einem Billig-Produkt langfristig teurer kommen, ist ein unheimlich labgwieriger und mühsamer Prozess, in dessen Verlauf man droht, seinen Verstand im Angesicht völliger Ignnoranz und Beratungsresistenz zu verlieren.

    -> Ich verstehe Deinen Ärger nur zu gut.

  6. Om nah hoo pez nyeetz, suit!

    Vielleicht lässt sich http://wiki.selfhtml.org/wiki/Technische_Ergänzungen/Loginsystem noch um die Datenbank-Variante ergänzen. Dann hätte man etwas, was man mit "So gehts richtig" zeigen könnte und dem Verlag anbieten kann.

    Obwohl der Artikel inzwischen CC-BY ist, sollte man in dem Fall auch den ursprünglichen Autor darüber informieren und nennen.

    Matthias

    --
    Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Box und Boxer.

    1. Vielleicht lässt sich http://wiki.selfhtml.org/wiki/Technische_Ergänzungen/Loginsystem noch um die Datenbank-Variante ergänzen. Dann hätte man etwas, was man mit "So gehts richtig" zeigen könnte und dem Verlag anbieten kann.

      Gute Idee - mal sehen ob' ich sowas auf die schnelle hinbekomme und am Wochenende Zeit dafür finde.

      Obwohl der Artikel inzwischen CC-BY ist, sollte man in dem Fall auch den ursprünglichen Autor darüber informieren und nennen.

      Wenn der Artikel umgeschrieben wird, auf jeden Fall - das ist zwar aufgrund der Lizenz wie du sagst nicht notwendig, aber anständig ist es auf jeden Fall. Die Namensnennung ist aber aufgrund der Lizenz erforderlich.

  7. Dann werden im Script variablen herumkopiert $benutzer = $_POST['benutzer'].

    Ich bin ein entschiedener Verfechter der Idee, die im Programm benötigten Parameter an zentraler Stelle (bei mir vorne im Code) zu bennen und nicht - eher per Zufall - verstreut im Code zu finden.

    Ich übernehme die erwarteten Parameter in ein array und greife dann nur auf das Array zu. So kann kein Parameter vergessen werden.

    Ausserdem mache ich nach dem "herumkopieren" eine Prüfung, sodass ich nicht mit fragwürdigen Rohdaten, sondern mit sicheren Werten weiterarbeiten kann oder - per Affenformular - Fehler anzeige.

    Der Autor des Artikels gibt übrigens an, schon "zahlreiche Fachbücher und Beiträge in Computer-Fachzeitschriften" geschrieben zu haben

    Naja, schreiben kann man viel. Wieviel hat er denn verkauft? Und wenn ich aus dem Englischen ein PHP- oder CSS-Statement übersetze und nett aufbereite, könnte man das als "Fachartikel" doch gelten lassen, oder?

    Ist denn heutzutage ordentliche Arbeit so aus der Mode gekommen?

    Ja, logo. Schau dir doch eine X-beliebige Stadt an. Findest du mehr Fachgeschäfte oder mehr Billig-Märkte? Wer in Fachgeschäften kauft, wird doch in auflagenstarker Werbung als "blöd" hingestellt.

    Es gibt immer eine Idee, bei einem Produkt irgendwas wegzulassen oder durch Schrott-Material zu ersetzen. Einzige Bedingung: Vor dem Verlassen des Ladens sollte es nicht auseinanderfallen. Deshalb wird so viel in Kunststoff eingeschweisst ;-)

    Linuchs

    1. Dann werden im Script variablen herumkopiert $benutzer = $_POST['benutzer'].

      Ich bin ein entschiedener Verfechter der Idee, die im Programm benötigten Parameter an zentraler Stelle (bei mir vorne im Code) zu bennen und nicht - eher per Zufall - verstreut im Code zu finden.

      Dann sollte man das aber in ein zentrals Objekt/Array packen, wo man dann alle benötigten Werte wieder schnell findet und auch auf einen Rutsch an jeder Stelle als Debugausrabe rauswerfen kann.

      Ich übernehme die erwarteten Parameter in ein array und greife dann nur auf das Array zu. So kann kein Parameter vergessen werden.

      Aber genau das wird ja in dem Artikel gemacht - alles in einzelne variablen Zerpflücken die vorher gesammelt in $_POST verfügbar waren ;)

      Ausserdem mache ich nach dem "herumkopieren" eine Prüfung, sodass ich nicht mit fragwürdigen Rohdaten, sondern mit sicheren Werten weiterarbeiten kann oder - per Affenformular - Fehler anzeige.

      Das verlagert die Plausibilitätsprüfung an eine Zentrale stelle und man kann im Fehlerfall schon früh die Verarbeitung abbrechen und muss nicht alles druchwerken, auch das ist vernünftig.

      Naja, schreiben kann man viel. Wieviel hat er denn verkauft? Und wenn ich aus dem Englischen ein PHP- oder CSS-Statement übersetze und nett aufbereite, könnte man das als "Fachartikel" doch gelten lassen, oder?

      Wenn man nach seinem Namen bei einschlägigen Onlinebuchhändlern sucht, findet man eine ganze Latte an Büchern zu allen möglichen Themenbereichen rund ums Thema Programmieren.

      1. Das verlagert die Plausibilitätsprüfung an eine Zentrale stelle und man kann im Fehlerfall schon früh die Verarbeitung abbrechen und muss nicht alles druchwerken, auch das ist vernünftig.

        Aber bitte nicht gleich nach dem ersten Fehler abbrechen. Ich hasse diese Formulare, die einen einzigen Fehler benennen und beim nächsten Durchgang den nächsten. Und jedesmal geht mein mühsam eingetipptes (je komplizierter, desto sicherer) Passwort verloren.

        Die schlimmsten Anwendungen sind die mit den Chaptas. Die erwische ich fast nie richtig. Bis mir dann einfällt: Ach ja, Cookies zulassen. Fehlende Cookies sollte eine Prüfroutine bemerken.

        Linuchs

        1. Aber bitte nicht gleich nach dem ersten Fehler abbrechen. Ich hasse diese Formulare, die einen einzigen Fehler benennen und beim nächsten Durchgang den nächsten. Und jedesmal geht mein mühsam eingetipptes (je komplizierter, desto sicherer) Passwort verloren.

          Na sicher kann die Prüfung alle eingaben prüfen und alle protentiellen Fehler auflisten :)

          1. Om nah hoo pez nyeetz, suit!

            Aber bitte nicht gleich nach dem ersten Fehler abbrechen. Ich hasse diese Formulare, die einen einzigen Fehler benennen und beim nächsten Durchgang den nächsten. Und jedesmal geht mein mühsam eingetipptes (je komplizierter, desto sicherer) Passwort verloren.

            Na sicher kann die Prüfung alle eingaben prüfen und alle protentiellen Fehler auflisten :)

            Da meint ihr beide dasselbe.

            Matthias

            --
            Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Integral und Integralhelm.

    2. Tach!

      Dann werden im Script variablen herumkopiert $benutzer = $_POST['benutzer'].
      Ich bin ein entschiedener Verfechter der Idee, die im Programm benötigten Parameter an zentraler Stelle (bei mir vorne im Code) zu bennen und nicht - eher per Zufall - verstreut im Code zu finden.

      Benennen ist ja schön und gut, aber muss das mit unnötigem Code erfolgen? Reicht da nicht auch ein Kommentar? Wenn (dein) Code unübersichtlich wird und man den Zufall braucht, um Dinge zu finden, dann ist die Codestruktur vermutlich verbesserungswürdig.

      Ausserdem mache ich nach dem "herumkopieren" eine Prüfung, sodass ich nicht mit fragwürdigen Rohdaten, sondern mit sicheren Werten weiterarbeiten kann oder - per Affenformular - Fehler anzeige.

      Die Prüfung muss aber vor dem Umkopieren erfolgen, zumindest eine nach dem Vorhandensein. Wenn das nicht der Fall ist, wirft PHP sonst eine Notice - wenn man das error_reporting auf E_ALL stehen hat. Und das will man (beim Entwickeln), weil solche Zugriffe auf nicht vorhandene Dinge oftmals auch einen Fehler im Code anzeigen (zum Beispiel Tippfehler). Wenn du nun solche Umkopierungen ohne Vorhandensein-Prüfung machst, handelst du dir nur unnötige Meldungen ein. Verteilst du die Prüfungen an mehrere Stellen ("oben" zum Umkopieren die auf Vorhandensein, "unten" die fachliche Inhaltsprüfung), dann fördert das nicht gerade die Übersichtlichkeit.

      dedlfix.

  8. Hallo,

    ich finde den Artikel symptomatisch für eine gewisse PHP-Programmierung. Es wird suggeriert, dass ich mit ein paar Scripten, in die ich Low-Level-Code hineinschreibe, etwas gewinnen könnte. Gerade Themen wie Nutzerverwaltung und Zugangsschutz kann man sich nicht mal eben erarbeiten.

    In ein paar Tagen kann ich vorhandene sichere Bibliotheken einbinden. In ein paar Wochen könnte ich mir die nötigen Grundlagen aneignen, vielleicht innerhalb eines Monats einen vernünftigen Mechanismus zusammen bekommen. Unter der Annahme, dass ich bereits ein erfahrener Programmierer bin, also mir nicht erst PHP-Programmiergrundlagen aneignen muss. Die meisten Leute lernen beides gleichzeitig, Programmiergrundlagen und Entwicklung von PHP-Webanwendungen.

    Technisch gesehen macht der Artikel alles falsch, was man falsch machen kann. Damit meine ich nicht nur die eklatanten Fehler wie SQL-Injections, XSS und ungesalzene, beschnittene Passwörter. Das Grundproblem ist, dass alles schnell vermantscht wird: HTML-Code mit eingebettetem <?php ?> mit eingebettetem SQL ($mysqli->query("INSERT $quatsch");) und eingebettetem HTML (echo "<p>$quatsch</p>.";) Erst dabei entstehen Probleme wie SQL-Injections und XSS.

    PHP ermöglicht es auf diese Weise schnelle Resultate zu erzielen. Aber PHP versucht seit 10 Jahren, dieser Falle zu entkommen. Eigentlich wurde das schon geschafft: Es gibt gute Bibliotheken und Frameworks, die es einem zumindest erschweren, sich selbst in den Fuß zu schießen. Man muss sich nur eingestehen, dass man diese Komplexität nicht in einem kurzen Artikel vermitteln kann, sondern höchstens in einem dicken Buch. Das ist natürlich schade, aber letztlich hilft es auch Einsteigern mehr als ein Artikel, der schlechte Praktiken vermittelt.

    Grüße,
    Mathias