Heim  >  Artikel  >  Backend-Entwicklung  >  Dieser seltsame PHP-Code in Frameworks und CMS

Dieser seltsame PHP-Code in Frameworks und CMS

Barbara Streisand
Barbara StreisandOriginal
2024-11-12 07:56:02634Durchsuche

Ese extraño código PHP en frameworks y CMS

Hinweis:Um diesem Beitrag zu folgen, wird davon ausgegangen, dass Sie über minimale Programmierkenntnisse in PHP verfügen.

In diesem Beitrag geht es um ein PHP-Codefragment, das Sie möglicherweise oben in Ihrem bevorzugten CMS oder Framework gesehen haben und von dem Sie wahrscheinlich gelesen haben, dass Sie es aus Sicherheitsgründen immer in den Header aller von Ihnen verwendeten PHP-Dateien einfügen sollten entwickeln, allerdings ohne eine sehr klare Erklärung dafür. Ich beziehe mich auf diesen Code:

<?php

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

Diese Art von Code kommt in WordPress-Dateien sehr häufig vor, obwohl er tatsächlich in fast allen Frameworks und CMS vorkommt. Im Fall des CMS Joomla ändert sich beispielsweise nur, dass statt ABSPATH JEXEC verwendet wird. Ansonsten ist die Logik dieselbe. Dieses CMS ist aus einem anderen CMS namens Mambo hervorgegangen, das ebenfalls ähnlichen Code verwendete, jedoch mit _VALID_MOS als Konstante. Wenn wir noch weiter in der Zeit zurückgehen, werden wir feststellen, dass das erste CMS, das diese Art von Code verwendete, PHP-Nuke war (von einigen als das erste CMS in PHP angesehen).

Der Ausführungsablauf von PHP-Nuke (und den meisten heutigen CMS und Frameworks) bestand aus dem sequentiellen Laden mehrerer Dateien, die zusammen auf die vom Benutzer oder Besucher im Web ausgeführte Aktion reagierten. Stellen Sie sich also eine Website aus dieser Zeit vor, die unter der Domain example.net läuft und auf der dieses CMS installiert ist. Jedes Mal, wenn die Homepage geladen wurde, führte das System eine Folge von Dateien in geordneter Weise aus (in diesem Fall handelt es sich nur um ein Beispiel, nicht um eine echte Folge): index.php => load_modules.php => module.php. Das heißt, in dieser Reihenfolge wurde zuerst index.php geladen, dann wurde dieses Skript Load_modules.php geladen und dieses wiederum Modules.php.

Diese Ausführungskette begann nicht immer mit der ersten Datei (index.php). Tatsächlich könnte jeder einen Teil dieses Ablaufs überspringen, indem er eine der anderen PHP-Dateien direkt über ihre URL aufruft (z. B. http://example.net/load_modules.php oder http://example.net/modules.php). , wie wir sehen werden, könnte in vielen Fällen gefährlich sein.

Wie wurde dieses Problem gelöst? Es wurde eine Sicherheitsmaßnahme eingeführt, bei der am Anfang jeder Datei Codes hinzugefügt wurden, die diesem ähneln:

<?php

if (!eregi("modules.php", $HTTP_SERVER_VARS['PHP_SELF'])) {
    die ("You can't access this file directly...");
}

Im Wesentlichen überprüft dieser Code, der sich im Header einer Datei namens „modules.php“ befindet, um festzustellen, ob auf „modules.php“ direkt über die URL zugegriffen wird. Wenn ja, wurde die Ausführung gestoppt und die Meldung angezeigt: „Sie können nicht direkt auf diese Datei zugreifen …“. Wenn $HTTP_SERVER_VARS['PHP_SELF'] keine module.php enthielt, bedeutete das, dass wir uns im normalen Ausführungsfluss befanden und fortfahren durften.

Dieser Code hatte jedoch einige Einschränkungen. Erstens war der Code für jede Datei, in die er eingefügt wurde, unterschiedlich, was die Komplexität erhöhte. Darüber hinaus hat PHP unter bestimmten Umständen $HTTP_SERVER_VARS['PHP_SELF'] keinen Wert zugewiesen, was seine Wirksamkeit einschränkte.

Was haben die Entwickler also gemacht? Sie haben alle diese Codefragmente durch eine einfachere und effizientere Version ersetzt:

<?php

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

In diesem neuen Code, der in der PHP-Community bereits weit verbreitet war, wurde die Existenz einer Konstante überprüft. Diese Konstante wurde in der ersten Datei des Flows (index.php oder home.php oder eine ähnliche Datei) definiert und einem Wert zugewiesen. Wenn diese Konstante also in einer anderen Datei im Stream nicht vorhanden war, bedeutete dies, dass jemand die Datei index.php übersprungen hatte und versuchte, direkt auf eine andere Datei zuzugreifen.

Gefahren, wenn jemand eine PHP-Datei direkt startet

Sicher denken Sie an diesem Punkt, dass das Durchbrechen der Hinrichtungskette das Schlimmste auf der Welt sein muss. Die Realität ist jedoch, dass es normalerweise keine nennenswerte Gefahr darstellt.

Gefahr kann entstehen, wenn ein PHP-Fehler den Pfad zu unseren Dateien offenlegt. Dies sollte uns nicht beunruhigen, wenn wir eine Fehlerunterdrückung auf dem Server konfiguriert haben, und selbst wenn die Fehler nicht ausgeblendet wären, wären die offengelegten Informationen minimal und würden einem möglichen Angreifer nur wenige Hinweise geben.

Es kann auch vorkommen, dass jemand auf Dateien zugreift, die HTML-Fragmente (aus Ansichten) enthalten, und so einen Teil ihres Inhalts preisgibt. In den meisten Fällen sollte dies auch kein Grund zur Sorge sein.

Schließlich kann es vorkommen, dass ein Entwickler aus Unaufmerksamkeit oder mangelnder Erfahrung mitten in einem Ausführungsfluss gefährlichen Code ohne externe Abhängigkeit einfügt. Dies ist sehr ungewöhnlich, da der Code eines Frameworks oder CMS normalerweise für seine Ausführung auf andere Klassen, Funktionen oder externe Variablen angewiesen ist. Wenn Sie daher versuchen, ein Skript direkt über die URL auszuführen, werden diese Abhängigkeiten nicht gefunden und die Ausführung wird nicht fortgesetzt.

Warum also den konstanten Code hinzufügen, wenn kaum Anlass zur Sorge besteht? Der Grund ist folgender: „Diese Methode verhindert auch eine versehentliche Variableninjektion durch einen Angriff auf register globals und verhindert so, dass die PHP-Datei davon ausgeht, dass sie sich in der Anwendung befindet, obwohl dies in Wirklichkeit nicht der Fall ist.“

Registrieren Sie Globals

Seit den Anfängen von PHP wurden alle über URLs (GET) oder Formulare (POST) gesendeten Variablen automatisch in globale umgewandelt. Das heißt, wenn auf die Datei download.php?filepath=/etc/passwd zugegriffen wurde, könnte in der Datei download.php (und in denen, die im Ausführungsablauf davon abhängen) echo $filepath verwendet werden; und das Ergebnis wäre /etc/passwd.

In download.php gab es keine Möglichkeit festzustellen, ob die Variable $filepath von einer vorherigen Datei im Ausführungsablauf erstellt wurde oder ob jemand sie über die URL oder mit einem POST gefälscht hatte. Dadurch entstanden große Sicherheitslücken. Sehen wir uns das anhand eines Beispiels an, wobei wir davon ausgehen, dass die Datei download.php den folgenden Code enthält:

<?php

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

Der Entwickler hat wahrscheinlich darüber nachgedacht, seinen Code mit einem Front-Controller-Muster zu implementieren, das heißt, alle Webanfragen über eine einzige Eingabedatei (index.php, home.php usw.) laufen zu lassen. Diese Datei wäre für die Initialisierung der Sitzung, das Laden gemeinsamer Variablen und schließlich für die Weiterleitung der Anfrage an ein bestimmtes Skript (in diesem Fall download.php) verantwortlich, um die Datei herunterzuladen.

Ein Angreifer könnte jedoch die geplante Ausführungssequenz umgehen, indem er einfach download.php?filepath=/etc/passwd aufruft, wie bereits erwähnt. Daher würde PHP automatisch die globale Variable $filepath mit dem Wert /etc/passwd erstellen, was es dem Angreifer ermöglicht, diese Datei vom System herunterzuladen. Schwerer Fehler.

Das ist nur die Spitze des Eisbergs, denn mit minimalem Aufwand könnten noch gefährlichere Angriffe durchgeführt werden. Zum Beispiel in Code wie dem folgenden, den der Programmierer als unvollendetes Skript hätte belassen können:

<?php

if (!eregi("modules.php", $HTTP_SERVER_VARS['PHP_SELF'])) {
    die ("You can't access this file directly...");
}

Ein Angreifer könnte mithilfe eines Remote File Inclusion (RFI)-Angriffs beliebigen Code ausführen. Wenn der Angreifer also auf seiner eigenen Website https://mysite.net eine My.class.php-Datei mit einem beliebigen Code erstellt, den er ausführen möchte, könnte er das anfällige Skript aufrufen, indem er ihm seine Domäne übergibt: codigo_inutil.php?base_path= https:// mysite.net, und der Angriff wurde abgeschlossen.

Ein weiteres Beispiel: in einem Skript namens „remove_file.inc.php“ mit dem folgenden Code:

<?php

if (!defined('MODULE_FILE')) {
    die ("You can't access this file directly...");
}

Ein Angreifer könnte diese Datei direkt über eine URL wie „remove_file.inc.php?filename=/etc/hosts“ aufrufen und so versuchen, die Datei /etc/hosts aus dem System zu löschen (sofern das System dies zulässt oder auf andere Weise). Dateien, für die Sie Löschberechtigungen haben).

In einem CMS wie WordPress, das intern auch globale Variablen verwendet, war diese Art von Angriff verheerend. Dank der konstanten Technik waren diese und andere PHP-Skripte jedoch geschützt. Schauen wir uns das letzte Beispiel an:

<?php

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

Wenn nun jemand versuchen würde, auf „remove_file.inc.php?filename=/etc/hosts“ zuzugreifen, würde die Konstante den Zugriff blockieren. Es ist wichtig, dass es sich um eine Konstante handelt, denn wenn es eine Variable wäre, könnte der Angreifer sie natürlich einfügen.

An diesem Punkt fragen Sie sich wahrscheinlich, warum PHP diese Funktionalität beibehalten hat, obwohl sie so gefährlich war. Wenn Sie auch andere Skriptsprachen (JSP, Ruby usw.) kennen, werden Sie feststellen, dass diese nichts Ähnliches haben (weshalb sie auch nicht die Konstantentechnik verwenden). Erinnern wir uns daran, dass PHP als Vorlagensystem in C geboren wurde und dieses Verhalten die Entwicklung erleichterte. Die gute Nachricht ist, dass die PHP-Betreuer angesichts der dadurch verursachten Probleme beschlossen haben, in php.ini eine Direktive namens register_globals einzuführen (standardmäßig aktiviert), um die Deaktivierung dieser Funktionalität zu ermöglichen.

Da die Probleme jedoch weiterhin bestanden, wurde es standardmäßig deaktiviert. Trotzdem aktivierten viele Hosts es weiterhin, aus Angst, dass die Projekte ihrer Kunden nicht mehr funktionieren würden, da ein Großteil des Codes zu diesem Zeitpunkt nicht die empfohlenen HTTP_*_VARS-Variablen verwendete, um auf die GET/POST/...-Werte zuzugreifen, aber eher globale Variablen.

Da sich die Situation schließlich nicht änderte, trafen sie eine drastische Entscheidung: Entfernen Sie diese Funktionalität in PHP 5.4, um all diese Probleme zu vermeiden. Heutzutage stellen Skripte wie die, die wir gesehen haben (ohne die Verwendung von Konstanten), normalerweise keine Gefahr mehr dar, abgesehen von einigen harmlosen Warnungen/Hinweisen in bestimmten Fällen.

heute nutzen

Heute ist die Konstanttechnik immer noch üblich. Was jedoch traurig ist – und der Grund, der zu diesem Beitrag geführt hat – ist, dass nur wenige Entwickler den wahren Grund für seine Verwendung kennen.

Wie bei anderen bewährten Methoden der Vergangenheit (z. B. das Kopieren von Parametern in einer Funktion in lokale Variablen, um Gefahren durch Referenzen im Aufruf zu vermeiden, oder die Verwendung von Unterstrichen in privaten Variablen zur Unterscheidung) wenden viele sie immer noch an, nur weil jemand es einmal getan hat sagte ihnen, dass es sich um eine gute Praxis handele, ohne darüber nachzudenken, ob es in der heutigen Zeit wirklich einen Mehrwert bringt. Die Realität ist, dass diese Technik in den meisten Fällen nicht mehr notwendig ist.

Einige Gründe, warum diese Praxis an Relevanz verloren hat, sind folgende:

  • Verschwinden von *register globals: Seit PHP 5.4 gibt es die Funktionalität, GET- und POST-Variablen als PHP-Globalvariablen zu registrieren, nicht mehr. Wie wir gesehen haben, wird die Ausführung einzelner Skripte ohne *register globals harmlos, wodurch der Hauptgrund für diese Praxis entfällt.

  • Besseres Design im aktuellen Code: Auch in Versionen vor PHP 5.4 ist moderner Code besser gestaltet, in Klassen und Funktionen strukturiert, was den Zugriff oder die Manipulation durch externe Variablen erschwert. Sogar WordPress, das häufig globale Variablen verwendet, minimiert diese Risiken.

  • Verwendung von *Front-Controllern: Heutzutage verwenden die meisten Webanwendungen gut gestaltete *Front-Controller, die dafür sorgen, dass der Code der Klassen und Funktionen funktioniert nur ausgeführt werden, wenn die Ausführungskette am Haupteinstiegspunkt beginnt. Es spielt also keine Rolle, wenn jemand versucht, Dateien isoliert hochzuladen: Die Logik wird nicht aktiviert, wenn der Fluss nicht am richtigen Punkt gestartet wird.

  • Automatisches Laden von Klassen: Da in der aktuellen Entwicklung das automatische Laden von Klassen verwendet wird, wurde die Verwendung von include oder require stark reduziert. Dies bedeutet, dass es, sofern Sie kein unerfahrener Entwickler sind, keine includes oder requires geben sollte, die Risiken bergen könnten (z. B. Remote File Inclusion oder ). Lokale Dateieinbindung).

  • Trennung von öffentlichem und privatem Code: In vielen modernen CMS und Frameworks wird öffentlicher Code (z. B. Assets) vom privaten Code (Programmiercode) getrennt. Diese Maßnahme ist besonders wertvoll, da sie sicherstellt, dass bei einem PHP-Ausfall auf dem Server der Code in den PHP-Dateien (unabhängig davon, ob sie die konstante Technik verwenden oder nicht) nicht offengelegt wird. Obwohl dies nicht speziell zur Abschwächung von Register Globals implementiert wurde, trägt es dazu bei, andere Sicherheitsprobleme zu vermeiden.

  • Erweiterte Verwendung benutzerfreundlicher URLs: Heutzutage ist es üblich, den Server für die Verwendung benutzerfreundlicher URLs zu konfigurieren, was immer einen einzigen Einstiegspunkt für die Programmierung erzwingt. Dadurch ist es für niemanden nahezu unmöglich, PHP-Dateien isoliert hochzuladen.

  • Fehlerausgabe in der Produktion unterdrücken: Die meisten modernen CMS und Frameworks blockieren standardmäßig die Fehlerausgabe, sodass Angreifer keine Hinweise auf die interne Funktionsweise der Anwendung finden können, was andere Arten erleichtern könnte von Angriffen.

Obwohl diese Technik in den meisten Fällen nicht mehr notwendig ist, heißt das nicht, dass sie niemals nützlich ist. Als professioneller Entwickler ist es wichtig, jeden Fall zu analysieren und zu entscheiden, ob die konstante Technik in dem spezifischen Kontext, in dem Sie arbeiten, relevant ist. Dies ist ein Kriterium, das Sie immer anwenden sollten, auch bei den Ihrer Meinung nach guten Praktiken.

Zweifel? Hier sind einige Tipps

Wenn Sie immer noch nicht sicher sind, wann Sie die Konstanttechnik anwenden sollen, können Ihnen diese Empfehlungen als Orientierungshilfe dienen:

  • Verwenden Sie diese Technik immer, wenn Sie glauben, dass Ihr Code auf einer PHP-Version vor 5.4 ausgeführt werden kann.
  • Verwenden Sie es nicht, wenn die Datei nur die Definition einer Klasse enthält.
  • Verwenden Sie es nicht, wenn die Datei nur Funktionen enthält.
  • Nicht verwenden, wenn die Datei nur HTML/CSS enthält, es sei denn, der HTML-Code enthält wertvolle Informationen.
  • Verwenden Sie es nicht, wenn die Datei nur Konstanten enthält.

Wenn Sie Zweifel haben, wenden Sie es bei allem anderen an. In den meisten Fällen sollte es nicht schädlich sein und könnte Sie in unerwarteten Situationen schützen, insbesondere wenn Sie gerade erst anfangen. Mit der Zeit und Erfahrung werden Sie besser einschätzen können, wann Sie diese und andere Techniken anwenden sollten.

Ese extraño código PHP en frameworks y CMS

Lerne weiter...

  • register_globals – MediaWiki
  • PHP: Verwenden von Register Globals – Handbuch
  • Sicherheitslücken bei der Remote-Dateieinbindung [LWN.net]
  • Bugtraq: Schwerwiegende Sicherheitslücke in Mambo Site Server Version 3.0.X

Das obige ist der detaillierte Inhalt vonDieser seltsame PHP-Code in Frameworks und CMS. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn