การกำหนดผู้อ้างอิงใน PHP


102

วิธีใดเป็นวิธีที่น่าเชื่อถือและปลอดภัยที่สุดในการพิจารณาว่าหน้าใดถูกส่งหรือเรียกว่า (ผ่าน AJAX) ซึ่งเป็นหน้าปัจจุบัน ฉันไม่ต้องการใช้$_SERVER['HTTP_REFERER']เนื่องจาก (ขาด) ความน่าเชื่อถือและฉันต้องการให้เพจถูกเรียกมาจากคำขอที่มาจากไซต์ของฉันเท่านั้น

แก้ไข: ฉันต้องการตรวจสอบว่ามีการเรียกสคริปต์ที่สร้างชุดการกระทำล่วงหน้าจากหน้าบนเว็บไซต์ของฉัน


5
เหตุใดคุณจึงกล่าวว่า $ _SERVER ['HTTP_REFERER'] ไม่น่าเชื่อถือ
Milan Babuškov

9
การใช้งาน PHP มีความน่าเชื่อถือ ปัญหาคือไม่เคยมีเบราว์เซอร์ส่งสิ่งนี้และคุณยังสามารถแก้ไขได้หากต้องการ ดังนั้นจึงไม่น่าเชื่อถือว่าถูกต้องจากฝั่งของลูกค้า
Biri

2
วิธีที่เป็นไปได้คือใส่คีย์เฉพาะ (เช่น GUID) ในฟิลด์หนึ่งของเพจของคุณและส่งกลับในคำขอถัดไป
PhiLho

หาที่อยู่ IP $_SERVER[REMOTE_ADDR]ของเซิร์ฟเวอร์และการใช้งาน

คำตอบ:


93

REFERER ถูกส่งโดยเบราว์เซอร์ของไคลเอนต์โดยเป็นส่วนหนึ่งของโปรโตคอล HTTP ดังนั้นจึงไม่น่าเชื่อถืออย่างแน่นอน อาจไม่มีอยู่อาจมีการปลอมแปลงคุณไม่สามารถวางใจได้หากเป็นเพราะเหตุผลด้านความปลอดภัย

หากคุณต้องการตรวจสอบว่าคำขอมาจากไซต์ของคุณหรือไม่คุณก็ทำไม่ได้ แต่คุณสามารถตรวจสอบได้ว่าผู้ใช้เคยเข้ามาที่ไซต์ของคุณและ / หรือได้รับการรับรองความถูกต้อง คุกกี้จะถูกส่งไปในคำขอของ AJAX เพื่อให้คุณวางใจได้


5
หากคุณต้องการใช้วิธีนี้คุณควรตรวจสอบผู้อ้างอิงด้วยเพื่อป้องกัน CSRF en.wikipedia.org/wiki/Cross-site_request_forgery
JD Isaacks

17
ตามหลักการแล้วคุณควรใช้โทเค็นที่ไม่ซ้ำกันต่อเซสชันต่อผู้ใช้ (ตามคำขอหากคุณหวาดระแวง) เพื่อป้องกันการโจมตี CSRF การตรวจสอบผู้อ้างอิงเป็นเพียงการรักษาความปลอดภัยโดยการทำให้สับสนและไม่ใช่วิธีแก้ปัญหาที่แท้จริง
Seldaek

3
@ Seldaek ไม่การตรวจสอบผู้อ้างอิงไม่ใช่ 'การรักษาความปลอดภัยโดยการทำให้สับสน' ผู้โจมตีที่พยายามทำการโจมตี CSRF ไม่สามารถควบคุมผู้อ้างอิงที่ส่งมาจากเบราว์เซอร์ของเหยื่อได้ดังนั้นการตรวจสอบจะป้องกัน CSRF อย่างไรก็ตามฉันจะยืนตามข้อสรุปของคุณว่าคุณควรใช้โทเค็น CSRF แทนเนื่องจากวิธีการตรวจสอบผู้อ้างอิงมีข้อเสียรวมถึงทำให้คุณเสี่ยงหากคุณมีการเปลี่ยนเส้นทางแบบเปิดในไซต์ของคุณและทำลายตัวแทนผู้ใช้ที่ดึงผู้อ้างอิงออกไป
Mark Amery

@MarkAmery ทุกอย่างขึ้นอยู่กับสิ่งที่คุณพยายามป้องกันแน่นอน แต่การใช้ส่วนหัว http เฉพาะไคลเอ็นต์โดยรวมแล้วไม่ใช่รูปแบบความปลอดภัยที่แข็งแกร่งมาก
Seldaek

23

สิ่งที่ฉันพบได้ดีที่สุดคือโทเค็น CSRF และบันทึกไว้ในเซสชันสำหรับลิงก์ที่คุณต้องตรวจสอบผู้อ้างอิง

ดังนั้นหากคุณกำลังสร้างการโทรกลับ FB มันจะมีลักษณะดังนี้:

$token = uniqid(mt_rand(), TRUE);
$_SESSION['token'] = $token;
$url = "http://example.com/index.php?token={$token}";

จากนั้น index.php จะมีลักษณะดังนี้:

if(empty($_GET['token']) || $_GET['token'] !== $_SESSION['token'])
{
    show_404();
} 

//Continue with the rest of code

ฉันรู้จักไซต์ที่ปลอดภัยซึ่งเทียบเท่ากับหน้าเว็บที่ปลอดภัยทั้งหมด


1
ลิงค์สำหรับข้อมูลเพิ่มเติมเกี่ยวกับโทเค็น CSRF: en.wikipedia.org/wiki/Cross-site_request_forgery
We0

7
แน่ใจหรือว่าเป็น$_GET['token'] == $_SESSION['token']ไม่ใช่$_GET['token'] !== $_SESSION['token']?
Timo Huovinen

17

ใช้$ _SERVER ['HTTP_REFERER']

ที่อยู่ของเพจ (ถ้ามี) ซึ่งอ้างถึงตัวแทนผู้ใช้ไปยังเพจปัจจุบัน สิ่งนี้กำหนดโดยตัวแทนผู้ใช้ ตัวแทนผู้ใช้บางรายเท่านั้นที่จะตั้งค่านี้และบางส่วนมีความสามารถในการแก้ไข HTTP_REFERER เป็นคุณลักษณะ ในระยะสั้นไม่สามารถเชื่อถือได้จริงๆ

if (!empty($_SERVER['HTTP_REFERER'])) {
    header("Location: " . $_SERVER['HTTP_REFERER']);
} else {
    header("Location: index.php");
}
exit;

0

ไม่มีวิธีที่เชื่อถือได้ในการตรวจสอบสิ่งนี้ อยู่ภายใต้มือของลูกค้าที่จะบอกคุณได้ว่ามาจากไหน คุณอาจนึกภาพว่าใช้คุกกี้หรือข้อมูลเซสชันที่ใส่เฉพาะบางหน้าในเว็บไซต์ของคุณ แต่การทำเช่นนั้นจะทำให้ประสบการณ์การใช้งานบุ๊กมาร์กของผู้ใช้เสียไป


0

เรามีตัวเลือกเดียวที่เหลือหลังจากอ่านปัญหาผู้อ้างอิงปลอมทั้งหมดนั่นคือหน้าเว็บที่เราต้องการติดตามในฐานะผู้อ้างอิงควรถูกเก็บไว้ในเซสชันและเมื่อเรียกว่า ajax จากนั้นตรวจสอบในเซสชันหากมีค่าหน้าผู้อ้างอิงและดำเนินการอื่น ๆ ที่ชาญฉลาดไม่ หนังบู๊.

ในทางกลับกันในขณะที่เขาขอเพจอื่นใด ๆ ให้กำหนดค่าเซสชันผู้อ้างอิงเป็น null

โปรดจำไว้ว่าตัวแปรเซสชันถูกตั้งค่าตามคำขอเพจความปรารถนาเท่านั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.