TL; DR - การแก้ไข (ซึ่งคุณอาจไม่จำเป็นต้องใช้) คือ VERY SIMPLE และท้ายคำตอบนี้
ฉันจะพยายามตอบคำถามเฉพาะของคุณ แต่ความเข้าใจผิดของคุณเกี่ยวกับสิ่งที่ PATH_INFO ทำให้คำถามนั้นผิดไปเล็กน้อย
คำถามแรกควรเป็น "ธุรกิจข้อมูลเส้นทางนี้คืออะไร"
คำถามต่อไปของคุณควรเป็น: "PHP กำหนดได้อย่างไรPATH_INFO
และSCRIPT_FILENAME
เป็นอย่างไร"
- PHP เวอร์ชันก่อนหน้านี้ไร้เดียงสาและในทางเทคนิคก็ไม่ได้รับการสนับสนุน
PATH_INFO
ดังนั้นสิ่งที่ควรจะเป็นPATH_INFO
ถูกรวมเข้าด้วยกันSCRIPT_FILENAME
ซึ่งใช่ถูกใช้งานไม่ได้ในหลายกรณี ฉันไม่มี PHP เวอร์ชันเก่าพอที่จะทดสอบ แต่ฉันเชื่อว่ามันSCRIPT_FILENAME
เป็น shebang ทั้งหมด: "/path/to/script.php/THIS/IS/PATH/INFO" ในตัวอย่างด้านบน (นำหน้าด้วย docroot ตามปกติ)
- ด้วยการเปิดใช้งาน cgi.fix_pathinfo PHP จะค้นหา "/ This / IS / PATH / INFO" อย่างถูกต้องสำหรับตัวอย่างข้างต้นและใส่ลงใน
PATH_INFO
และSCRIPT_FILENAME
รับส่วนที่ชี้ไปที่สคริปต์ที่ร้องขอ (นำหน้าด้วย docroot ของหลักสูตร)
- หมายเหตุ: เมื่อ PHP รองรับการใช้งานจริง
PATH_INFO
พวกเขาจะต้องเพิ่มการตั้งค่าการกำหนดค่าสำหรับคุณสมบัติใหม่เพื่อให้ผู้ใช้งานสคริปต์ที่ขึ้นอยู่กับพฤติกรรมเก่าสามารถใช้งาน PHP เวอร์ชันใหม่ได้ นั่นเป็นเหตุผลที่มีแม้กระทั่งสวิตช์การกำหนดค่าสำหรับมัน มันควรจะติดตั้งในตัว (พร้อมกับพฤติกรรม "อันตราย") ตั้งแต่เริ่มต้น
แต่ PHP รู้ได้อย่างไรว่าส่วนใดเป็นสคริปต์และข้อมูลเส้นทางคืออะไร? เกิดอะไรขึ้นถ้า URI เป็นเช่น:
http://example.com/path/to/script.php/THIS/IS/PATH/INFO.php?q=foo
- นั่นอาจเป็นคำถามที่ซับซ้อนในบางสภาพแวดล้อม สิ่งที่เกิดขึ้นใน PHP คือพบส่วนแรกของเส้นทาง URI ที่ไม่ตรงกับสิ่งใดภายใต้ docroot ของเซิร์ฟเวอร์ สำหรับตัวอย่างนี้จะเห็นว่าในเซิร์ฟเวอร์ของคุณคุณไม่มี "/docroot/path/to/script.php/THIS" แต่แน่นอนที่สุดคุณมี "/docroot/path/to/script.php" ดังนั้นตอนนี้
SCRIPT_FILENAME
ได้รับการพิจารณาและPATH_INFO
ได้รับส่วนที่เหลือ
- ดังนั้นตอนนี้ตัวอย่างที่ดีของอันตรายที่มีรายละเอียดอย่างดีในเอกสาร Nginx และในคำตอบของ Hrvoje Špoljar (คุณไม่สามารถยุ่งเกี่ยวกับตัวอย่างที่ชัดเจนเช่นนี้) ได้ชัดเจนยิ่งขึ้น: ตัวอย่างของ Hrvoje (" http: // example" com / foo.jpg / nonexistent.php "), PHP เห็นไฟล์ใน docroot ของคุณ" /foo.jpg "แต่ไม่เห็นสิ่งที่เรียกว่า" /foo.jpg/nonexistent.php "ดังนั้น
SCRIPT_FILENAME
รับ" /foo.jpg " (อีกครั้งนำหน้าด้วย docroot) และPATH_INFO
รับ "/ noonexistent.php"
เหตุใดจึงเป็นอันตรายอย่างไรและควรชัดเจนว่า:
- เว็บเซิร์ฟเวอร์ไม่ใช่ความผิด แต่เป็นเพียงการพร็อกซี URI ถึง PHP เท่านั้นซึ่งพบว่า "foo.jpg" มีเนื้อหา PHP จริง ๆ ดังนั้นจึงดำเนินการ (ตอนนี้คุณได้รับ pwned แล้ว!) นี่ไม่ใช่เฉพาะ Nginx ต่อ se
- จริงปัญหาคือการที่คุณปล่อยให้เนื้อหาที่ไม่น่าเชื่อถือถูกอัปโหลดที่ใดที่หนึ่งโดยไม่ต้องฆ่าเชื้อและคุณอนุญาตการร้องขอโดยพลการอื่น ๆ ไปยังสถานที่เดียวกันซึ่ง PHP อย่างมีความสุขรันเมื่อมันสามารถ
Nginx และ Apache สามารถสร้างหรือกำหนดค่าเพื่อป้องกันการร้องขอโดยใช้กลอุบายนี้และมีความอุดมสมบูรณ์ของตัวอย่างสำหรับวิธีการทำที่รวมทั้งในคำตอบของ user2372674 บทความในบล็อกนี้อธิบายถึงปัญหาได้เป็นอย่างดี แต่ไม่มีวิธีแก้ไขที่เหมาะสม
อย่างไรก็ตามทางออกที่ดีที่สุดคือตรวจสอบให้แน่ใจว่า PHP-FPM ได้รับการกำหนดค่าอย่างถูกต้องเพื่อไม่ให้รันไฟล์เว้นแต่ว่าลงท้ายด้วย ".php" เป็นที่น่าสังเกตว่า PHP-FPM เวอร์ชันล่าสุด (~ 5.3.9 +?) มีสิ่งนี้เป็นค่าเริ่มต้นดังนั้นความเสี่ยงนี้จึงไม่เป็นปัญหาอีกต่อไป
การแก้ไขปัญหา
หากคุณมี PHP-FPM เวอร์ชันล่าสุด (~ 5.3.9 +?) คุณต้องไม่ทำอะไรเลยเนื่องจากพฤติกรรมด้านความปลอดภัยด้านล่างนี้เป็นค่าเริ่มต้นแล้ว
มิฉะนั้นค้นหาwww.conf
ไฟล์ของ php-fpm (อาจ/etc/php-fpm.d/www.conf
ขึ้นอยู่กับระบบของคุณ) ตรวจสอบให้แน่ใจว่าคุณมีสิ่งนี้:
security.limit_extensions = .php
อีกครั้งนั่นเป็นค่าเริ่มต้นในหลาย ๆ ที่ในวันนี้
โปรดทราบว่าสิ่งนี้จะไม่ป้องกันผู้โจมตีไม่ให้อัพโหลดไฟล์ ".php" ไปยัง WordPress อัพโหลดโฟลเดอร์และดำเนินการโดยใช้เทคนิคเดียวกัน คุณยังต้องมีความปลอดภัยที่ดีสำหรับแอปพลิเคชันของคุณ