Ich habe hier eine Reihe von Beiträgen gesehen, in denen empfohlen wird, die $_REQUEST
variabel. Normalerweise tue ich das nicht, aber manchmal ist es praktisch. Was ist daran falsch?
Antworten
Zu viele Anzeigen?Es ist absolut nichts falsch daran, den Input von beiden Seiten zu erhalten. $_GET
y $_POST
in einer kombinierten Weise. Das ist in der Tat das, was Sie fast immer tun wollen:
-
Bei einer einfachen idempotenten Anfrage, die normalerweise per GET übermittelt wird, besteht die Möglichkeit, dass die gewünschte Datenmenge nicht in eine URL passt, so dass sie in der Praxis stattdessen in eine POST-Anfrage umgewandelt werden muss.
-
für eine Anfrage, die eine echte Wirkung hat, müssen Sie überprüfen, ob sie mit der POST-Methode übermittelt wurde. Das geht aber nur, indem man prüft
$_SERVER['REQUEST_METHOD']
ausdrücklich, nicht auf$_POST
für ein GET leer zu sein. Und überhaupt, wenn die MethodePOST
können Sie dennoch einige Abfrageparameter aus der URL entfernen.
Nein, das Problem mit $_REQUEST
hat nichts mit der Verwechslung von GET- und POST-Parametern zu tun. Es geht darum, dass es standardmäßig auch $_COOKIE
. Und Cookies sind überhaupt nicht mit Parametern für die Übermittlung von Formularen vergleichbar: Sie sollten sie fast nie als dasselbe behandeln.
Wenn auf Ihrer Website versehentlich ein Cookie mit demselben Namen wie einer Ihrer Formularparameter gesetzt wird, funktionieren die Formulare, die auf diesen Parameter angewiesen sind, auf mysteriöse Weise nicht mehr richtig, weil die Cookie-Werte die erwarteten Parameter überschreiben. Dies ist sehr einfach, wenn Sie mehrere Anwendungen auf derselben Website haben, und kann sehr schwer zu beheben sein, wenn Sie nur ein paar Benutzer mit alten Cookies haben, die Sie nicht mehr verwenden und die Formulare auf eine Art und Weise beschädigen, die niemand sonst reproduzieren kann.
Sie können dieses Verhalten in das wesentlich sinnvollere GP
(nein C
) Auftrag mit dem anfrage_bestellung Konfiguration in PHP 5.3. Wo dies nicht möglich ist, würde ich persönlich Folgendes vermeiden $_REQUEST
und, wenn ich ein kombiniertes GET+POST-Array benötigte, dieses manuell erstellen.
Ich habe mich durch einige Newsgroup-Beiträge zu folgenden Themen gewühlt PHP-Interna und fand eine interessante Diskussion zu diesem Thema. Im ursprünglichen Thread ging es um etwas anderes, aber eine Bemerkung von Stefan Esser, einem (wenn auch nicht die ), ein Sicherheitsexperte in der PHP-Welt, lenkte die Diskussion auf die Sicherheitsimplikationen der Verwendung von $_REQUEST für ein paar Beiträge.
Unter Stefan Esser über PHP-Interna
$_REQUEST ist eine der größten Designschwächen in PHP. Jede Anwendung, die $_REQUEST verwendet, ist höchstwahrscheinlich anfällig für Delayed Cross Site Request Forgery-Probleme. (Das bedeutet, wenn z.B. ein Cookie namens (age) existiert, wird es immer den GET/POST-Inhalt überschreiben und somit unerwünschte Anfragen durchgeführt werden)
und in einer spätere Antwort auf denselben Thread
Es geht nicht darum, dass jemand GET-, POST- oder COOKIE-Variablen fälschen kann. Es geht um die Tatsache, dass COOKIEs GET- und POST-Daten in REQUEST.
Daher könnte ich Ihren Browser mit einem Cookie infizieren, das z. B. lautet action=logout steht, und von diesem Tag an können Sie die Anwendung nicht mehr benutzen Anwendung nicht mehr benutzen, weil REQUEST[action] für immer logout lautet (bis Sie das Cookie manuell löschen).
Und Sie mit einem COOKIE zu infizieren ist so einfach...
a) Ich könnte eine XSS-Schwachstelle in einer beliebigen Anwendung auf einer Subdomäne nutzen
b) Haben Sie schon einmal versucht, ein Cookie für *.co.uk oder *.co.kr zu setzen, wenn Sie eine eine einzelne Domain besitzen?
c) Andere bereichsübergreifende Wege...Und wenn Sie glauben, dass dies kein Problem ist, dann kann ich Ihnen sagen, dass es eine einfache Möglichkeit gibt, z.B. ein *.co.kr Cookie zu setzen, das dazu führt dazu führt, dass mehrere PHP-Versionen nur weiße Seiten zurückgeben. Stellen Sie sich vor: Nur ein einziger Cookie, der alle PHP-Seiten in *.co.kr löscht
Und durch das Setzen einer illegalen Sitzungs-ID in einem für *.co.kr gültigen Cookie in einer Variable namens +PHPSESSID= illegal Sie können immer noch jedes PHP DOS Anwendung in Korea mit PHP-Sitzungen...
Die Diskussion geht noch ein paar Beiträge weiter und ist interessant zu lesen.
Wie Sie sehen können, ist das Hauptproblem mit $_REQUEST nicht so sehr, dass es Daten von $_GET und $_POST enthält, sondern auch von $_COOKIE. Einige andere Leute auf der Liste schlugen vor, die Reihenfolge zu ändern, in der $_REQUEST gefüllt wird, z.B. es zuerst mit $_COOKIE zu füllen, aber Dies könnte zu zahlreichen anderen potenziellen Problemen führen, z. B. beim Umgang mit Sitzungen .
Sie können $_COOKIES aus dem $_REQUEST global jedoch komplett weglassen, so dass es nicht von einem der anderen Arrays überschrieben wird (tatsächlich können Sie es auf eine beliebige Kombination seiner Standardinhalte beschränken, wie die PHP-Handbuch auf der variable_ordnung ini-Einstellung sagt uns:
variable_order Legt die Reihenfolge der EGPCS (Environment, Get, Post, Cookie, and Server) Variablenanalyse fest. Wenn variables_order z.B. auf "SP" gesetzt ist, wird PHP die Superglobals $_SERVER und $_POST erzeugen, aber nicht $_ENV, $_GET und $_COOKIE. Die Einstellung auf "" bedeutet, dass keine Superglobals gesetzt werden.
Andererseits könnten Sie auch erwägen, $_REQUEST überhaupt nicht zu verwenden, einfach weil Sie in PHP auf Environment, Get, Post, Cookie und Server in ihren eigenen Globals zugreifen können und einen Angriffsvektor weniger haben. Sie müssen diese Daten zwar immer noch bereinigen, aber Sie müssen sich um eine Sache weniger Sorgen machen.
Nun werden Sie sich vielleicht fragen, warum $_REQUEST überhaupt existiert und warum es nicht entfernt wird. Diese Frage wurde auch auf PHP Internals gestellt. Ich zitiere Rasmus Lerdorf über Warum gibt es $_REQUEST? zu PHP-Interna
Je mehr solcher Dinge wir entfernen, desto schwieriger wird es für die Menschen, die schnell auf neuere, schnellere und sicherere PHP-Versionen zu wechseln. Das verursacht weit mehr Frustration für alle als ein paar "hässliche" Legacy Funktionen. Wenn es einen vernünftigen technischen Grund gibt, Leistung oder Sicherheit, dann müssen wir uns das genau ansehen. In diesem Fall ist das sollten wir uns nicht fragen, ob wir $_REQUEST entfernen sollten entfernen sollten, sondern ob wir die Cookie-Daten daraus entfernen sollten. Viele Konfigurationen tun das bereits, einschließlich aller meiner eigenen, und es gibt eine starke gültige Sicherheitsgrund, keine Cookies in $_REQUEST aufzunehmen. Die meisten Leute benutzen $_REQUEST im Sinne von GET oder POST, ohne zu wissen, dass es auch Cookies enthalten kann Cookies enthalten könnte, und als solche könnten Bösewichte möglicherweise einige Cookie-Injection Tricks anwenden und naive Anwendungen zerstören.
Wie auch immer, ich hoffe, das bringt etwas Licht ins Dunkel.
$_REQUEST
wird im Allgemeinen aus demselben Grund als schädlich angesehen, aus dem einfache bis mittelkomplexe Datentransformationen oft im Anwendungscode durchgeführt werden, anstatt in SQL deklariert zu werden: Manche Programmierer sind einfach schlecht.
Wenn man also dazu neigt, die $_REQUEST
überall kann ich mit GET alles tun, was ich auch mit POST tun könnte, was bedeutet, dass ich die <img>
Tags auf meiner (bösartigen) Website, die dazu führen, dass Benutzer, die in Ihrem E-Commerce-Modul angemeldet sind, unbemerkt Produkte kaufen, oder ich kann sie dazu bringen, auf Links zu klicken, die zu gefährlichen Aktionen oder zur Offenlegung sensibler Informationen (wahrscheinlich für mich) führen.
Dies liegt jedoch daran, dass ein unerfahrener oder zumindest unerfahrener PHP-Programmierer einfache Fehler macht. Zunächst einmal sollten Sie wissen, wann welcher Datentyp angemessen ist. Ich habe zum Beispiel einen Webdienst, der Antworten in URLEncoding, XML oder JSON zurückgeben kann. Die Anwendung entscheidet, wie die Antwort formatiert werden soll, indem sie den HTTP_ACCEPT-Header prüft, kann aber zu einem bestimmten Format gezwungen werden, indem sie den format
Parameter.
Bei der Überprüfung des Inhalts des Formatparameters könnte dieser per Querystring oder Postdata gesendet werden, was von einer Vielzahl von Faktoren abhängt, nicht zuletzt davon, ob die aufrufenden Anwendungen "&format=json" in ihre Anfrage einmischen wollen oder nicht. In diesem Fall, $_REQUEST
ist sehr praktisch, weil es mir erspart, so etwas eingeben zu müssen:
$format = isset($_POST['format']) ? $_POST['format']
: (isset($_GET['format']) ? $_GET['format'] : null);
Ich werde nicht weiter ausholen, aber es genügt zu sagen, dass $_REQUEST
Von der Nutzung wird nicht abgeraten, weil sie von Natur aus gefährlich ist - sie ist nur ein weiteres Werkzeug, das genau das tut, was von ihm verlangt wird, ob man diese Auswirkungen versteht oder nicht - es ist die schlechte, faule oder uninformierte Entscheidung eines schlechten, faulen oder unerfahrenen Programmierers, die dieses Problem verursacht.
Wie zu verwenden $_REQUEST
sicher
- Ihre Daten kennen : Sie sollten eine gewisse Erwartung haben, welche Art von Daten Sie erhalten werden, also bereinigen Sie sie entsprechend. Daten für eine Datenbank?
addslashes()
o*_escape_string()
. Zeigen Sie es dem Benutzer zurück?htmlentities()
ohtmlspecialchars()
. Erwarten Sie numerische Daten?is_numeric()
octype_digit()
. In der Tat,filter_input()
und die zugehörigen Funktionen dienen lediglich der Überprüfung und Bereinigung von Daten. Verwenden Sie diese Werkzeuge immer. - Kein direkter Zugriff auf vom Benutzer bereitgestellte superglobale Daten . Machen Sie es sich zur Gewohnheit, Ihre Daten jedes Mal zu bereinigen, und verschieben Sie Ihre Daten in saubere Variablen, selbst wenn es sich nur um
$post_clean
. Alternativ können Sie auch direkt in den Superglobalen bereinigen, aber der Grund, warum ich die Verwendung einer separaten Variable befürworte, ist, dass es dadurch einfacher wird, Schwachstellen im Code zu erkennen, wie alles direkt auf eine Superglobale und nicht auf ihr bereinigtes Äquivalent verweist, gilt als gefährlicher Fehler. - Sie wissen, woher Ihre Daten kommen sollen. Bezogen auf mein obiges Beispiel ist es durchaus sinnvoll, dass die Antwortformatvariable über GET oder POST gesendet werden kann. Ich erlaube auch, dass die "action"-Variable über beide Methoden gesendet werden kann. Allerdings, die Aktionen selbst haben sehr spezifische Anforderungen, welches HTTP-Verb akzeptabel ist . Funktionen, die z. B. Änderungen an den vom Dienst verwendeten Daten vornehmen, dürfen nur per POST gesendet werden. Anfragen für bestimmte Arten von Daten ohne oder mit geringen Rechten (z. B. dynamisch generierte Kartenbilder) können als Antwort auf Anfragen mit beiden Methoden übermittelt werden.
Abschließend möchte ich Ihnen diese einfache Regel ans Herz legen:
SICHERHEIT IST DAS, WAS MAN DARAUS MACHT, LEUTE!
EDITAR:
I stark empfehlen den Rat von bobince: Wenn Sie können, stellen Sie die request_order
in der php.ini auf "GP" setzen, d.h. keine Cookie-Komponente. In mehr als 98 % der Fälle gibt es dafür keine rationale Begründung, da Cookie-Daten fast nie als vergleichbar mit dem Querystring oder den Postdata angesehen werden sollten.
P.S., Anekdote!
Ich kannte einen Programmierer, der die Idee hatte $_REQUEST
einen Ort, an dem man einfach Daten speichern konnte, die global zugänglich waren. Wichtige Benutzernamen und Passwörter, Pfade zu Dateien, alles wurde in $_REQUEST
. Er war ein wenig überrascht (wenn auch leider nicht komisch), als ich ihm sagte, wie sich diese Variable verhält. Es erübrigt sich zu sagen, dass diese Praxis abgeschafft wurde.
GET-Anfragen sollten idempotent sein, POST-Anfragen sind es im Allgemeinen nicht. Dies bedeutet, dass Daten in $_GET
y $_POST
sollten im Allgemeinen auf unterschiedliche Weise verwendet werden.
Wenn Ihre Anwendung Daten aus $_REQUEST
wird es sich bei GET- und POST-Anfragen gleich verhalten, was gegen die Idempotenz von GET verstößt.
- See previous answers
- Weitere Antworten anzeigen