ความเสี่ยงด้านความปลอดภัยของการตั้งค่า Access-Control-Allow-Origin คืออะไร?


124

เมื่อเร็ว ๆ นี้ฉันต้องตั้งค่าAccess-Control-Allow-Originเป็น*เพื่อให้สามารถโทร ajax ข้ามโดเมนย่อยได้
ตอนนี้ฉันอดไม่ได้ที่จะรู้สึกว่ากำลังทำให้สภาพแวดล้อมเสี่ยงต่อความปลอดภัย
โปรดช่วยฉันด้วยถ้าฉันทำผิด

คำตอบ:


69

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

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

สิ่งนี้ก่อให้เกิดความเสี่ยงด้านความปลอดภัยโดยเฉพาะอย่างยิ่งหากคุณอนุญาตให้ใช้ทรัพยากรร่วมกันไม่เพียง แต่สำหรับทรัพยากรที่เลือกเท่านั้น แต่สำหรับทุกทรัพยากร ในบริบทนี้คุณควรดูว่าเมื่อไรจึงจะปลอดภัยในการเปิดใช้งาน CORS .


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

1
@Gumbo เนื้อหาคงที่ล่ะ? (เช่นเนื้อหา cdn แบบคงที่เช่น javascripts, css, static html เป็นต้น) มีปัญหาด้านความปลอดภัยในการตั้งค่าAccess-Control-Allow-Origin: *หรือไม่? จะไม่มี nogin ฯลฯ เป็นสาธารณะสำหรับทุกคน?
Umut Benzer

2
@UmutBenzer ไม่เป็นไร
Gumbo

25
อันที่จริงคำตอบนี้ไม่ถูกต้องตามมาตรฐาน CORS ปัจจุบัน : "สตริง" * "ไม่สามารถใช้กับทรัพยากรที่รองรับข้อมูลประจำตัวได้" ดังนั้นคุณจึงไม่สามารถบังคับคำขอให้ใช้การพิสูจน์ตัวตนชั่วคราวในรูปแบบของคุกกี้การตรวจสอบสิทธิ์ HTTP ที่แคชไว้หรือใบรับรอง SSL ของไคลเอ็นต์ อย่างไรก็ตามหากเว็บไซต์ดังกล่าวใช้พื้นที่จัดเก็บในตัวเครื่องสำหรับการตรวจสอบสิทธิ์นั่นอาจเป็นปัญหาได้
Niklas B.

2
@NiklasB: ฉันลองใช้สถานการณ์นี้แล้ว Chrome ทำตามมาตรฐาน CORS ตามที่คุณได้กล่าวไว้ เช่นสตริง " " ไม่รองรับคำขอข้อมูลรับรอง นี่คือสิ่งที่ Chrome รายงาน: "XMLHttpRequest ไม่สามารถโหลดlocalhost: 12346 / helloไม่สามารถใช้สัญลักษณ์แทน"ในส่วนหัว "Access-Control-Allow-Origin" เมื่อค่าสถานะข้อมูลรับรองเป็นจริง Origin " localhost: 12345 " จึงไม่ได้รับอนุญาตให้เข้าถึงโหมดหนังสือรับรองของ XMLHttpRequest ถูกควบคุมโดยแอตทริบิวต์ withCredentials "
factotum

37

Access-Control-Allow-Origin: *มีความปลอดภัยโดยสิ้นเชิงที่จะเพิ่มลงในทรัพยากรใด ๆเว้นแต่ทรัพยากรนั้นจะมีข้อมูลส่วนตัวที่ได้รับการปกป้องโดยสิ่งอื่นที่ไม่ใช่ข้อมูลรับรองมาตรฐาน (คุกกี้, การรับรองความถูกต้องพื้นฐาน, ใบรับรองไคลเอ็นต์ TLS)

เช่น: ข้อมูลที่ได้รับการปกป้องโดยคุกกี้นั้นปลอดภัย

ลองนึกภาพhttps://example.com/users-private-dataซึ่งอาจเปิดเผยข้อมูลส่วนตัวขึ้นอยู่กับสถานะการเข้าสู่ระบบของผู้ใช้ สถานะนี้ใช้คุกกี้เซสชัน มันปลอดภัยที่จะเพิ่มAccess-Control-Allow-Origin: *ให้กับทรัพยากรนี้เป็นส่วนหัวนี้จะช่วยให้สามารถเข้าถึงการตอบสนองถ้าขอจะทำโดยไม่ต้องคุกกี้และคุกกี้จะต้องได้รับข้อมูลส่วนตัว ด้วยเหตุนี้จึงไม่มีข้อมูลส่วนตัวรั่วไหล

เช่น: ข้อมูลที่ป้องกันโดยตำแหน่ง / IP / เครือข่ายภายในไม่ปลอดภัย (น่าเสียดายที่มักเกิดกับอินทราเน็ตและเครื่องใช้ภายในบ้าน):

ลองนึกภาพhttps://intranet.example.com/company-private-dataซึ่งเปิดเผยข้อมูลของ บริษัท เอกชน แต่จะเข้าถึงได้ก็ต่อเมื่อคุณอยู่ในเครือข่าย wifi ของ บริษัท มันไม่ปลอดภัยที่จะเพิ่มAccess-Control-Allow-Origin: *ให้กับทรัพยากรนี้มันได้รับการคุ้มครองโดยใช้สิ่งอื่นนอกเหนือจากข้อมูลประจำตัวของมาตรฐาน มิฉะนั้นสคริปต์ที่ไม่ดีอาจใช้คุณเป็นช่องสัญญาณไปยังอินทราเน็ต

หลักการง่ายๆ

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


ควร "เนื่องจากอนุญาตเฉพาะคำขอที่ไม่มีคุกกี้" เป็น "เนื่องจากอนุญาตเฉพาะคำขอที่มีคุกกี้เท่านั้น"
DJCordhose

3
@DJCordhose ไม่มี. Access-Control-Allow-Origin: *อนุญาตเฉพาะคำขอที่ไม่มีคุกกี้ ฉันได้แก้ไขคำตอบเพื่อชี้แจงเล็กน้อย
JaffaTheCake

อะไรคือความแตกต่างระหว่าง "*" และกรณีที่ไม่มีส่วนหัวนี้เลย มันเหมือนกันไหม?
Nigrimmist

ฉันจะชอบถ้า "มิฉะนั้นสคริปต์ที่ไม่ดีอาจใช้คุณเป็นอุโมงค์สู่อินทราเน็ต" สามารถอธิบายเพิ่มเติมได้
Sam Rueby

@Nigrimmist จากนั้นคำขอ preflight จะล้มเหลวและการเข้าถึงทรัพยากรจะถูกบล็อก
iamareebjamal

9

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

จุดสิ้นสุดของเซิร์ฟเวอร์ไม่ได้ตรวจสอบว่า "ต้นทาง" คืออะไรเมื่อส่งคืนการตอบกลับ เพียงแค่เพิ่มส่วนหัว http เป็นเบราว์เซอร์ (ส่วนท้ายไคลเอ็นต์) ซึ่งส่งคำขอที่ตัดสินใจอ่านส่วนหัวการควบคุมการเข้าถึงและดำเนินการตามนั้น โปรดทราบว่าในกรณีของ XHR อาจใช้คำขอ 'OPTIONS' พิเศษเพื่อขอส่วนหัวก่อน

ดังนั้นใครก็ตามที่มีความสามารถในการเขียนสคริปต์อย่างสร้างสรรค์สามารถเพิกเฉยต่อส่วนหัวทั้งหมดได้ไม่ว่าจะตั้งค่าอะไรก็ตาม

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


ตอนนี้เพื่อตอบคำถามจริง

ฉันอดไม่ได้ที่จะรู้สึกว่ากำลังทำให้สภาพแวดล้อมเสี่ยงต่อความปลอดภัย

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


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

3
ใช่การตั้งค่าAccess-Control-Allow-Origin *บนเว็บไซต์ที่เป็นอันตรายซึ่งโฮสต์สคริปต์เพื่อขโมยรหัสผ่านนั้นไม่ควรอย่างยิ่ง :-)
commonpike

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

5
@commonpike ... ผู้ใช้. อีกวิธีหนึ่งคุณอาจแค่เยี่ยมชมไซต์ของฉัน (ซึ่งอาจเป็นไซต์ธรรมดาโดยไม่มีอะไรน่าสงสัย ... อาจเป็นไซต์ที่ถูกต้องตามกฎหมายจริงที่ถูกขโมยไป!) แต่ JavaScript บางตัวที่ส่งคำขอ HTTP ไปยังธนาคารของคุณเพื่อโอนบางส่วน เงินเข้าบัญชีของฉัน ธนาคารไม่ทราบความแตกต่างระหว่างคำขอจากหน้าหรือคำขอจากหน้าอื่น ๆ ทั้งสองมีคุกกี้ที่ทำให้คำขอประสบความสำเร็จ
Brad

3
@commonpike ขอยกตัวอย่างทั่วไป ... สิ่งที่เกิดขึ้นตลอดเวลา สมมติว่าคุณมีเราเตอร์ทั่วไปในบ้านเช่น Linksys WRT54g หรืออะไรสักอย่าง สมมติว่าเราเตอร์อนุญาตการร้องขอข้ามแหล่งกำเนิด สคริปต์บนหน้าเว็บของฉันสามารถส่งคำขอ HTTP ไปยังที่อยู่ IP ของเราเตอร์ทั่วไป (เช่น192.168.1.1) และกำหนดค่าเราเตอร์ของคุณใหม่เพื่อให้สามารถโจมตีได้ มันยังสามารถใช้เราเตอร์ของคุณโดยตรงเป็น DDoS node (เราเตอร์ส่วนใหญ่มีหน้าทดสอบที่อนุญาตให้มีการ ping หรือการตรวจสอบเซิร์ฟเวอร์ HTTP แบบง่ายซึ่งสามารถใช้ในทางที่ผิดได้)
Brad

6

นี่คือ 2 ตัวอย่างที่โพสต์เป็นความคิดเห็นเมื่อสัญลักษณ์แทนมีปัญหาจริงๆ:

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

- แบรด

สมมติว่าคุณมีเราเตอร์ทั่วไปในบ้านเช่น Linksys WRT54g หรืออะไรสักอย่าง สมมติว่าเราเตอร์อนุญาตการร้องขอข้ามแหล่งกำเนิด สคริปต์บนหน้าเว็บของฉันสามารถส่งคำขอ HTTP ไปยังที่อยู่ IP ของเราเตอร์ทั่วไป (เช่น 192.168.1.1) และกำหนดค่าเราเตอร์ของคุณใหม่เพื่อให้สามารถโจมตีได้ มันยังสามารถใช้เราเตอร์ของคุณโดยตรงเป็น DDoS node (เราเตอร์ส่วนใหญ่มีหน้าทดสอบที่อนุญาตให้มีการ Ping หรือการตรวจสอบเซิร์ฟเวอร์ HTTP แบบง่ายสิ่งเหล่านี้สามารถใช้ในทางที่ผิดได้)

- แบรด

ฉันรู้สึกว่าความคิดเห็นเหล่านี้ควรเป็นคำตอบเพราะพวกเขาอธิบายปัญหาด้วยตัวอย่างชีวิตจริง


8
ยกเว้นจะใช้ไม่ได้ "สตริง" * "ไม่สามารถใช้กับทรัพยากรที่รองรับข้อมูลรับรอง" w3.org/TR/cors/#resource-requests
bayo

@bayotop เบราว์เซอร์แยกความแตกต่างระหว่างหน้าที่ต้องมีการตรวจสอบสิทธิ์และหน้าที่มีข้อมูลอื่นในส่วนหัวอย่างไร
60

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

2
@wedstrom แฟล็กถูกกำหนดโดยผู้ที่ร้องขอ อย่างไรก็ตามสถานการณ์ข้างต้นเป็นตัวอย่างของการโจมตี CSRF การปล่อยให้ต้นกำเนิด '*' ไม่ทำให้คุณเสี่ยงมากขึ้นถ้าคุณเป็นอยู่แล้ว (อาจจะน้อยนิดในบางกรณี) ในกรณีส่วนใหญ่คุณสามารถส่งคำขอข้ามไซต์ที่เป็นอันตรายได้โดยใช้แบบฟอร์มดังนั้น CORS จึงไม่สำคัญ ในกรณีที่คุณจำเป็นต้องดำเนินการตามคำขอ AJAX คำขอก่อนการบินจะเกิดขึ้น (นี่คือจุดที่เบราว์เซอร์เข้ามาเมื่อ ACAO: '*' และ Access-Control-Allow-Credentials: 'true')
โย

0

ในสถานการณ์ที่เซิร์ฟเวอร์พยายามปิดการใช้งาน CORS โดยสมบูรณ์โดยตั้งค่าด้านล่างส่วนหัว

  • Access-Control-Allow-Origin: * (บอกเบราว์เซอร์ว่าเซิร์ฟเวอร์ยอมรับคำขอข้ามไซต์จาก ORIGIN ใด ๆ )

  • Access-Control-Allow-Credentials: true (บอกเบราว์เซอร์ว่าคำขอข้ามไซต์สามารถส่งคุกกี้ได้)

มีการใช้งานความล้มเหลวที่ปลอดภัยในเบราว์เซอร์ซึ่งจะส่งผลให้เกิดข้อผิดพลาดด้านล่าง

"Credential is not supported if the CORS header ‘Access-Control-Allow-Origin’ is ‘*’"

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

เนื่องจากไม่สามารถเปลี่ยนส่วนหัว ORIGIN โดยใช้จาวาสคริปต์ที่ทำงานบนเบราว์เซอร์ไซต์ที่เป็นอันตรายจึงไม่สามารถปลอมแปลงได้

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