wake-up-neo.com

Was ist los mit $ _REQUEST []?

Ich habe hier eine Reihe von Beiträgen gesehen, die sagten, die $_REQUEST-Variable nicht zu verwenden. Normalerweise nicht, aber manchmal ist es bequem. Was stimmt damit nicht?

112
sprugman

Es ist absolut nichts dagegen einzuwenden, Eingaben von $_GET und $_POST auf eine kombinierte Weise zu übernehmen. Tatsächlich möchten Sie dies fast immer tun:

  • bei einer einfachen idempotenten Anforderung, die normalerweise über GET übermittelt wird, kann die gewünschte Datenmenge nicht in eine URL passen. Daher wurde sie aus praktischen Gründen zu einer Anforderung POST mutiert.

  • für eine Anfrage, die einen echten Effekt hat, müssen Sie prüfen, ob sie von der Methode POST übermittelt wird. Die Möglichkeit, dies zu tun, besteht darin, $_SERVER['REQUEST_METHOD'] explizit zu überprüfen, und sich nicht darauf zu verlassen, dass $_POST für einen GET leer ist. Wenn die Methode POST ist, möchten Sie trotzdem einige Abfrageparameter aus der URL herausnehmen.

Nein, das Problem mit $_REQUEST hat nichts mit der Verknüpfung von GET- und POST -Parametern zu tun. Es ist auch so, dass es standardmäßig $_COOKIE enthält. Und Cookies sind wirklich nicht wie Parameter für die Übermittlung von Formularen: Sie möchten sie fast nie als dasselbe behandeln.

Wenn Sie versehentlich ein Cookie mit dem gleichen Namen wie eines Ihrer Formularparameter auf Ihrer Website erhalten, werden die auf diesen Parameter angewendeten Formulare auf mysteriöse Weise nicht mehr ordnungsgemäß funktionieren, da die Cookie-Werte die erwarteten Parameter überschreiben. Dies ist sehr einfach zu tun, wenn Sie mehrere Apps auf derselben Website haben. Wenn Sie nur ein paar Benutzer mit alten Cookies haben, ist das Debuggen sehr schwierig. Sie verwenden keine weiteren Anwendungen und brechen die Formulare nicht -jemand anderes kann sich reproduzieren.

Sie können dieses Verhalten in die viel sinnvollere Reihenfolge GP (keine C) mit der Option request_order config in PHP ändern. 5.3. Wo dies nicht möglich ist, würde ich persönlich $_REQUEST vermeiden und, wenn ich ein kombiniertes GET + POST-Array benötige, es manuell erstellen.

181
bobince

Ich habe einige Newsgroup-Posts zu PHP Internals durchforstet und eine interessante Diskussion zu diesem Thema gefunden. Der anfängliche Thread befasste sich mit etwas anderem, aber eine Bemerkung von Stefan Esser, ein (wenn nicht der) Sicherheitsexperte in der PHP - Welt, richtete die Diskussion auf die Sicherheitsauswirkungen der Verwendung von $ _REQUEST für a wenige Beiträge.

Zitieren von Stefan Esser in PHP Internals

$ _REQUEST ist eine der größten Designschwächen in PHP. Jede Anwendung mit $ _REQUEST ist höchstwahrscheinlich anfällig für verzögerte Cross Site Request Fälschungsprobleme. (Dies bedeutet im Wesentlichen, wenn beispielsweise ein Cookie mit dem Namen (Alter) Vorhanden ist, wird der GET/POST-Inhalt immer überschrieben, und daher werden Unerwünschte Anforderungen ausgeführt.)

und in einer später Antwort auf den gleichen Thread

Es geht nicht darum, dass jemand GET, POST schmieden kann; COOKIE-Variablen . Es geht darum, dass COOKIEs GET- und POST -Daten in .__ überschreiben. ANFORDERN.

Daher könnte ich Ihren Browser mit einem Cookie infizieren, das z. B. ... sagt. action = logout und ab diesem Tag können Sie die Anwendung nicht mehr verwenden mehr, weil REQUEST [action] für immer abgemeldet wird (bis Sie das Cookie manuell löschen).

Und Sie mit einem COOKIE zu infizieren, ist so einfach ...
a) Ich könnte ein XSS-Vuln in jeder Anwendung auf einer Subdomain verwenden
b) Haben Sie schon immer versucht, ein Cookie für * .co.uk oder * .co.kr zu setzen, wenn Sie ein .__ besitzen. Einzige Domain dort?
c) Andere bereichsübergreifende Wege ...

Und wenn Sie glauben, dass dies kein Thema ist, dann kann ich Ihnen das sagen. Es gibt eine einfache Möglichkeit, f.e. ein * .co.kr-Cookie, das sich ergibt In mehreren PHP -Versionen werden nur weiße Seiten zurückgegeben. Stellen Sie sich vor: Nur ein einziger Cookie, um alle PHP - Seiten in * .co.kr zu töten

Und durch das Setzen einer ungültigen Sitzungs-ID in einem für * .co.kr in einem .__ gültigen Cookie. Variable mit dem Namen + PHPSESSID = illegal Sie können trotzdem jedes PHP .__ DOS ausführen. Anwendung in Korea mit PHP Sitzungen ...

Die Diskussion wird für einige weitere Beiträge fortgesetzt und ist interessant zu lesen. 


Wie Sie sehen, besteht das Hauptproblem bei $ _REQUEST nicht so sehr darin, dass es Daten von $ _GET und $ _POST, sondern auch von $ _COOKIE enthält. Einige andere Leute auf der Liste schlugen vor, die Reihenfolge zu ändern, in der $ _REQUEST gefüllt wird, z. Erst mit $ _COOKIE füllen, aber dies könnte zu zahlreichen anderen potenziellen Problemen führen, zum Beispiel beim Session-Handling

Sie könnten $ _COOKIES jedoch vollständig aus dem globalen $ _REQUEST weglassen, so dass es nicht durch eines der anderen Arrays überschrieben wird (Sie können es auf eine beliebige Kombination des Standardinhalts beschränken, z. B. das PHP). Handbuch zur Einstellung variable_order ini sagt uns:

variable_order Legt die Reihenfolge der EGPCS-Variablen (Environment, Get, Post, Cookie und Server) fest. Wenn variables_order beispielsweise auf "SP" gesetzt ist, erstellt PHP die Superglobalen $ _SERVER und $ _POST, nicht jedoch $ _ENV, $ _GET und $ _COOKIE. Die Einstellung auf "" bedeutet, dass keine Superglobals gesetzt werden. 

Andererseits könnten Sie auch in Betracht ziehen, $ _REQUEST nicht vollständig zu verwenden, weil Sie in PHP einfach auf Environment, Get, Post, Cookie und Server in ihren eigenen Globals zugreifen können und einen Angriffsvektor weniger haben. Sie müssen diese Daten immer noch bereinigen, aber es ist eine Sache, um die Sie sich Sorgen machen müssen.


Nun fragen Sie sich vielleicht, warum es überhaupt $ _REQUEST gibt und warum es nicht entfernt wird. Dies wurde auch bei PHP Internals gefragt. Rasmus Lerdorf zitiert über Warum gibt es $ _REQUEST? auf PHP Interns

Je mehr Sachen wir entfernen, desto schwieriger wird es für die Menschen Wechseln Sie schnell zu neueren, schnelleren und sichereren PHP-Versionen. Das verursacht weitaus mehr Frustration für alle als ein paar "hässliche" Erbe Eigenschaften. Wenn es einen guten technischen Grund gibt, Leistung oder Sicherheit, dann müssen wir es uns genauer ansehen. In diesem Fall ist der Was wir prüfen sollten, ist nicht, ob wir $ _REQUEST .__ entfernen sollen. Aber ob wir Cookie-Daten daraus entfernen sollen. Viele Konfigurationen mache das schon, auch alle meine eigenen, und es gibt eine starke Gültigkeit Sicherheitsgrund dafür, dass in $ _REQUEST keine Cookies enthalten sind. Die meisten Leute benutzen $ _REQUEST bedeutet GET oder POST, ohne zu wissen, dass es auch .__ enthalten kann. Cookies und als solche Bösewichte könnten möglicherweise eine Cookie-Injektion durchführen Tricks und brechen naive Anwendungen.

Wie auch immer, hoffe, dass etwas Licht erscheint.

70
Gordon

$_REQUEST bezieht sich auf alle Arten von Anforderungen (GET, POST usw.). Dies ist manchmal nützlich, in der Regel ist es jedoch besser, die genaue Methode anzugeben ($ _GET, $ _POST usw.).

10
Luca Matteis

GET-Anforderungen sollten idempotent sein und POST -Anfragen sind im Allgemeinen nicht. Dies bedeutet, dass Daten in $_GET und $_POST im Allgemeinen auf unterschiedliche Weise verwendet werden sollten.

Wenn Ihre Anwendung Daten aus $_REQUEST verwendet, verhält es sich bei GET- und POST -Anfragen gleich, was die Idempotenz von GET verletzt.

8
Ben James

$_REQUEST wird im Allgemeinen aus dem gleichen Grund als schädlich angesehen, dass Datentransformationen mit einfacher bis mittlerer Komplexität häufig im Anwendungscode durchgeführt und nicht in SQL deklariert werden: Einige Programmierer sind scheiße.

Wenn Sie dazu neigen, $_REQUEST überall zu verwenden, kann ich über GET alles tun, was ich über POST tun konnte. Dies bedeutet, <img>-Tags auf meiner (böswilligen) Website einzurichten, die dazu führen, dass Benutzer, die sich bei Ihrem E-Commerce-Modul angemeldet haben, automatisch Produkte kaufen oder ich kann sie dazu veranlassen, auf Links zu klicken, die zu gefährlichen Aktionen oder der Offenlegung sensibler Informationen führen (wahrscheinlich für mich).

Dies ist jedoch auf einen unerfahrenen oder zumindest unerfahrenen PHP Programmierer zurückzuführen, der einfache Fehler begeht. Zuerst wissen Sie, wann welche Daten geeignet sind. Ich habe beispielsweise einen Webservice, der Antworten in URLEncoding, XML oder JSON zurückgeben kann. Die Anwendung entscheidet, wie die Antwort formatiert wird, indem sie den HTTP_ACCEPT-Header überprüft. Sie kann jedoch durch Senden des Parameters format in eine einzige gezwungen werden.

Wenn der Inhalt des Formatparameters geprüft wird, kann er abhängig von einer Vielzahl von Faktoren über Querstring oder Postdata gesendet werden, wobei nicht zuletzt darauf zu achten ist, ob die aufrufenden Anwendungen "& format = json" mit ihrer Anforderung mischen wollen oder nicht. In diesem Fall ist $_REQUEST sehr praktisch, da ich so etwas nicht eingeben muss:

$format = isset($_POST['format']) ? $_POST['format'] 
    : (isset($_GET['format']) ? $_GET['format'] : null);

Ich werde nicht viel weiter streifen, aber es genügt zu sagen, dass die Verwendung von $_REQUEST nicht abschreckend ist, weil es von Natur aus gefährlich ist - es ist nur ein anderes Werkzeug, das genau das tut, was von ihm verlangt wird, ob Sie diese Implikationen verstehen oder nicht - es ist die arme, faule oder uninformierte Entscheidung eines armen, faulen oder unerfahrenen Programmierers, die dieses Problem verursacht.

So verwenden Sie $_REQUEST sicher


  1. Kennen Sie Ihre Daten: Sie sollten einige Erwartungen haben, welche Art von Daten Sie erhalten werden. Desinfizieren Sie sie daher entsprechend. Daten für eine Datenbank? addslashes() oder *_escape_string(). Wollen Sie es dem Benutzer wieder zeigen? htmlentities() oder htmlspecialchars(). Numerische Daten erwarten? is_numeric() oder ctype_digit(). Tatsächlich sind filter_input() und die dazugehörigen Funktionen nur dazu gedacht, Daten zu prüfen und zu bereinigen. Verwenden Sie diese Werkzeuge immer.
  2. Greifen Sie nicht direkt auf vom Benutzer bereitgestellte Superglobals-Daten zu. Machen Sie es sich zur Gewohnheit, Ihre Daten jedes Mal zu bereinigen und verschieben Sie Ihre Daten in saubere Variablen, auch wenn es sich nur um $post_clean handelt. Alternativ können Sie einfach direkt in den Superglobals bereinigen. Der Grund, warum ich die Verwendung einer separaten Variablen befürworte, besteht darin, dass es leicht ist, Schwachstellen im Code aufzuspüren, da alles direkt auf ein Superglobales verweist und nicht auf das gesäuberte Äquivalent als gefährlicher Fehler betrachtet.
  3. Wissen, woher Ihre Daten kommen sollen. Bezüglich meines Beispiels von oben ist es absolut sinnvoll, die Antwortformatvariable über GET oder POST senden zu lassen. Ich lasse auch zu, dass die "action" -Variable über eine der beiden Methoden gesendet wird. Die Aktionen selbst haben jedoch sehr spezifische Anforderungen hinsichtlich des akzeptablen HTTP-Verbs. Beispielsweise können Funktionen, die Änderungen an den vom Dienst verwendeten Daten vornehmen, nur per POST gesendet werden. Anforderungen für bestimmte Arten von Nicht- oder Niedrigprivileg-Daten (wie z. B. dynamisch erzeugte Kartenbilder) können als Reaktion auf Anforderungen von beiden Methoden bedient werden.

Zum Schluss erinnern Sie sich an diese einfache Regel:

SICHERHEIT IS WAS SIE MACHEN, MENSCHEN!

BEARBEITEN:

I dringend empfiehlt den Rat von Bobince: Wenn möglich, setzen Sie den request_order-Parameter in php.ini auf "GP"; Das heißt, keine Cookie-Komponente. In über 98% der Fälle gibt es fast keine vernünftigen Gründe dafür, da Cookie-Daten fast nie als vergleichbar mit dem Querstring oder mit Postdata betrachtet werden sollten.

P.S., Anekdote!

Ich kannte einen Programmierer, der an $_REQUEST dachte, einen Ort, an dem einfach Daten gespeichert werden können, auf die superglobal zugegriffen werden kann. Wichtige Benutzernamen und Kennwörter, Pfade zu Dateien, nennen Sie es und es wurde in $_REQUEST gespeichert. Er war etwas überrascht (leider nicht komisch), als ich ihm erzählte, wie sich diese Variable verhält. Es ist unnötig zu erwähnen, dass diese Praxis abgesetzt wurde.

8
Dereleased

Es ist vage. Sie wissen nicht wirklich, wie die Daten zu Ihnen gelangt sind, da sie Post-, Get- und Cookie-Daten enthalten. Ich denke nicht unbedingt, dass das immer eine schlechte Sache ist, es sei denn, Sie müssen die Art der Zustellung kennen oder einschränken.

7
Sampson

Ich benutze es eigentlich gerne. Es gibt Ihnen die Flexibilität, GET oder POST zu verwenden, was sich zum Beispiel für Suchformulare als nützlich erweisen kann, bei denen die meisten Daten POST sind. Manchmal möchten Sie jedoch einen Link zu einer bestimmten Suche angeben Verwenden Sie stattdessen GET-Parameter.

Wenn Sie sich viele andere Sprachen ansehen (z. B. ASP.NET), unterscheiden sie überhaupt nicht zwischen GET- und POST - Variablen.

ETA

Ich habe REQUEST noch nie verwendet, um COOKIE-Werte zu erhalten, aber ich denke, Kyle Butt macht in den Kommentaren zu diesem Beitrag einen großartigen Punkt. Es ist NICHT ratsam, REQUEST zu verwenden, um COOKIE-Werte zu erhalten. Ich glaube, er hat Recht, dass es ein wirkliches Potenzial für die Fälschung von Anfragen an verschiedenen Standorten gibt, wenn Sie dies tun.

Die Reihenfolge, in der Sachen in REQUEST geladen werden, wird auch durch die Konfigurationsparameter in php.ini (variables_order und request_order) gesteuert. Wenn Sie also die gleiche Variable sowohl über POST als auch über GET übergeben haben, hängt diejenige, die tatsächlich in REQUEST eingeht, von diesen Ini-Einstellungen ab. Dies kann die Portabilität beeinträchtigen, wenn Sie von einer bestimmten Reihenfolge abhängen und diese Einstellungen anders konfiguriert sind, als Sie dies erwarten.

3
Eric Petroelje

Die einzige Zeit, in der $_REQUEST keine schlechte Idee ist, ist mit GET.

  • Wenn Sie es verwenden, um POST -Werte zu laden, riskieren Sie standortübergreifende Anforderungsfälschungen
  • Wenn Sie damit Cookie-Werte laden, riskieren Sie erneut standortübergreifende Anforderungsfälschungen

Und selbst mit GET ist $_GET kürzer als $_REQUEST;)

2

Es ist wichtig zu wissen, wann POST verwendet wird, wann GET verwendet wird und wann ein Cookie verwendet wird. Mit $ _REQUEST könnte der Wert, den Sie betrachten, von jedem von ihnen stammen. Wenn Sie erwarten, dass der Wert von einem POST, einem GET oder einem COOKIE abgerufen wird, ist es für jemanden, der Ihren Code liest, informativer, die spezifische Variable anstelle von $ _REQUEST zu verwenden.

Jemand anderes hat auch darauf hingewiesen, dass Sie nicht möchten, dass alle POSTs oder Cookies von GETs überschrieben werden, da für alle unterschiedliche Site-Regeln gelten. Wenn Sie zum Beispiel Ajax-Daten zurückgeben, während Sie $ _REQUEST verwenden, sind Sie anfällig zu einem Cross Site Script Angriff.

2
Kyle Butt

Darren Cook: "Seit PHP 5.3 sagt die Standard php.ini nur GET und POST Daten werden in $_REQUEST. Siehe php.net/request_order Ich bin gerade über diese Abwärtskompatibilitätspause gestolpert, als ich erwartet habe, dass die Cookie-Daten in $_REQUEST und frage mich, warum es nicht funktioniert hat! "

Wow ... einige meiner Skripte funktionierten aufgrund eines Upgrades auf PHP 5.3 nicht mehr Ding: Nehmen Sie an, dass Cookies gesetzt werden, wenn Sie das $_REQUEST Variable. Mit dem Upgrade hat genau das aufgehört zu funktionieren.

Ich rufe jetzt Cookie-Werte separat mit $_COOKIE["Cookie_name"]...

0
Arjan202

Ich denke, es gibt kein Problem mit $_REQUEST, aber wir müssen vorsichtig damit umgehen, da es sich um eine Sammlung von Variablen aus 3 Quellen (GPC) handelt.

Ich denke, $_REQUEST ist immer noch verfügbar, um alte Programme mit neuen PHP-Versionen kompatibel zu machen, aber wenn wir neue Projekte (einschließlich neuer Bibliotheken) starten, sollten wir $_REQUEST nicht mehr verwenden, um die Programme klarer zu machen. Wir sollten sogar in Erwägung ziehen, die Verwendung von $_REQUEST zu löschen und durch eine Wrapper-Funktion zu ersetzen, um das Programm leichter zu machen, insbesondere bei der Verarbeitung großer gesendeter Textdaten, da $_REQUEST Kopien von $_POST enthält.

// delete $_REQUEST when program execute, the program would be lighter 
// when large text submitted
unset($_REQUEST);

// wrapper function to get request var
function GetRequest($key, $default = null, $source = '') 
{
  if ($source == 'get') {
    if (isset($_GET[$key])) { 
      return $_GET[$key]; 
    } else { 
      return $default; 
    }
  } else if ($source == 'post') {
    if (isset($_POST[$key])) { 
      return $_POST[$key]; 
    } else { 
      return $default; 
    }
  } else if ($source == 'cookie') {
    if (isset($_COOKIE[$key])) { 
      return $_COOKIE[$key]; 
    } else { 
      return $default; 
    }
  } else {
    // no source specified, then find in GPC
    if (isset($_GET[$key])) {
      return $_GET[$key];     
    } else if (isset($_POST[$key])) {
      return $_POST[$key]; 
    } else if (isset($_COOKIE[$key])) {
      return $_COOKIE[$key]; 
    } else {
      return $default; 
    } 
  }
}
0
user953985

Ich kann nur verwendet werden, wenn Sie die aktuelle URL oder den aktuellen Hostnamen abrufen möchten. Für das Parsen von Daten von dieser URL, z. B. von Parametern mit dem Symbol &, ist dies wahrscheinlich keine gute Idee. Im Allgemeinen möchten Sie nicht eine vage Beschreibung dessen, was Sie versuchen, verwenden. Wenn Sie genau sein müssen, dann ist $ _REQUEST schlecht, wenn Sie nicht spezifisch sein müssen, können Sie es gerne verwenden. Ich würde denken.

0
Brian T Hannan

Wenn Sie wissen, welche Daten Sie wünschen, sollten Sie explizit danach fragen. IMO, GET und POST sind zwei verschiedene Tiere und ich kann mir keinen guten Grund vorstellen, warum Sie jemals Postdaten und Abfragezeichenfolgen mischen müssten. Wenn jemand eine hat, wäre ich interessiert.

Es kann praktisch sein, $ _REQUEST zu verwenden, wenn Ihre Skripts auf dieselbe Weise auf GET oder POST reagieren. Ich würde jedoch behaupten, dass dies ein äußerst seltener Fall sein sollte, und in den meisten Fällen werden zwei separate Funktionen für die Handhabung von zwei separaten Konzepten oder zumindest das Überprüfen der Methode und das Auswählen der richtigen Variablen bevorzugt. Der Programmablauf ist in der Regel viel einfacher zu verfolgen, wenn es nicht erforderlich ist, auf die Herkunft der Variablen zu verweisen. Seien Sie freundlich zu der Person, die Ihren Code in 6 Monaten aufrechterhalten muss. Es könntest du sein.

Berücksichtigen Sie zusätzlich zu den Sicherheitsproblemen und WTFs, die durch Cookies und Umgebungsvariablen in der Variablen REQUEST verursacht werden (lassen Sie mich nicht mit GLOBAL beginnen), darüber nachdenken, was in der Zukunft passieren könnte, wenn PHP andere Methoden wie PUT nativ unterstützt und LÖSCHEN. Es ist äußerst unwahrscheinlich, dass diese mit dem Superglobal REQUEST zusammengeführt werden. Es ist jedoch möglich, dass sie als Option in die Einstellung variable_order aufgenommen werden. Sie haben also wirklich keine Ahnung, was REQUEST beinhaltet und was Vorrang hat, insbesondere wenn Ihr Code auf einem Server eines Drittanbieters bereitgestellt wird.

Ist POST sicherer als GET? Nicht wirklich. Es ist besser, GET möglichst praktisch einzusetzen, da in Ihren Protokollen einfacher zu sehen ist, wie Ihre Anwendung bei einem Angriff ausgenutzt wird. POST eignet sich besser für Vorgänge, die sich auf den Domänenstatus auswirken, da Spiders sie normalerweise nicht befolgen, und Mechanismen zum vorhersagenden Abruf nicht den gesamten Inhalt löschen, wenn Sie sich bei Ihrem CMS anmelden. Die Frage war jedoch nicht nach den Vorzügen von GET vs. POST, es ging darum, wie der Empfänger die eingehenden Daten behandeln soll und warum es schlecht ist, sie zusammenzuführen, daher handelt es sich wirklich nur um eine BTW.

0
Duncan