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