MVC / REST ควรส่งคืน 403 หรือ 404 สำหรับทรัพยากรที่เป็นของผู้ใช้รายอื่นหรือไม่


33

เมื่อทำงานกับไซต์ที่ใช้ทรัพยากร (เช่นแอปพลิเคชัน MVC หรือบริการ REST) ​​เรามีสองตัวเลือกหลักเมื่อไคลเอ็นต์พยายามเข้าถึงGETทรัพยากรที่พวกเขาไม่สามารถเข้าถึง:

  • 403ซึ่งบอกว่าลูกค้าไม่ได้รับอนุญาต ; หรือ
  • 404ซึ่งบอกว่าไม่มีทรัพยากร(หรือไม่สามารถหาได้)

ภูมิปัญญาทั่วไปและการปฏิบัติทั่วไปดูเหมือนว่าจะตอบสนองกับความจริง - นั่นคือ 403 แต่ฉันสงสัยว่านี่เป็นสิ่งที่ถูกต้องหรือไม่

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

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

มีเหตุผลที่น่าสนใจที่จะไม่ส่งคืน 404 หรือไม่? นโยบาย 404 อาจมีผลข้างเคียงเชิงลบหรือไม่ ถ้าไม่เป็นเช่นนั้นทำไมการปฏิบัติจึงไม่เป็นเรื่องปกติ


1
เหตุผลที่น่าสนใจที่จะไม่ส่งคืน 404: หากบริการไม่ทำงานหรือมีข้อผิดพลาด / ข้อผิดพลาดในการตรวจสอบแล้วคุณจะได้รับ 404 แต่ลูกค้า / ผู้ใช้ / ผู้ทดสอบ / นักพัฒนา / สนับสนุน / ผู้พยายามวินิจฉัยปัญหาอาจไม่มีความคิด เกิดอะไรขึ้นจากข้อความแสดงข้อผิดพลาด
Steven Evers

@ Snorfus: นั่นเป็นจุดที่ดี - ฉันได้ตอบไว้แล้ว แม้ว่าจอชไม่อยู่แล้วเพิ่มความแตกต่างที่ดี ...
Aaronaught

สิ่งที่ควรทราบอีกประการหนึ่งก็คือเรื่องนี้: 404s ได้รับการปฏิบัติต่อเนื่องอย่างไร? มี CDN หรือแคชบ้างไหม? หากคุณต้องการแคชเหล่านั้นคุณอาจไม่ต้องการให้ "ผู้ใช้ไม่มีสิทธิ์" ที่จะถูกแคช 404 วินาที
pc1oad1etter

คำตอบ:


15

มีความเข้าใจผิดทั่วไป (และใช้ผิด) ที่เกี่ยวข้องกับ403 Forbidden: ไม่ควรให้อะไรเกี่ยวกับสิ่งที่เซิร์ฟเวอร์คิดเกี่ยวกับการร้องขอ มันออกแบบมาโดยเฉพาะที่จะพูด

ฉันได้รับสิ่งที่คุณร้องขอ แต่ฉันจะไม่จัดการกับคำขอไม่ว่าคุณจะพยายามทำอะไร ดังนั้นหยุดพยายาม

UA หรือไคลเอนต์ใด ๆควรตีความว่านั่นหมายความว่าคำขอจะไม่ทำงานและตอบสนองอย่างเหมาะสม

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

403เป็นในทางตรงกันข้ามกับ401 Authorization Requiredที่ไม่ให้ออกไปที่เซิร์ฟเวอร์จะจัดการการร้องขอตราบเท่าที่คุณส่งผ่านข้อมูลประจำตัวที่ถูกต้อง 403ซึ่งมักจะเป็นสิ่งที่ผู้คนคิดว่าเมื่อพวกเขาได้ยิน

นอกจากนี้ยังแตกต่างกับ404 Page Not Foundที่คนอื่นชี้ให้เห็นได้รับการออกแบบไม่เพียง แต่จะพูดว่า "ฉันไม่พบหน้านั้น" แต่เพื่อแนะนำให้ลูกค้าว่าเซิร์ฟเวอร์ไม่ได้เรียกร้องความสำเร็จหรือความล้มเหลวสำหรับการร้องขอในอนาคต

ด้วย401และ404เซิร์ฟเวอร์จะไม่พูดอะไรกับลูกค้าหรือ UA เกี่ยวกับวิธีที่พวกเขาควรดำเนินการ: พวกเขาสามารถพยายามโดยหวังว่าจะได้รับการตอบสนองที่แตกต่างกัน

ดังนั้น404เป็นวิธีที่เหมาะสมในการจัดการกับหน้าเว็บที่คุณไม่ต้องการที่จะแสดงให้ทุกคน แต่ไม่ต้องการที่จะให้ออกไปอะไรเกี่ยวกับเหตุผลที่คุณจะไม่แสดงในบางสถานการณ์

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

users/*นั่นคือสมมติว่าคุณเป็นตัวจัดการ ถ้าฉันรู้ว่าusers/foo, users/barและusers/baazการทำงานของเซิร์ฟเวอร์กลับ401, 403หรือ404สำหรับusers/quuxไม่ได้หมายความว่าฉันจะไม่ไปลองโดยเฉพาะอย่างยิ่งถ้าฉันมีเหตุผลที่จะเชื่อว่ามีเป็นquuxผู้ใช้ สถานการณ์ตัวอย่างมาตรฐานคือ Facebook: โปรไฟล์ของฉันเป็นแบบส่วนตัว แต่ความคิดเห็นของฉันเกี่ยวกับโปรไฟล์สาธารณะไม่ได้ ลูกค้าที่เป็นอันตรายรู้ว่าฉันมีอยู่แม้ว่าคุณจะกลับมา404ที่หน้าโปรไฟล์ของฉัน

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


4
คะแนนที่ดีเกี่ยวกับ 401 กับ 403 ฉันไม่เห็นด้วยกับข้อสรุปของงบของคุณใน 404 แน่นอนว่าในตัวอย่างของ Facebook คุณรู้อยู่แล้วว่าquuxมีอยู่จริง แต่มีไม่ได้เสมอไปเป็นหลักฐานภายนอกโดยเฉพาะอย่างยิ่งบนไซต์ที่ไม่ใช่สังคมที่ข้อมูลของลูกค้าเป็นจริงส่วนตัว ผู้ใช้ที่มีจมูกยาวหรือศัตรูในที่สุดก็อาจจะสามารถที่จะอนุมานว่าคุณกำลังโกหก แต่ไม่จำเป็นต้องซึ่งทรัพยากรที่คุณกำลังโกหกเกี่ยวกับ ฉันคิดว่าจุดสำคัญที่นี่เป็นจริงอย่ากังวลกับแหล่งข้อมูล 404 เว้นแต่จะไม่มีวิธีการค้นพบอื่น ๆ
Aaronaught

@Aaraught สิ่งนี้คือคุณต้องแน่ใจจริงๆว่ามีบางคนไม่สามารถเข้าใจได้ว่าเซิร์ฟเวอร์นั้นถูกหลอกลวงหรือไม่มีวิธีการค้นพบบางอย่างที่คุณยังไม่ได้ทำ คนฉลาดพอที่จะคิดออกและ ณ จุดนั้นรหัสสถานะไม่มีความหมาย

1
ฉันยังไม่ชัดเจนว่าบุคคลที่ฉลาดพอจะเข้าใจได้อย่างไรหากไม่มีการแบ่งปันข้อมูลระหว่างโปรไฟล์ผู้ใช้ ฉันเข้าใจว่าใครบางคนที่กำหนดแล้วจะรู้ว่า "โอ้ 404 จริง ๆ แล้วหมายความว่ามันอาจมีอยู่ แต่ฉันไม่สามารถเข้าถึงได้" - แต่สมมติว่าเซิร์ฟเวอร์ส่งคืนข้อผิดพลาดเดียวกันสำหรับทรัพยากรที่ไม่มีอยู่จริงอย่างแท้จริงบอกความแตกต่างระหว่างทรัพยากรที่ไม่มีอยู่จริงกับทรัพยากรที่มีอยู่หรือไม่
Aaronaught

@Aaronaught สิ่งเดียวที่บุคคลนั้นจะต้องรู้คือ URL ที่ควรมีอยู่ คุณอาจใช้ ID โปรไฟล์และเพิ่มพวกเขาในแบบหลอก (ดังนั้นบุคคลที่มี ID โปรไฟล์ที่ 3333 ไม่ได้หมายความว่ามีบุคคลที่มี ID โปรไฟล์เป็น 3332) แต่คนที่ตั้งใจจะคาดเดาได้บ้าง ขนาดตัวอย่างของ ID ที่ถูกต้อง ความล้มเหลวนั้นและแม้จะได้รับระบบที่ทำให้สมบูรณ์ที่ไม่มีข้อมูลเกี่ยวกับวิธีสร้าง URL สำหรับหน้าโปรไฟล์จะมีวิศวกรรมทางสังคมอยู่เสมอ

8

อ้างอิงจากRFC2616

10.4.4 403 สิ่งต้องห้าม

เซิร์ฟเวอร์เข้าใจคำขอ แต่ปฏิเสธที่จะปฏิบัติตาม การอนุญาตจะไม่ช่วยและไม่ควรทำซ้ำการร้องขอ หากวิธีการร้องขอไม่ได้เป็น HEAD และเซิร์ฟเวอร์ประสงค์ที่จะเปิดเผยต่อสาธารณะว่าทำไมคำขอไม่ได้รับการตอบสนองก็ควรอธิบายเหตุผลของการปฏิเสธในเอนทิตี หากเซิร์ฟเวอร์ไม่ต้องการให้ข้อมูลนี้พร้อมใช้งานสำหรับลูกค้าสามารถใช้รหัสสถานะ 404 (ไม่พบ) แทน

โปรดทราบด้วยว่าเมื่อเข้าถึงทรัพยากรที่ต้องห้ามการอนุญาตจะไม่ช่วยอะไร


ฉันรู้เรื่อง RFC แม้ว่าจะมีความคล้ายคลึงกับความเป็นจริงเล็กน้อย เกือบจะไม่มีเซิร์ฟเวอร์อธิบายเหตุผลสำหรับ 403 เกินกว่าประโยคแรกนั้น("เซิร์ฟเวอร์เข้าใจคำขอ แต่ปฏิเสธที่จะทำตามนั้น")และกรอบงาน MVC ส่วนใหญ่มีบางสิ่งที่คล้ายกับHttpUnauthorizedResultที่ตั้งใจจะใช้สำหรับทรัพยากรที่มีสิทธิพิเศษ . ฉันยังตระหนัก (ชัด) ว่าสามารถใช้404 แทน; คำถามของฉันคือควรใช้หรือไม่และควรพิจารณาสิ่งใดเมื่อตัดสินใจ
Aaronaught

@Aaraught: RFC ไม่เพียง แต่อนุญาตให้คุณใช้ 404 ก็แนะนำให้คุณโยน 404 เมื่อคุณไม่ต้องการรับรู้อะไร
โกหก

3
ไม่เป็นไร แต่เมื่อใดที่ฉันไม่ควรยอมรับอะไร หรือค่อนข้างฉันควรเมื่อไหร่ นั่นคือสาระสำคัญของคำถาม
Aaronaught

5

คุณควร ใช่แล้ว

คุณพูดด้วยตัวเองหักหลังให้น้อยที่สุด ถ้าฉันถูกโจมตีระบบและสังเกตว่าเซิร์ฟเวอร์ตอบสนองด้วยรหัส 403 ฉันจะมุ่งเน้นไปที่พวกเขาแทนที่จะย้ายไป ดีกว่าที่จะประกาศว่าไม่มีประตูแล้วก็ประกาศว่ามันจะถูกกันออกไป

ข้อเสียของการใช้ 404 คำร้องขอคือภายนอกจะปรากฏราวกับว่าไม่มีหน้าอยู่และอาจมีข้อขัดแย้งเมื่อเปรียบเทียบกับหน้าที่ควรจะมีอยู่ แต่หายไปแทน หากคุณไม่กังวลเกี่ยวกับโปรแกรมรวบรวมข้อมูลเว็บ (ระบบที่ผ่านการรับรองความถูกต้องควรถูกปฏิเสธอย่างสิ้นเชิง) คุณควรดำเนินการอย่างสมบูรณ์ API ทุกตัวที่ฉันจัดการเข้าถึงที่ไม่ได้รับอนุญาตในลักษณะเดียวกันและStackOverflow ก็เช่นกัน ไม่เห็นหน้านั้นใช่ไหม ผมมั่นใจว่ามันจะมีอยู่ถึงแม้จะอ้างว่าไม่ให้

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


เหตุผลที่น่าสนใจที่จะไม่ส่งคืน 404: หากบริการไม่ทำงานหรือมีข้อผิดพลาด / ข้อผิดพลาดในการตรวจสอบแล้วคุณจะได้รับ 404 แต่ลูกค้า / ผู้ใช้ / ผู้ทดสอบ / นักพัฒนา / สนับสนุน / ผู้พยายามวินิจฉัยปัญหาอาจไม่มีความคิด เกิดอะไรขึ้นจากข้อความแสดงข้อผิดพลาด

นักพัฒนาควรมีสิทธิ์เข้าถึงบันทึกซึ่งจะระบุถึงความพยายามในการเข้าถึงทรัพยากรที่มีการป้องกัน ลูกค้า / ผู้ใช้ / ผู้ทดสอบจะสร้างข้อเสนอแนะซึ่งในที่สุดก็จะตีนักพัฒนา

ปลอดภัยด้วยความสับสน ... จริงเหรอ?

นี่ไม่ใช่ความปลอดภัยโดยความสับสน คุณกำลังใช้ความคลุมเครือนอกเหนือจากมาตรการรักษาความปลอดภัยที่เหมาะสม

คำขอที่ถูกต้องที่ได้รับ "404" นั้นเป็นเพียงการเพิ่มความซับซ้อนและความสับสนที่ไม่จำเป็น

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


ปลอดภัยด้วยความสับสน ... จริงเหรอ? หากมีคนพยายามที่จะกระตุ้นบริการของคุณด้วยเจตนาร้ายพวกเขารู้อยู่แล้วว่ามี คำขอที่ถูกต้องที่ได้รับ "404" นั้นเป็นเพียงการเพิ่มความซับซ้อนและความสับสนที่ไม่จำเป็น
Steven Evers

4
@Snorfus: มีความแตกต่างที่ลึกซึ้งที่จะทำที่นี่ระหว่างการรักษาความปลอดภัยและความเป็นส่วนตัว ความเป็นส่วนตัวเกือบตามคำจำกัดความ "ด้วยความสับสน" สิ่งนี้มีความสำคัญอย่างยิ่งในบริบทของระบบฐานทรัพยากรเนื่องจากการดำรงอยู่หรือไม่มีอยู่ของทรัพยากรเป็นข้อมูลที่สำคัญ อาจมีข้อโต้แย้งด้านความปลอดภัยเช่นกันแม้ว่าฉันจะเป็นห่วงน้อยกว่าก็ตาม ผมจะชอบที่จะได้ยินเพิ่มเติมเกี่ยวกับเพิ่มความซับซ้อนนี้ คุณสามารถเข้าไปดูรายละเอียดนอกเหนือจากความคิดเห็นเริ่มต้นของคุณได้ไหม? (บางทีอาจจะเป็นคำตอบที่ครอบคลุมกว่านี้ไหมคุณถูก 404'ed 403s ถูกกัด)
Aaronaught

2
@Snorfus: ฉันยังต้องการที่จะเพิ่มเป็นภายหลังที่ป้องกันในเชิงลึกไม่ได้เช่นเดียวกับการรักษาความปลอดภัยจากความสับสน หลังหมายถึงว่าไม่มีอื่น ๆวิธีของการป้องกัน แต่การเพิ่มความสับสนให้กับระบบที่มีความปลอดภัยอยู่แล้วมักจะเป็นสิ่งที่ดี - ตราบใดที่มันไม่ทำให้เกิดปัญหาอื่น ๆ ในกรณีนี้มันเป็นระบบที่ได้รับการรักษาความปลอดภัยแล้วเนื่องจากยุค 404 ถูกปล่อยออกมาโดยรหัสการอนุญาต
Aaronaught

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

@Snorfus: ทรัพยากรเป็นส่วนตัวสำหรับลูกค้า - หรืออาจจะเป็นกลุ่ม - ไม่ใช่เพื่อทั้งโลก
Aaronaught

0

ขึ้นอยู่กับข้อมูลที่ได้รับจากรหัสสถานะ 403 หากคุณมี API ปลายทางที่ตอบสนองGET /myresource/{id}ด้วย 404 เมื่อทรัพยากรไม่มีอยู่แล้วรหัสสถานะที่ส่งคืนโดยปลายทางเมื่อทรัพยากรนั้นมีอยู่ แต่ไม่ได้รับอนุญาตให้ผู้ใช้ปัจจุบันขึ้นอยู่กับความสามารถในการคาดการณ์ของidพารามิเตอร์และจำนวนเงิน ของข้อมูลที่มีอยู่โดยตัวมันเอง

  • หากidเป็นฟิลด์ส่วนตัวเช่นที่อยู่อีเมลหรือหมายเลขบัญชีธนาคารก็ควรจะซ่อนอยู่หลัง 404 เสมอในกรณีของที่อยู่อีเมลสามารถป้องกันไม่ให้บอทสแปมรวบรวมรายการที่อยู่อีเมลที่ถูกต้องที่ลงทะเบียนในเว็บไซต์ของคุณ
  • หากidเป็นชื่อผู้ใช้สาธารณะไม่ต้องกังวลมีวิธีอื่นในการเข้าถึงข้อมูลนี้ (เช่นเพียงแค่เรียกดูหน้าฟอรัมของเว็บไซต์ของคุณ)
  • หากidเป็นตัวทึบ แต่เป็นตัวบ่งชี้ที่คาดเดาได้ (เช่นจำนวนเต็มเพิ่มอัตโนมัติ) คุณจะไม่ให้ข้อมูลใด ๆ แก่ผู้โจมตีซึ่งเขาไม่สามารถหาได้ด้วยวิธีอื่น ดังนั้นในความคิดของฉันมันปลอดภัยที่จะส่งคืนรหัสสถานะ 403
  • หากidเป็นตัวระบุทึบแสงและไม่แน่นอน (เช่น GUID แบบสุ่ม) คำถามจะละเอียดกว่านี้ โดยส่วนตัวฉันคิดว่าไม่มีปัญหาในการส่งคืนรหัสสถานะ 403 ข้อมูลนี้สามารถใช้ประโยชน์ได้หากมีจุดปลายที่มีข้อบกพร่องอีกจุดหนึ่งใน API ของคุณโดยใช้ ID นี้ แต่จุดบกพร่องที่แท้จริงคือจุดสิ้นสุดอื่นของคุณ

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

กลไกการรักษาความปลอดภัยไม่ควรเป็นเพียงแค่การเพิ่มความเร็วให้กับผู้โจมตีมิฉะนั้นมันจะไร้ประโยชน์ ในกรณีนี้อาจทำให้คุณไม่สามารถใช้คุณสมบัติอื่น ๆ ได้อย่างถูกต้อง (โปรแกรมรวบรวมข้อมูล, Web Application Firewall มองหารหัสสถานะ 403 ที่ผิดปกติเพื่อบล็อกผู้ใช้ ... )

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