Heim >Backend-Entwicklung >PHP-Tutorial >Dieser seltsame PHP-Code in Frameworks und CMS
Hinweis: Um diesem Beitrag folgen zu können, wird davon ausgegangen, dass Sie über einige Grundkenntnisse in der Programmierung in PHP verfügen.
In diesem Artikel geht es um ein PHP-Code-Snippet, das Sie wahrscheinlich oben in Ihrem bevorzugten CMS oder Framework gesehen haben. Sie haben wahrscheinlich gelesen, dass Sie es aus Sicherheitsgründen immer am Anfang jeder von Ihnen entwickelten PHP-Datei einfügen sollten, allerdings ohne eine 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 in fast allen Frameworks und CMS vorkommt. Im Fall des CMS Joomla besteht die einzige Änderung beispielsweise darin, dass anstelle von ABSPATH JEXEC verwendet wird. Ansonsten bleibt die Logik dieselbe. Dieses CMS ist aus einem früheren System namens Mambo hervorgegangen, das ebenfalls ähnlichen Code verwendete, jedoch mit _VALID_MOS als Konstante. Wenn wir noch weiter zurückgehen, stellen wir fest, dass das erste CMS, das diese Art von Code verwendete, PHP-Nuke war (von einigen als das erste PHP-basierte CMS angesehen).
Der Ausführungsablauf von PHP-Nuke (und den meisten heutigen CMS und Frameworks) bestand aus dem sequenziellen Laden mehrerer Dateien, um auf die Aktion zu reagieren, die der Benutzer oder Besucher auf der Website ausgeführt hatte. Stellen Sie sich zum Beispiel eine Website aus dieser Zeit vor, die bei example.net gehostet wird und auf der dieses CMS installiert ist. Jedes Mal, wenn die Homepage geladen wurde, führte das System eine Folge von Dateien der Reihe nach aus (dies ist nur ein Beispiel, keine tatsächliche Folge): index.php => load_modules.php => module.php. In dieser Kette wurde zuerst index.php geladen, das dann Load_modules.php geladen hat, das wiederum Modules.php geladen hat.
Diese Ausführungskette begann nicht immer mit der ersten Datei (index.php). Tatsächlich könnte jeder einen Teil des Ablaufs umgehen, indem er über die URL direkt auf eine der anderen PHP-Dateien zugreift (z. B. http://example.net/load_modules.php oder http://example.net/modules.php). , was, wie wir sehen werden, in vielen Fällen riskant sein kann.
Wie wurde dieses Problem gelöst? Eine Sicherheitsmaßnahme wurde eingeführt, indem am Anfang jeder Datei ein ähnlicher Code wie dieser hinzugefügt wurde:
<?php if (!eregi("modules.php", $HTTP_SERVER_VARS['PHP_SELF'])) { die ("You can't access this file directly..."); }
Im Wesentlichen prüft dieser Code, der oben in einer Datei mit dem Namen „modules.php“ platziert wird, 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'] module.php nicht enthielt, bedeutete dies, dass der normale Ausführungsfluss aktiv war und dies zuließ Skript zum Fortfahren.
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 in bestimmten Situationen $HTTP_SERVER_VARS['PHP_SELF'] keinen Wert zugewiesen, was seine Wirksamkeit einschränkte.
Was haben die Entwickler also gemacht? Sie haben alle diese Codeschnipsel 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 recht beliebt geworden war, wurde die Existenz einer Konstante überprüft. Diese Konstante wurde in der ersten Datei des Ausführungsablaufs (index.php, home.php oder eine ähnliche Datei) definiert und mit einem Wert versehen. Wenn diese Konstante also in keiner anderen Datei in der Sequenz vorhanden war, bedeutete dies, dass jemand index.php umgangen hatte und versuchte, direkt auf eine andere Datei zuzugreifen.
An diesem Punkt denken Sie vielleicht, dass das Unterbrechen der Ausführungskette äußerst schwerwiegend sein muss. Die Wahrheit ist jedoch, dass es normalerweise keine große Bedrohung darstellt.
Das Risiko kann entstehen, wenn ein PHP-Fehler den Pfad zu unseren Dateien offenlegt. Dies sollte uns nicht beunruhigen, wenn der Server so konfiguriert ist, dass Fehler unterdrückt werden. Selbst wenn Fehler nicht verborgen würden, wären die offengelegten Informationen minimal und würden nur wenige Hinweise auf einen potenziellen Angreifer liefern.
Es kann auch vorkommen, dass jemand auf Dateien zugreift, die HTML-Fragmente (Ansichten) enthalten, und so einen Teil ihres Inhalts preisgibt. In den meisten Fällen sollte dies auch kein Grund zur Sorge sein.
Schließlich könnte ein Entwickler aus Versehen oder mangelnder Erfahrung riskanten Code ohne externe Abhängigkeiten mitten in einen Ausführungsfluss platzieren. Dies ist sehr ungewöhnlich, da Framework- oder CMS-Code für seine Ausführung im Allgemeinen von anderen Klassen, Funktionen oder externen Variablen abhängt. Wenn also versucht wird, ein Skript direkt über die URL auszuführen, treten Fehler auf, da diese Abhängigkeiten nicht gefunden werden und die Ausführung nicht fortgesetzt wird.
Warum also den konstanten Code hinzufügen, wenn es wenig Grund zur Sorge gibt? Die Antwort lautet: „Diese Methode verhindert auch die versehentliche Variableninjektion durch einen Register Globals-Angriff und verhindert so, dass die PHP-Datei davon ausgeht, dass sie sich in der Anwendung befindet, obwohl dies tatsächlich nicht der Fall ist.“
Seit den Anfängen von PHP wurden alle über URLs (GET) oder Formulare (POST) gesendeten Variablen automatisch in globale Variablen umgewandelt. Wenn beispielsweise auf die Datei download.php?filepath=/etc/passwd zugegriffen wurde, könnten Sie in der Datei download.php (und in den davon abhängigen Dateien im Ausführungsablauf) echo $filepath; und es würde /etc/passwd.
ausgebenIn download.php gab es keine Möglichkeit herauszufinden, ob die Variable $filepath von einer vorherigen Datei in der Ausführungskette erstellt wurde oder ob sie über die URL oder POST manipuliert wurde. Dadurch entstanden erhebliche Sicherheitslücken. Schauen wir uns ein Beispiel an, vorausgesetzt, die Datei download.php enthält den folgenden Code:
<?php if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly }
Der Entwickler hatte wahrscheinlich vor, ein Front-Controller-Muster für seinen Code zu verwenden, was bedeutet, dass alle Webanfragen über eine einzige Eintragsdatei (index.php, home.php usw.) laufen würden. Diese Datei würde die Sitzungsinitialisierung übernehmen, allgemeine Variablen laden und schließlich die Anfrage an ein bestimmtes Skript (in diesem Fall download.php) umleiten, um den Dateidownload durchzuführen.
Ein Angreifer könnte jedoch die beabsichtigte Ausführungssequenz umgehen, indem er einfach download.php?filepath=/etc/passwd aufruft, wie bereits erwähnt. PHP würde automatisch die globale Variable $filepath mit dem Wert /etc/passwd erstellen, sodass der Angreifer diese Datei vom System herunterladen kann. Ernsthaftes Problem.
Dies ist nur die Spitze des Eisbergs, da mit minimalem Aufwand noch gefährlichere Angriffe ausgeführt werden könnten. Zum Beispiel in Code wie dem folgenden, den der Programmierer möglicherweise als unvollendetes Skript hinterlassen hat:
<?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 auf seiner eigenen Website https://mysite.net eine Datei My.class.php erstellt hat, die Code enthält, den er ausführen möchte, kann er das anfällige Skript aufrufen, indem er seine Domäne angibt: useless_code.php?base_path=https: //mysite.net, und der Angriff wäre 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 mit einer URL wie „remove_file.inc.php?filename=/etc/hosts“ aufrufen und versuchen, die Datei /etc/hosts vom System zu löschen (sofern das System dies zulässt) oder andere Dateien, die sie haben Sie haben die Berechtigung zum Löschen).
In einem CMS wie WordPress, das intern auch globale Variablen verwendet, waren solche Angriffe verheerend. Dank der konstanten Technik waren diese und andere PHP-Skripte jedoch geschützt. Schauen wir uns das letzte Beispiel an:
<?php if(file_exists($filepath)) { header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.basename($filepath).'"'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($filepath)); flush(); // Flush system output buffer readfile($filepath); exit; }
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 dies eine Konstante ist, denn wenn es eine Variable wäre, könnte ein Angreifer sie logischerweise einfügen.
Inzwischen fragen Sie sich vielleicht, warum PHP diese Funktionalität beibehalten hat, obwohl sie so gefährlich war. Wenn Sie außerdem andere Skriptsprachen (JSP, Ruby usw.) kennen, werden Sie feststellen, dass diese nichts Ähnliches haben (weshalb sie auch nicht die Konstantentechnik verwenden). Denken Sie daran, dass PHP ursprünglich als C-basiertes Template-System erstellt wurde und dieses Verhalten die Entwicklung erleichterte. Die gute Nachricht ist, dass die PHP-Betreuer angesichts der dadurch verursachten Probleme eine php.ini-Direktive namens register_globals eingeführt haben (standardmäßig aktiviert), um die Deaktivierung dieser Funktionalität zu ermöglichen.
Aber da die Probleme weiterhin bestanden, wurde es standardmäßig deaktiviert. Dennoch aktivierten viele Hosts es weiterhin, aus Angst, dass die Projekte ihrer Kunden nicht mehr funktionieren würden, da ein Großteil des damaligen Codes nicht die empfohlenen HTTP_*_VARS-Variablen für den Zugriff auf GET/POST/...-Werte verwendete, sondern stattdessen verwendete globale Variablen.
Als sie schließlich sahen, dass sich die Situation nicht verbesserte, trafen sie eine drastische Entscheidung: diese Funktionalität in PHP 5.4 zu entfernen, um all diese Probleme zu vermeiden. Daher stellen Skripte wie die, die wir gesehen haben (ohne die Verwendung von Konstanten), heute normalerweise kein Risiko mehr dar, abgesehen von einigen harmlosen Warnungen/Hinweisen in bestimmten Fällen.
Heute ist die Konstanttechnik immer noch üblich. Die bedauerliche Realität – und der Grund für diesen Artikel – ist jedoch, dass nur wenige Entwickler den wahren Grund für seine Verwendung verstehen.
Wie bei anderen Best Practices aus der Vergangenheit (wie dem Kopieren von Parametern in lokale Variablen innerhalb von Funktionen, um Probleme mit Referenzen zu vermeiden oder der Verwendung von Unterstrichen in privaten Variablen, um sie zu unterscheiden), wenden viele sie weiterhin an, einfach weil ihnen jemand einmal gesagt hat, dass es sich um eine handelt gute Praxis, ohne zu hinterfragen, ob sie heute noch einen Mehrwert bietet. Die Wahrheit ist, dass diese Technik in den meisten Fällen nicht mehr notwendig ist.
Hier sind einige Gründe, warum diese Praxis an Relevanz verloren hat:
Entfernung von *register globals: Seit PHP 5.4 wurde die automatische Registrierung von GET- und POST-Variablen als Globals in PHP entfernt. Ohne *register globals ist die direkte Ausführung einzelner Skripte harmlos, wodurch der Hauptgrund für diese Technik entfällt.
Besseres Code-Design: Selbst in Versionen vor PHP 5.4 ist moderner Code besser strukturiert, im Allgemeinen in Klassen und Funktionen, was den Zugriff oder die Manipulation über externe Variablen schwieriger macht. Sogar WordPress, das traditionell globale Variablen verwendet, minimiert diese Risiken.
Verwendung von *Front-Controllern: Heutzutage verwenden die meisten Webanwendungen gut gestaltete *Front-Controller, um sicherzustellen, dass Klassen- und Funktionscode nur ausgeführt wird, wenn die Ausführung erfolgt Die Kette beginnt am Haupteinstiegspunkt. Wenn also jemand versucht, Dateien isoliert zu laden, wird die Logik nicht ausgelöst, es sei denn, der Fluss beginnt am richtigen Einstiegspunkt.
Automatisches Laden von Klassen: Mit der weit verbreiteten Verwendung des automatischen Ladens von Klassen in der modernen Entwicklung ist die Verwendung von include oder require erheblich zurückgegangen. Dies verringert die Risiken, die mit diesen Methoden (wie Remote File Inclusion oder Local File Inclusion) bei erfahreneren Entwicklern verbunden sind.
Trennung von öffentlichem und privatem Code: In vielen modernen CMS und Frameworks ist öffentlicher Code (wie Assets) vom privaten Code (Logik) getrennt. Diese Maßnahme ist besonders wertvoll, da sie sicherstellt, dass PHP-Code (unabhängig davon, ob er die Konstantentechnik verwendet oder nicht) nicht offengelegt wird, wenn PHP auf dem Server ausfällt. Obwohl diese Trennung nicht speziell zur Abschwächung von Register-Globals implementiert wurde, trägt sie dazu bei, andere Sicherheitsprobleme zu verhindern.
Weit verbreitete Verwendung benutzerfreundlicher URLs: Heutzutage ist die Konfiguration von Servern für die Verwendung benutzerfreundlicher URLs gängige Praxis, um einen einzigen Einstiegspunkt für die Anwendungslogik sicherzustellen. Dadurch ist es für niemanden nahezu unmöglich, PHP-Dateien isoliert zu laden.
Fehlerunterdrückung in der Produktion: Die meisten modernen CMS und Frameworks deaktivieren die Fehlerausgabe standardmäßig, sodass Angreifer keine Hinweise auf das Innenleben der Anwendung finden, was andere Arten von Angriffen erleichtern könnte.
Auch wenn diese Technik in den meisten Fällen nicht mehr notwendig ist, heißt das nicht, dass sie nie nützlich ist. Als professioneller Entwickler ist es wichtig, jede Situation zu analysieren und zu entscheiden, ob die konstante Technik für den spezifischen Kontext, in dem Sie arbeiten, relevant ist. Diese Art des kritischen Denkens sollte immer angewendet werden, auch bei sogenannten Best Practices.
Wenn Sie immer noch unsicher sind, wann Sie die Konstanttechnik anwenden sollen, können Ihnen diese Empfehlungen helfen:
Wenn Sie Zweifel haben, wenden Sie es bei allem anderen an. In den meisten Fällen ist es nicht schädlich und kann Sie in unerwarteten Situationen schützen, insbesondere wenn Sie gerade erst anfangen. Mit der Zeit und Erfahrung werden Sie in der Lage sein, zu beurteilen, wann Sie diese und andere Techniken effektiver anwenden sollten.
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!