จะหยุดโค้ดที่เป็นอันตรายไม่ให้ปลอมแปลงส่วนหัว "Origin" เพื่อใช้ประโยชน์จาก CORS ได้อย่างไร


143

วิธีที่ผมเข้าใจมันถ้าสคริปต์ฝั่งไคลเอ็นต์ที่ทำงานบนหน้าจาก foo.com ต้องการที่จะขอข้อมูลจาก bar.com ในการร้องขอนั้นจะต้องระบุส่วนหัวและบาร์จะต้องตอบสนองด้วยOrigin: http://foo.comAccess-Control-Allow-Origin: http://foo.com

มีอะไรที่จะหยุดโค้ดที่เป็นอันตรายจากเว็บไซต์ roh.com จากการปลอมแปลงส่วนหัวOrigin: http://foo.comเพื่อขอหน้าเว็บจากแถบ


2
ผมเชื่อว่าประเด็นก็คือว่าโดเมนเดิมหน้าจะมาจาก (ที่นี่foo.com) จะสามารถให้Access-Control-Allow-Originส่วนหัวหรืออื่น ๆ bar.comที่เบราว์เซอร์ไม่อนุญาตให้มีการร้องขอไปยัง
Chris Hayes

2
การอ่านโพสต์นี้ช่วยให้ฉันเข้าใจกระบวนการ cors ระหว่างเบราว์เซอร์เซิร์ฟเวอร์ต้นทางและเซิร์ฟเวอร์เป้าหมายได้อย่างแท้จริง html5rocks.com/th/tutorials/cors
brendonparker

5
@ChrisHayes นั่นไม่ใช่วิธีการทำงานของ CORS เลย คุณสามารถอ่านข้อมูลเพิ่มเติมได้อีกเล็กน้อยโดยดูข้อมูลจำเพาะหรือหน้าวิกิ MDN ที่ยอดเยี่ยมในหัวข้อนี้
Ray Nicholus

1
@brendonparker ใช่นั่นเป็นบทความที่ยอดเยี่ยม ผู้เขียนที่ตอบคำถามจำนวนมากในดังนั้น ธ และยังรักษาenable-cors.org
Ray Nicholus

4
@RayNicholus น่าสนใจฉันเห็นได้ชัดว่าปิดทาง ขอบคุณสำหรับลิงค์ ตัดสินโดยการโหวตในความคิดเห็นของฉันฉันไม่ใช่คนเดียวที่ทุกข์ทรมานภายใต้ความหลงผิดนี้ ฉันหวังว่าสองคนนั้นจะกลับมาและเรียนรู้ (และลบคะแนนโหวตออก!)
Chris Hayes

คำตอบ:


149

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

ข้อควรจำ: CORS ไม่ใช่ความปลอดภัย อย่าพึ่งพา CORS เพื่อรักษาความปลอดภัยให้กับไซต์ของคุณ หากคุณกำลังให้บริการข้อมูลที่มีการป้องกันให้ใช้คุกกี้หรือโทเค็น OAuth หรือสิ่งอื่นที่ไม่ใช่Originส่วนหัวเพื่อรักษาความปลอดภัยของข้อมูลนั้น Access-Control-Allow-Originหัวในล ธ เพียงคำสั่งซึ่งต้นกำเนิดควรจะได้รับอนุญาตให้ทำการร้องขอข้ามกำเนิด อย่าพึ่งหวังอะไรมาก


3
สิ่งนี้เข้าท่ามาก หากเบราว์เซอร์ไม่อนุญาตให้ JavaScript แทนที่ส่วนหัว Origin ก็ไม่มีปัญหา หากคุณกำลังดำเนินการตามคำขอจากภายนอกเบราว์เซอร์คุณจะไม่มีคุกกี้ ฉันเดาว่าฉันสับสนเพราะในเอกสารทั้งหมดที่ฉันอ่านไม่มีที่ไหนบอกอย่างชัดเจนว่าไม่สามารถลบล้างส่วนหัว Origin ได้ ขอบคุณ!
Jay Lamont

41
หากมีใครต้องการสวมรอยบางอย่างก็สามารถทำได้ ใช้ภาษาสคริปต์ใด ๆ ที่พวกเขาสามารถสร้างคำขอ http Perl และ Python มีไลบรารี http ซึ่งทำให้ง่ายมาก ไลบรารีจะจัดเก็บและส่งคุกกี้ช่วยให้คุณสามารถเพิ่มส่วนหัวได้ตามอำเภอใจและให้ข้อมูลการแก้ไขจุดบกพร่องมากมาย ดังนั้นส่วนหัว CORS จึงเป็นเพียงการทำให้จาวาสคริปต์ที่เป็นอันตรายยากขึ้นในฟอรัมที่คุณอ่านเพื่อทำสิ่งที่น่ารังเกียจกับบัญชีธนาคารของคุณบนโดเมนอื่นเมื่อคุณลงชื่อเข้าใช้ทั้งในเบราว์เซอร์ของคุณ
Mnebuerquo

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

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

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

35

TLDR:ไม่มีอะไรหยุดโค้ดที่เป็นอันตรายจากการปลอมแปลงต้นทาง เมื่อเป็นเช่นนั้นเซิร์ฟเวอร์ของคุณจะไม่มีทางรู้เรื่องนี้และจะดำเนินการตามคำขอ บางครั้งคำขอเหล่านั้นมีราคาแพง ดังนั้นอย่าใช้ CORS แทนการรักษาความปลอดภัยทุกประเภท


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

สิ่งแรกที่ฉันพบคือOriginส่วนหัวเป็นชื่อส่วนหัวที่ต้องห้ามของ HTTP ซึ่งไม่สามารถแก้ไขโดยใช้โปรแกรมได้ ซึ่งหมายความว่าคุณสามารถแก้ไขได้ในเวลาประมาณ 8 วินาทีโดยใช้การปรับเปลี่ยนส่วนหัวสำหรับ Google Chrome

เพื่อทดสอบสิ่งนี้ฉันตั้งค่าโดเมนไคลเอนต์สองโดเมนและโดเมนเซิร์ฟเวอร์หนึ่งโดเมน ฉันรวมรายการที่อนุญาตพิเศษของ CORS ไว้บนเซิร์ฟเวอร์ซึ่งอนุญาตให้มีการร้องขอ CORS จากไคลเอนต์ 1 แต่ไม่ใช่จากไคลเอนต์ 2 ฉันทดสอบไคลเอนต์ทั้งสองและแน่นอนว่าคำขอ CORS ของไคลเอ็นต์ 1 ประสบความสำเร็จในขณะที่ไคลเอนต์ 2 ล้มเหลว

จากนั้นฉันก็หลอกOriginส่วนหัวของไคลเอนต์ 2 เพื่อให้ตรงกับไคลเอนต์ 1 เซิร์ฟเวอร์ได้รับOriginส่วนหัวที่ปลอมแปลงและผ่านการตรวจสอบรายการที่อนุญาต (หรือล้มเหลวหากคุณเป็นผู้ชายที่ว่างเปล่าครึ่งแก้ว) หลังจากนั้นเซิร์ฟเวอร์ก็ดำเนินการตามหน้าที่โดยใช้ทรัพยากรทั้งหมดที่ออกแบบมาเพื่อใช้งาน (การโทรฐานข้อมูลการส่งอีเมลราคาแพงการส่งข้อความ SMS ที่มีราคาแพงกว่าเป็นต้น) เมื่อเสร็จแล้วเซิร์ฟเวอร์ก็ส่งAccess-Control-Allow-Originส่วนหัวที่ปลอมแปลงกลับไปยังเบราว์เซอร์อย่างมีความสุข

เอกสารที่ฉันอ่านระบุว่าAccess-Control-Allow-Originค่าที่ได้รับต้องตรงกับOriginค่าที่ส่งในคำขอทุกประการ มันตรงกันดังนั้นฉันจึงแปลกใจเมื่อเห็นข้อความต่อไปนี้ใน Chrome:

XMLHttpRequest ไม่สามารถโหลดhttp://server.dev/testได้ ส่วนหัว "Access-Control-Allow-Origin" มีค่าhttp://client1.dev ที่ไม่เท่ากับต้นทางที่ให้มา Origin http://client2.dev จึงไม่อนุญาตให้เข้าถึง

เอกสารที่ฉันอ่านดูเหมือนจะไม่ถูกต้อง แท็บเครือข่ายของ Chrome แสดงทั้งส่วนหัวของคำขอและการตอบกลับอย่างชัดเจนhttp://client1.devแต่คุณจะเห็นข้อผิดพลาดที่ Chrome รู้ว่าต้นกำเนิดที่แท้จริงคืออะไรhttp://client2.devและปฏิเสธการตอบกลับอย่างถูกต้อง ซึ่งไม่สำคัญในตอนนี้เนื่องจากเซิร์ฟเวอร์ได้ยอมรับคำขอปลอมและใช้เงินของฉันไปแล้ว


2
@Nocturno ขอบคุณสำหรับตัวอย่าง ขอผมเพิ่มข้อสังเกต CORS เกี่ยวข้องกับคุณลักษณะด้านความปลอดภัยของเบราว์เซอร์ หากเบราว์เซอร์ที่ปลอดภัยถูกปรับเปลี่ยนจากสถานะดั้งเดิมนั่นอาจแปลได้ว่าเบราว์เซอร์อาจไม่มีคุณลักษณะด้านความปลอดภัย
Luka Žitnik

10
ไม่เก่งเลย มันคิดถึงจุดของ CORS โดยสิ้นเชิง หากคุณอยู่ในตำแหน่งที่จะสกัดกั้นคำขอที่มาจากเครื่องของผู้ใช้คุณสามารถอ่านคุกกี้ของพวกเขาติดตั้งคีย์ล็อกเกอร์ซอฟต์แวร์ป้องกันและภัยคุกคามอื่น ๆ ทั้งหมดได้ CORS มีไว้เพื่อปกป้องผู้ใช้ที่ซื่อสัตย์ที่ลงชื่อเข้าใช้ไซต์ A จากสคริปต์ที่เป็นอันตรายซึ่งถูกแทรกไปยังไซต์ B สคริปต์บนไซต์ B (ซึ่งอาจเป็นตัวอย่างของ Javascript ในโพสต์ในฟอรัมที่ไม่ได้รับการหลีกเลี่ยงอย่างถูกต้องโดยไซต์ B) การดำเนินการบนไซต์ A ภายใต้บัญชีของผู้ใช้ (เช่นลบเนื้อหาเป็นต้น) โดยใช้คุกกี้เซสชันจากไซต์ A.
Stijn de Witt

3
สิ่งนี้เรียกว่าการเขียนสคริปต์ข้ามไซต์และหากไม่มี CORS สามารถทำได้โดยไม่จำเป็นต้องควบคุมเครื่องของผู้ใช้ นั่นคือประเด็นทั้งหมด ไม่จำเป็นต้องมีการควบคุมเครื่องของผู้ใช้เนื่องจากเมื่อทำการร้องขอไปยังไซต์เบราว์เซอร์ที่ใช้ในการเพิ่มคุกกี้เซสชันลงในคำขอโดยอัตโนมัติดังนั้นจึงดูเหมือนเป็นคำขอที่ถูกต้องจากผู้ใช้เองเมื่อในความเป็นจริงมันมาจากสคริปต์ในบางส่วน เว็บไซต์. นโยบายแหล่งกำเนิดเดียวกันป้องกันและ CORS ถูกใช้เพื่ออนุญาตพิเศษโดเมนที่ควรได้รับการเข้าถึงแม้ว่าจะอยู่ในต้นทางที่แตกต่างกัน
Stijn de Witt

3
@Nocturno ใช่ฉันอาจจะหยาบคายเกินไปขอโทษด้วย จุดเดิมของคุณคือ นโยบายแหล่งกำเนิดเดียวกันเป็นคุณลักษณะด้านความปลอดภัยของเบราว์เซอร์และ CORS เป็นกลไกในการลดความปลอดภัยนั้นโดยการอนุญาตบางโดเมน OP จำเป็นต้องเข้าใจว่าการปลอมแปลงส่วนหัว Origin นั้นไม่สามารถทำได้จริงในฐานะ 'การโจมตี' เนื่องจากไม่ได้นำสิ่งที่ไม่สามารถมีมาให้คุณได้เช่น curl
Stijn de Witt

3
@ Nocturno ฉันคิดว่าคำกล่าวเปิดของคุณทำให้เข้าใจผิดไปหน่อย There's nothing stopping malicious code from spoofing the origin-> ใช่มี, JavaScript Originไม่สามารถตั้งค่า ใช่ผู้ใช้สามารถปรับเปลี่ยนเบราว์เซอร์ / ใช้มือเล่นเพื่อเปลี่ยนจุดเริ่มต้นได้ แต่นั่นไม่ใช่สิ่งที่ CORS ปกป้อง เว็บไซต์ที่ควบคุมโดยผู้โจมตีไม่สามารถเปลี่ยน Origin ได้ซึ่งเป็นสิ่งสำคัญทั้งหมด
RJFalconer

14

เพียงแค่สรุปความอ่อนน้อมถ่อมตน:

ถาม:นโยบายแหล่งกำเนิดเดียวกัน (SOP) บังคับใช้กับเบราว์เซอร์เท่านั้นหรือไม่
ตอบ:ใช่ สำหรับการโทรทั้งหมดที่คุณโทรภายในเบราว์เซอร์เบราว์เซอร์จะใช้ SOP อย่างแน่นอน เซิร์ฟเวอร์อาจตรวจสอบที่มาของคำขอหรือไม่ก็ได้

ถาม:หากคำขอไม่เป็นไปตาม SOP เบราว์เซอร์จะบล็อกหรือไม่
ตอบ:ไม่ได้อยู่นอกเหนืออำนาจของเบราว์เซอร์ เบราว์เซอร์เพียงส่งคำขอข้ามแหล่งที่มาและรอการตอบสนองเพื่อดูว่าการโทรนั้นส่งสัญญาณโดยเซิร์ฟเวอร์ผ่านAccess-Control- * ส่วนหัวหรือไม่ หากเซิร์ฟเวอร์ไม่ส่งกลับAccess-Control-Allow-Originส่วนหัวไม่สะท้อนต้นกำเนิดของผู้โทรกลับหรือไม่ส่งกลับไป*ที่ส่วนหัวสิ่งที่เบราว์เซอร์จะทำคือละเว้นจากการให้การตอบสนองต่อผู้โทร

ถาม:หมายความว่าฉันไม่สามารถสวมรอยได้Originใช่หรือไม่?
ตอบ:ในเบราว์เซอร์และการใช้สคริปต์คุณไม่สามารถลบล้างได้Originเนื่องจากอยู่ในการควบคุมของเบราว์เซอร์ อย่างไรก็ตามหากคุณต้องการแฮ็คตัวเองคุณสามารถแก้ไขการโทรที่ออกจากเบราว์เซอร์ของคุณได้โดยใช้ส่วนขยายของเบราว์เซอร์หรือเครื่องมืออื่น ๆ ที่คุณติดตั้งบนเครื่องของคุณ นอกจากนี้คุณยังสามารถออกHTTPสายโดยใช้curl, Python, C#ฯลฯ และปรับเปลี่ยนOriginส่วนหัวเพื่อหลอกลวงเซิร์ฟเวอร์

ถาม:ถ้าฉันสามารถหลอกล่อเซิร์ฟเวอร์โดยการแก้ไขOriginได้หมายความว่าCORSไม่ปลอดภัยหรือไม่?
A: CORS per se เงียบเกี่ยวกับความปลอดภัยนั่นคือการพิสูจน์ตัวตนและการอนุญาตคำขอ ขึ้นอยู่กับเซิร์ฟเวอร์ที่จะตรวจสอบคำขอและรับรองความถูกต้อง / อนุญาตโดยกลไกใด ๆ ที่ทำงานด้วยเช่นคุกกี้และส่วนหัว ต้องบอกว่ามันสามารถปกป้องเราได้อีกเล็กน้อยในกรณีที่มีการโจมตีเช่น XSS:

ตัวอย่าง: สมมติว่าคุณได้ลงชื่อเข้าใช้เว็บไซต์ของคุณและสคริปต์ที่เป็นอันตรายพยายามส่งคำขอไปยังเว็บไซต์ธนาคารของคุณเพื่อสอบถามยอดเงินของคุณ: การโจมตีXSS ที่สะท้อนกลับ เว็บไซต์ธนาคารของคุณเชื่อถือข้อมูลรับรองที่มาจาก (ในนามของ) เว็บไซต์ของคุณดังนั้นคำขอจึงได้รับการตรวจสอบสิทธิ์และการHTTPตอบสนองที่มุ่งเป้าไปที่รหัสที่เป็นอันตรายจะได้รับการออก หากเว็บไซต์ธนาคารของคุณไม่สนใจเกี่ยวกับการแบ่งปันปลายทางกับแหล่งที่มาอื่น ๆ ก็จะไม่รวมถึงAccess-Control-Allow-Originส่วนหัวในการตอบกลับ ตอนนี้เมื่อมาถึงของคำขอเบราว์เซอร์จะทราบว่าคำขอนั้นเป็นคำขอข้ามต้นทาง แต่การตอบกลับไม่ได้แสดงว่าเซิร์ฟเวอร์ยินดีที่จะแบ่งปันทรัพยากร (ในที่นี้คือจุดสิ้นสุดของแบบสอบถามยอดคงเหลือ) กับเว็บไซต์ของคุณ ดังนั้นมันจึงหยุดการไหลดังนั้นผลลัพธ์ที่ส่งกลับจะไม่ไปถึงโค้ดที่เป็นอันตราย


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