شرح - post method in php



ما الخطأ في استخدام $_REQUEST[]؟ (10)

Darren Cook: "منذ php 5.3 ، يشير php.ini الافتراضي إلى أن بيانات GET و POST فقط يتم وضعها في $_REQUEST . انظر php.net/request_order لقد تعثرت للتو في هذا التوافق مع الإصدارات السابقة عندما تتوقع أن تكون بيانات ملفات تعريف الارتباط في $_REQUEST لماذا لم تكن تعمل! "

واو ... لقد توقفت بعض النصوص الخاصة بي عن العمل بسبب الترقية إلى PHP 5.3 . فعل الشيء نفسه: افترض أنه سيتم تعيين ملفات تعريف الارتباط عند استخدام المتغير $_REQUEST . مع الترقية بالضبط توقفت عن العمل.

أدعو الآن قيم ملفات تعريف الارتباط بشكل منفصل باستخدام $_COOKIE["Cookie_name"] ...

https://code.i-harness.com

لقد رأيت عددًا من المشاركات هنا تقول بعدم استخدام المتغير $_REQUEST . أنا عادة لا ، ولكن في بعض الأحيان أنها مريحة. ما الخطأ فى ذلك؟


أعتقد أنه لا توجد مشكلة في $_REQUEST ، ولكن يجب أن نكون حذرين عند استخدامه لأنه مجموعة من المتغيرات من 3 مصادر (GPC).

أعتقد أن $_REQUEST ما زال متاحًا لجعل البرامج القديمة متوافقة مع إصدارات php الجديدة ، ولكن إذا بدأنا مشاريع جديدة (بما في ذلك المكتبات الجديدة) أعتقد أنه لا ينبغي لنا استخدام $_REQUEST بعد الآن لجعل البرامج أكثر وضوحًا. يجب علينا حتى التفكير في حذف استخدام $_REQUEST واستبداله بوظيفة ملحقة لجعل البرنامج أخف ، خاصة في معالجة البيانات النصية الكبيرة المقدمة ، حيث يحتوي $_REQUEST على نسخ من $_POST .

// 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; 
    } 
  }
}

إذا كنت تعرف ما هي البيانات التي تريدها ، فعليك أن تطلبها بصراحة. IMO ، GET و POST هما حيوانان مختلفان ولا أستطيع التفكير في سبب وجيه لماذا ستحتاج في أي وقت إلى خلط البيانات المنشورة وسلاسل الاستعلام. إذا كان لدى أحدهم ، سأكون مهتمًا.

يمكن أن يكون ملائما لاستخدام $ _REQUEST عندما تستجيب البرامج النصية الخاصة بك إما GET أو POST بنفس الطريقة. يمكنني القول أنه ينبغي أن تكون هذه حالة نادرة للغاية ، وفي معظم الحالات ، يفضل استخدام وظيفتين منفصلتين للتعامل مع مفصلين منفصلين ، أو على الأقل التحقق من الطريقة واختيار المتغيرات الصحيحة. عادةً ما يكون تتبع البرنامج أسهل كثيرًا عندما لا يكون من الضروري الإشارة المرجعية حيث قد تأتي من المتغيرات. كن لطيفًا مع الشخص الذي يجب عليه الاحتفاظ بالرمز في غضون 6 أشهر. ربما تكون أنت

بالإضافة إلى مشاكل الأمان و WTFs التي تسببها ملفات تعريف الارتباط ومتغيرات البيئة في المتغير REQUEST (لا تدع لي البدء في GLOBAL) ، فكر في ما قد يحدث في المستقبل إذا بدأت PHP في دعم طرق أخرى مثل PUT و DELETE. على الرغم من أنه من غير المرجح أن يتم دمج هذه العناصر في REQUEST superglobal ، إلا أنه من الممكن تضمينها كخيار في إعداد variable_order. إذاً ، فأنت لا تملك أي فكرة على الإطلاق عما يحمله REQUEST ، وما هو الأسبقية ، خاصة إذا تم نشر الكود الخاص بك على خادم طرف ثالث.

هل POST أكثر أمانًا من GET؟ ليس صحيحا. من الأفضل استخدام GET حيث يكون عمليًا لأنه من الأسهل أن ترى في سجلاتك كيف يتم استغلال تطبيقك عند تعرضه للهجوم. POST أفضل للعمليات التي تؤثر على حالة المجال لأن العناكب لا تتبعها بشكل عام ، ولا تؤدي آليات الجلب التنبؤي إلى حذف كل المحتوى الخاص بك عند تسجيل الدخول إلى نظام إدارة المحتوى الخاص بك. ومع ذلك ، لم يكن السؤال حول مزايا GET مقابل POST ، وإنما كان حول كيفية تعامل جهاز الاستقبال للبيانات الواردة ولماذا من السيء دمجها ، لذا فإن هذا في الحقيقة مجرد BTW.


المرة الوحيدة التي تستخدم $_REQUEST ليست فكرة سيئة هي GET.

  • إذا كنت تستخدمه لتحميل قيم POST ، فأنت تخاطر بتزوير طلبات عبر المواقع
  • إذا كنت تستخدمه لتحميل قيم ملفات تعريف الارتباط ، فستخاطر مجددًا بتزوير طلبات عبر الموقع

وحتى مع GET ، يكون $_REQUEST أقصر في الكتابة من $_REQUEST ؛)


انها غير آمنة للغاية. كما أنه أمر محرج لأنك لا تعرف ما إذا كنت تحصل على POST أو GET أو أي طلب آخر. يجب عليك معرفة الفرق بينهما عند تصميم تطبيقاتك. GET غير آمن للغاية حيث يتم تمريره في عنوان URL ولا يناسب أي شيء تقريبًا إلى جانب التنقل في الصفحة. POST ، في حين أنها ليست آمنة في حد ذاتها ، يوفر مستوى واحد من safetey.


تشير $_REQUEST إلى كافة أنواع الطلبات (GET و POST وما إلى ذلك). هذا مفيد في بعض الأحيان ، ولكن عادة ما يكون من الأفضل تحديد الطريقة الصحيحة ($ _GET ، $ _POST الخ).


لا يوجد شيء خاطئ على الإطلاق في أخذ كلٍّ من $_GET و $_POST بطريقة مشتركة. في الواقع ، هذا ما تريد دائمًا أن تفعله:

  • بالنسبة إلى طلب idempotent العادي الذي يتم إرساله عادة عبر GET ، هناك احتمال ألا يتناسب حجم البيانات التي تريدها مع عنوان URL بحيث يتم تحويره إلى طلب POST بدلاً من ذلك كمسألة عملية.

  • للطلب الذي له تأثير حقيقي ، يجب عليك التحقق من أنه تم إرساله بواسطة طريقة POST. ولكن طريقة القيام بذلك هي التحقق من $_SERVER['REQUEST_METHOD'] بشكل صريح ، وليس الاعتماد على $_POST فارغًا لـ GET. وعلى أي حال ، إذا كانت الطريقة هي POST ، فربما تحتاج إلى أخذ بعض معامِلات طلب البحث من عنوان URL.

لا ، المشكلة مع $_REQUEST لا علاقة لها $_REQUEST GET و POST. إنها أيضًا ، بشكل افتراضي ، تتضمن $_COOKIE . وملفات تعريف الارتباط ليست في الواقع مثل معلمات نموذج الإرسال على الإطلاق: لا تريد أبدًا تقريبًا أن تعاملها على أنها الشيء نفسه.

إذا حصلت بطريق الخطأ على ملف تعريف ارتباط على موقعك بنفس الاسم كأحد معلمات النموذج ، فإن النماذج التي تعتمد على هذه المعلمة ستتوقف بشكل غامض عن العمل بشكل صحيح بسبب قيم ملفات تعريف الارتباط التي تتجاوز المعلمات المتوقعة. من السهل جدًا القيام بذلك إذا كان لديك تطبيقات متعددة على نفس الموقع ، ويمكن أن يكون من الصعب جدًا تصحيحها عندما يكون لديك اثنين من المستخدمين فقط باستخدام ملفات تعريف الارتباط القديمة التي لا تستخدمها حاليًا في التضييق على النماذج وكسرها بطرق لا أي شخص آخر يمكن أن تتكاثر.

يمكنك تغيير هذا السلوك إلى أمر GP (لا يوجد C ) الأكثر request_order مع تكوين request_order في PHP 5.3. عندما لا يكون ذلك ممكنًا ، أنا شخصياً أتفادى $_REQUEST وإذا كنت أحتاج إلى صفيف GET + POST مجتمعة ، $_REQUEST بإنشائه يدويًا.


لقد كنت أحفر من خلال بعض منشورات مجموعة الأخبار على PHP Internals وعثرت على مناقشة شيقة حول الموضوع. كان الخيط الأولي يتعلق بشيء آخر ، إلا أن ملاحظة ستيفان إيسر ، الخبير الأمني ​​(إن لم يكن) في عالم PHP ، حولت النقاش إلى الآثار الأمنية لاستخدام $ _REQUEST لبضع مشاركات.

نقلا عن ستيفان ايسر على PHP Internals

تعتبر $ _REQUEST واحدة من أكبر نقاط الضعف في التصميم في PHP. كل تطبيق يستخدم $ _REQUEST هو على الأرجح عرضة لمشاكل Delayed Cross Site Request Forgery. (وهذا يعني في الأساس أنه إذا كان هناك مثلاً ملف تعريف ارتباط اسمه (العمر) ، فستقوم دائمًا بالكتابة فوق محتوى GET / POST ، وبالتالي سيتم تنفيذ الطلبات غير المرغوب فيها)

وفي رد لاحق على نفس الموضوع

الأمر لا يتعلق بحقيقة أن شخصًا ما يمكنه صياغة GET أو POST ؛ متغيرات COOKIE. يتعلق الأمر بحقيقة أن COOKIE ستحل محل بيانات GET و POST في REQUEST.

لذلك ، يمكن أن أصاب المتصفح باستخدام ملف تعريف الارتباط الذي يقول على سبيل المثال الإجراء = الخروج ومن ذلك اليوم لا يمكنك استخدام التطبيق بعد الآن لأن REQUEST [action] سيكون الخروج إلى الأبد (حتى تحذف ملف تعريف الارتباط يدويًا).

وتصيبك مع COOKIE هو في غاية البساطة ...
أ) يمكنني استخدام XSS في أي تطبيق على نطاق فرعي
ب) حاول إعداد ملف تعريف ارتباط لـ * .co.uk أو * .co.kr عندما تمتلك نطاقًا واحدًا هناك؟
ج) عبر المجالات الأخرى أيا كانت ...

وإذا كنت تعتقد أن هذه ليست مشكلة ، فيمكنني أن أقول لك أن هناك إمكانية بسيطة لضبط ملف تعريف الارتباط * .co.kr الذي ينتج عنه عدة إصدارات من PHP فقط إرجاع الصفحات البيضاء. تخيل: مجرد ملف تعريف ارتباط واحد لقتل جميع صفحات PHP في * .co.kr

وعن طريق تعيين معرف جلسة غير قانوني في ملف تعريف ارتباط صالح لـ * .co.kr في متغير يسمى + PHPSESSID = غير قانوني ، يمكنك الاستمرار في تطبيق DOS PHP في كوريا باستخدام جلسات PHP ...

تستمر المناقشة لبضع مشاركات أكثر ومثيرة للاهتمام للقراءة.

كما ترى ، لا تكمن المشكلة الرئيسية في $ _REQUEST في أنه يحتوي على بيانات من $ _GET و $ _POST ، ولكن أيضًا من $ _COOKIE. اقترح بعض الأشخاص الآخرين في القائمة تغيير الترتيب الذي يتم به ملء $ _REQUEST ، على سبيل المثال ملئه بـ $ _COOKIE أولاً ، ولكن قد يؤدي ذلك إلى العديد من المشكلات المحتملة الأخرى ، على سبيل المثال مع معالجة الجلسة .

يمكنك حذف $ _COOKIES $ من _REQUEST عالمي على الرغم من ذلك ، بحيث لا يتم الكتابة فوقها بواسطة أي من المصفوفات الأخرى (في الواقع ، يمكنك تحديدها لأي مجموعة من محتوياتها القياسية ، مثل دليل PHP في الإعداد ini variable_order أخبرنا:

variable_order تعيين ترتيب التحليل المتغير EGPCS (بيئة ، إحضار ، نشر ، ملفات تعريف الارتباط ، والخادم). على سبيل المثال ، إذا تم تعيين variables_order على "SP" ، فسيؤدي PHP إلى إنشاء superglobals $ _SERVER و $ _POST ، ولكن لن ينشئ $ _ENV و $ _GET و $ _COOKIE. الإعداد إلى "" يعني عدم تعيين superglobals.

ولكن مرةً أخرى ، قد تفكر أيضًا بعدم استخدام $ _REQUEST تمامًا ، لأنه ببساطة في PHP يمكنك الوصول إلى البيئة ، و الحصول على ، و النشر ، و ملف تعريف الارتباط ، و الخادم في globals الخاصة بهم و يكون له هجوم واحد أقل. لا يزال عليك تطهير هذه البيانات ، ولكن هناك شيء أقل ما يدعو للقلق.

الآن قد تتساءل ، لماذا يوجد $ _REQUEST بعد كل شيء ولماذا لم تتم إزالته. وقد سئل هذا على PHP Internals كذلك. نقلا عن Rasmus Lerdorf حول سبب وجود $ _REQUEST؟ على PHP Internals

كلما زاد عدد الأشياء التي نزيلها ، أصبح من الصعب على الأشخاص الانتقال سريعًا إلى إصدارات أحدث وأسرع وأكثر أمانًا من PHP. هذا يسبب إحباطًا كبيرًا للجميع أكثر من بضع ميزات قديمة "قبيحة". إذا كان هناك سبب تقني لائق أو أداء أو أمن ، فإننا نحتاج إلى إلقاء نظرة فاحصة عليه. في هذه الحالة ، فإن الأمر الذي يجب علينا النظر إليه ليس ما إذا كان يجب علينا إزالة $ _REQUEST أم لا ولكن ما إذا كان يجب إزالة بيانات ملفات تعريف الارتباط منه. تقوم العديد من عمليات التهيئة بذلك بالفعل ، بما في ذلك التهيئة الخاصة بي ، وهناك سبب أمان قوي قوي لعدم تضمين ملفات تعريف الارتباط في $ _REQUEST. يستخدم معظم الأشخاص $ _REQUEST ليعني GET أو POST ، دون أن يدركوا أنه يمكن أن يحتوي أيضًا على ملفات تعريف الارتباط ، وأنه من المحتمل أن يقوم الأشخاص السيئون ببعض حيل حقن ملفات تعريف الارتباط وتحطيم التطبيقات الساذجة.

على أي حال ، نأمل أن تسليط بعض الضوء.


يجب أن تكون طلبات GET غير ثابتة وأن طلبات POST ليست عامة. وهذا يعني أنه يجب استخدام البيانات في $_GET و $_POST بطرق مختلفة.

إذا كان تطبيقك يستخدم بيانات من $_REQUEST ، فسوف يتصرف بنفس الطريقة لكل من طلبات GET و POST ، التي تنتهك مفهوم GET.


$_REQUEST ضارًا للسبب نفسه الذي غالبًا ما يتم تنفيذ تحويلات البيانات ذات التعقيد البسيط إلى المتوسط ​​في شفرة التطبيق بدلاً من الإعلان عنها في SQL: يمتص بعض المبرمجين.

على هذا النحو ، إذا كان أحد يميل إلى استخدام $_REQUEST كل مكان ، يمكنني القيام بأي شيء عبر GET يمكنني الوصول إليه عبر POST ، مما يعني إعداد علامات <img> على موقعي (الخبيث) الذي يسبب تسجيل دخول المستخدمين إلى وحدة التجارة الإلكترونية الخاصة بك للشراء في صمت ، أو يمكنني جعلهم ينقرون على الروابط التي تؤدي إلى أعمال خطيرة أو الكشف عن معلومات حساسة (ربما بالنسبة لي).

ومع ذلك ، فإن هذا يرجع إلى وجود مبرمج ، أو على الأقل خبرة ، مبرمج PHP الذي يرتكب أخطاء بسيطة. أولاً ، تعرف متى تكون البيانات من النوع المناسب. على سبيل المثال ، لدي خدمة ويب يمكنها إرجاع الردود في URLEncoding أو XML أو JSON. يقرر التطبيق كيفية تنسيق الاستجابة عن طريق التحقق من رأس HTTP_ACCEPT ، ولكن يمكن إجراؤها في أحدها بشكل محدد عن طريق إرسال معلمة format .

عند التحقق من محتوى معلمة التنسيق ، يمكن إرسالها عبر querystring أو postdata ، اعتمادًا على العديد من العوامل ، وليس أقلها ما إذا كانت تطبيقات الاستدعاء تريد "& format = json" مختلطة مع طلبها. في هذه الحالة ، يكون $_REQUEST مناسبًا جدًا لأنه يوفر لي الحاجة إلى كتابة شيء كالتالي:

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

لن أتطرق إلى أبعد من ذلك ، ولكن يكفي القول إن استخدام $_REQUEST لا يتم ثنيه لأنه خطير بطبيعته - إنه مجرد أداة أخرى تفعل ما يطلب منها بالضبط ، سواء $_REQUEST تلك $_REQUEST أم لا - إنها هو القرار الضعيف أو البطيئ أو الباطل لمبرمج فقير أو كسل أو غير خبير في الخبرة يسبب هذه المشكلة.

كيفية استخدام $_REQUEST بأمان

  1. اعرف بياناتك : يجب أن يكون لديك بعض التوقعات فيما يتعلق بنوع البيانات التي ستحصل عليها ، لذلك قم بتعقيمها وفقًا لذلك. البيانات لقاعدة البيانات؟ addslashes() أو *_escape_string() . ذاهب لإظهار مرة أخرى إلى المستخدم؟ htmlspecialchars() أو htmlspecialchars() . نتوقع البيانات الرقمية؟ is_numeric() أو ctype_digit() . في الواقع ، تم filter_input() ووظائفه ذات الصلة لفعل أي شيء ما عدا فحص وتعقيم البيانات. استخدم هذه الأدوات دائمًا.
  2. لا تدخل بيانات superglobals التي قدمها المستخدم مباشرة . اعتاد على تعقيم بياناتك ، في كل مرة ، ونقل بياناتك لتنظيف المتغيرات ، حتى لو كانت مجرد $post_clean . بدلا من ذلك ، يمكنك فقط تنظيف مباشرة في superglobals ، ولكن السبب في الدعوة إلى استخدام متغير منفصل هو أن ذلك يجعل من السهل تحديد نقاط الضعف في التعليمات البرمجية ، حيث أن أي شيء يشير مباشرة إلى superglobal وليس مكافئ المعقم يعتبر خطأ خطير .
  3. اعرف من أين تأتي البيانات. بالإشارة إلى المثال الخاص بي من أعلاه ، من المعقول تماماً السماح بإرسال متغير تنسيق الاستجابة عبر GET أو POST. أسمح أيضًا بإرسال متغير "الإجراء" عبر أي من الطريقتين. ومع ذلك ، تحتوي الإجراءات نفسها على متطلبات محددة جدًا فيما يتعلق بـ "فعل HTTP" . وظائف ، على سبيل المثال ، التي تجعل التغييرات على البيانات المستخدمة من قبل الخدمة قد يتم إرسالها فقط عبر POST. قد يتم تقديم طلبات لأنواع معينة من البيانات غير ذات الامتيازات المنخفضة (مثل صور الخرائط التي تم إنشاؤها ديناميكيًا) استجابةً للطلبات الواردة من أي من الطريقتين.

في الختام ، تذكر هذه القاعدة البسيطة:

الأمن هو ما تفعله ، الناس!

تصحيح:

أوصي بشدة نصيحة bobince: إذا كنت تستطيع ، قم بتعيين المعلمة request_order في php.ini إلى "GP" ؛ أي ، لا يوجد مكون ملفات تعريف الارتباط. لا يوجد أي منطق منطقي تقريبًا لهذا في 98٪ من الحالات ، حيث أن بيانات ملفات تعريف الارتباط يجب عدم اعتبارها تقريبًا تقريبًا إلى سلسلة البحث أو في postdata.

PS ، حكاية!

عرفت مبرمجًا فكر في $_REQUEST مكانًا لتخزين البيانات التي كان يمكن الوصول إليها بطريقة $_REQUEST . أسماء المستخدمين المهمة وكلمات المرور ومسارات للملفات $_REQUEST وتم تخزينها في $_REQUEST . لقد كان مندهشا بعض الشيء (على الرغم من أنه ليس هزليًا ، للأسف) عندما أخبرته كيف يتصرف هذا المتغير. وغني عن القول ، وقد تم خلع هذه الممارسة.





form-submit