dedlfix: Kontext-gerechtes Verarbeiten von user-submitted data

Beitrag lesen

Hi!

Gibt es denn soetwas wie einen Leitfaden für die Erstellung eines sicheren Formulares? Die if (isset($array))-Variante habe ich aus dem Netz, woher soll man denn praktisch wissen, ob man mit GET oder POST oder was auch immer arbeiten muss?!

Die isset()-Abfrage hat weniger sicherheitstechnische als vielmehr PHP-technische Gründe. Unter PHP müssen Variablennamen nicht explizit definiert werden. Ein Zugriff auf nicht vorhandene Variablen und auch Array-Elemente wirft üblicherweise nur im Stillen eine Notice-Meldung. Sichtbar machen kann man diese mit einem auf E_ALL gestellten error_reporting (plus display_errors auf on). Da man bei Requsts aus dem großen weiten Internet nie wissen kann, was alles an Daten mitgeliefert wird, fragt man zunächst deren Existenz ab, bevor man fortfährt. Sind die erwarteten Werte nicht vorhanden, so ist das meist ein Zeichen dafür, dass man den Request so nicht abarbeiten will.

Was die Sicherheit anbelangt: Meiner Meinung nach wird zu oft nur ein Teilaspekt bedacht. Man weiß: "All Input is evil." Aber das ist nur die halbe Wahrheit, wenn man sich dabei auf Benutzereingaben beschränkt. Im Grunde genommen kann man das Sicherheitsdenken ziemlich weit herunterfahren, wenn man sich der eigentlichen Erfordernisse der jeweiligen Syntax annimmt. Nahezu jeder Kontext verlangt bestimmte Regeln, was die Notation von Werten anbelangt. Dazu zwei Beispiele: Die Zahl 42 wird in einem Text-Kontext als Folge der Ziffern 4 und 2 notiert. Aber auch 0x2A (hex) oder 052 (oktal) sind gültige (PHP-)Schreibweisen, die die 42 repräsentieren. - In einem String, der mit "" begrenzt wird und ein " als Datenbestandteil hat, ist das " als " zu notieren. Ein " wird also durch ein " repräsentiert. Andere Kontexte haben andere Regeln, wie &lt; für ein < unter HTML. Es ist wichtig, dass man diese kontextspezifischen Notationsregeln für die verschiedenen Werte kennt. Technisch ausgedrückt: Ein Wert muss (häufig) durch sein Literal repräsentiert werden.

Es ist völlig unerheblich, ob ein Wert aus einer Benutzereingabe stammt, selbst notiert ist oder sonstwo entstanden ist beziehungsweise abgefragt wurde. Es müssen in jedem Fall beim Einfügen in einen anderen Kontext die Regeln dieses Kontextes zur Notation des Wertes befolgt werden. Bei einer händischen Notation von Code ist das noch einfach, weil es offensichtlich ist und oft durch einen Syntaxfehler geahndet wird. Hat man jedoch die Werte in einer Variablen stehen, so sieht man ohne eine Kontrollausgabe nicht, dass da Zeichen mit besonderer Bedeutung für bestimmte Kontexte enthalten sind, oder dass irgendwann im Verlaufe des Script-Lebens solche Sonderzeichen (auf welchen Weise auch immer) in diese Variablen gelangen können. Da das Einfügen von Variableninhalten jedoch ein häufiger Anwendungsfall ist, gibt es für die meisten Kontexte spezielle Funktionen, die die Variableninhalte (oder allgemein: des übergebenen Parameters) in die kontextgerechte Notation bringen. htmlspecialchars() für den HTML-Kontext, url_encode() für URLs, mysql(i)_real_escape_string() für Strings in MySQL-Statements.

Lo!