2012-02-10 29 views
28

XMLHttpRequest s yêu cầu CORS hoạt động trên nhiều miền. Tương tự cho phông chữ web, kết cấu WebGL và một vài thứ khác. Nói chung tất cả các API mới dường như có hạn chế này.Tại sao API trình duyệt hạn chế yêu cầu miền chéo?

Tại sao?

Thật dễ dàng để phá vỡ: tất cả những gì cần là một proxy phía máy chủ đơn giản. Nói cách khác, mã phía máy chủ không bị cấm thực hiện các yêu cầu miền chéo; tại sao mã phía máy khách? Làm thế nào điều này cung cấp cho bất kỳ bảo mật, cho bất cứ ai?

Và nó rất không nhất quán: Tôi không thể XMLHttpRequest, nhưng tôi có thể <script src> hoặc <link rel> hoặc <img src> hoặc . Những gì hạn chế XHR vv thậm chí còn hoàn thành?

Trả lời

50

Nếu tôi ghé thăm một trang web độc hại, tôi muốn chắc chắn rằng:

  1. Nó không thể đọc cá nhân dữ liệu của tôi từ các trang web khác mà tôi sử dụng. Hãy suy nghĩ attacker.com đọc gmail.com
  2. Nó không thể thực hiện các hoạt động thay mặt tôi trên các trang web khác mà tôi sử dụng. Hãy nghĩ rằng attacker.com chuyển tiền từ tài khoản của tôi trên bank.com

Chính sách xuất xứ tương tự giải quyết vấn đề đầu tiên. Vấn đề thứ hai được gọi là giả mạo yêu cầu trang web chéo và không thể giải quyết được với các hạn chế miền chéo hiện tại.

Chính sách cùng một nguồn gốc là nói chung phù hợp với các quy tắc sau -

  • Nguyên tắc 1: Không cho phép bạn đọc bất cứ thứ gì từ một tên miền khác nhau
  • Quy tắc 2: Cho phép bạn viết bất cứ điều gì bạn muốn một tên miền khác, nhưng quy tắc số 1 sẽ không cho phép bạn đọc phản hồi.
  • Quy tắc 3: Bạn có thể tự do đưa ra yêu cầu GET cross-domain và yêu cầu POST, nhưng bạn không thể kiểm soát các tiêu đề HTTP

Hãy xem làm thế nào những điều khác nhau mà bạn đã liệt kê dòng lên đến các quy tắc trên:

  1. <img> thẻ cho phép bạn thực hiện yêu cầu HTTP, nhưng không có cách nào để đọc nội dung của hình ảnh khác ngoài việc chỉ hiển thị hình ảnh đó. Ví dụ: nếu tôi làm điều này <img src="http://bank.com/get/latest/funds"/>, yêu cầu sẽ được thực hiện (quy tắc 2). Nhưng không có cách nào để kẻ tấn công nhìn thấy số dư của tôi (quy tắc 1).

  2. <script> thẻ hoạt động chủ yếu như <img>. Nếu bạn làm điều gì đó như <script src="http://bank.com/get/latest/funds">, yêu cầu sẽ được thực hiện. Trình duyệt cũng sẽ cố gắng phân tích cú pháp phản hồi dưới dạng JavaScript và sẽ không thành công.

  3. Có một sự lạm dụng nổi tiếng là <script> thẻ được gọi là JSONP, nơi bạn kết hợp với máy chủ tên miền chéo để bạn có thể 'đọc' tên miền chéo. Nhưng nếu không có sự tham gia rõ ràng của máy chủ tên miền chéo, bạn không thể đọc phản hồi qua thẻ

  4. <link> cho biểu định kiểu hoạt động chủ yếu như <script> thẻ, ngoại trừ phản hồi được đánh giá là CSS. Nói chung, bạn không thể đọc phản hồi - trừ khi phản hồi bằng cách nào đó xảy ra là CSS được định dạng tốt.

  5. thực chất là một cửa sổ trình duyệt mới. Bạn không thể đọc HTML của iframe tên miền chéo. Ngẫu nhiên, bạn có thể thay đổi URL của iframe tên miền chéo, nhưng bạn không thể đọc URL. Hãy chú ý cách nó tuân theo hai quy tắc tôi đã đề cập ở trên.

  6. XMLHttpRequest là phương pháp linh hoạt nhất để thực hiện yêu cầu HTTP. Điều này hoàn toàn nằm trong sự kiểm soát của nhà phát triển; trình duyệt không làm bất cứ điều gì với phản hồi. Ví dụ: trong trường hợp <img>, <script> hoặc <link>, trình duyệt giả định một định dạng cụ thể và nói chung sẽ xác thực nó một cách thích hợp. Nhưng trong XHR, không có định dạng đáp ứng theo quy định. Vì vậy, các trình duyệt thực thi chính sách gốc giống nhau và ngăn bạn đọc phản hồi trừ khi trang web tên miền chéo cho phép bạn rõ ràng.

  7. Phông chữ qua font-face là một sự bất thường. AFAIK, chỉ Firefox yêu cầu hành vi chọn tham gia; các trình duyệt khác cho phép bạn sử dụng phông chữ giống như bạn sử dụng hình ảnh.

Tóm lại, chính sách gốc giống nhau là nhất quán. Nếu bạn tìm cách thực hiện yêu cầu tên miền chéo đọc phản hồi mà không có sự cho phép rõ ràng từ trang web tên miền chéo - bạn sẽ tạo tiêu đề trên toàn thế giới.

EDIT: Tại sao tôi không thể thực hiện tất cả điều này với proxy phía máy chủ?

Để gmail hiển thị dữ liệu được cá nhân hóa, nó cần cookie từ trình duyệt của bạn. Một số trang web sử dụng xác thực cơ sở HTTP, trong đó thông tin đăng nhập được lưu trữ trong trình duyệt.

Proxy phía máy chủ không thể truy cập vào cookie hoặc thông tin đăng nhập cơ bản của xác thực. Và như vậy, mặc dù nó có thể thực hiện một yêu cầu, máy chủ sẽ không trả về dữ liệu cụ thể của người dùng.

+1

Hmm ... Tôi đang bắt đầu kết nối các dấu chấm. Điều này chắc chắn là câu trả lời hữu ích nhất cho đến nay. Nhưng, bạn có thể mở rộng về lý do tại sao mã máy khách phát hành yêu cầu 'GET' tới gmail.com tệ hơn mã máy chủ không? Tôi nghĩ rằng tôi hiểu tại sao nhưng vì đây là một câu trả lời hoàn chỉnh, điều quan trọng là phải giải quyết câu hỏi "tại sao tôi không thể giải quyết vấn đề này với một proxy phía máy chủ". – Domenic

+2

@Domenic - Xem nội dung cập nhật của tôi. Khi mã phía máy khách thực hiện một yêu cầu, các cookie sẽ được truyền theo ngầm. Các cookie này cho phép máy chủ tên miền chéo xác định người dùng và do đó trả lại dữ liệu được cá nhân hóa. Proxy phía máy chủ sẽ không có quyền truy cập vào các cookie này, vì vậy nó không thể đọc dữ liệu cá nhân. –

+0

Tuyệt vời, cảm ơn bạn! Đặc biệt hữu ích khi bạn chỉ rõ cookie và thông tin xác thực cơ bản; Tôi chỉ nghĩ đến bánh quy. – Domenic

4

Hãy xem xét kịch bản này ...

  1. Bạn hãy vào trang web độc hại của tôi.
  2. Trang web của tôi tạo XHR cho trang web ngân hàng của bạn và yêu cầu biểu mẫu chuyển khoản ngân hàng.
  3. XHR đọc mã thông báo ngăn CSRF và POST biểu mẫu cùng với mã thông báo bảo mật và chuyển một khoản tiền vào tài khoản của tôi.
  4. (I) Lợi nhuận !!!

Nếu không có Chính sách xuất xứ giống nhau, bạn vẫn có thể POST biểu mẫu đó, nhưng bạn sẽ không thể yêu cầu mã thông báo CSRF ngăn CSRF.

Mã phía máy chủ không chạy trên máy tính của khách hàng.

+2

Thực ra, không. Chính sách gốc tương tự ngăn không cho * đọc từ * các trang web khác. Nó không ngăn chặn * ghi vào * các trang web khác. Nói chung, không có chính sách bảo mật nào của trình duyệt hiện tại ngăn chặn CSRF. –

+0

@SripathiKrishnan Tôi đã cập nhật bài đăng của mình để hy vọng làm cho nó rõ ràng hơn một chút. – alex

+0

Rất tiếc, xin lỗi. Tôi đã bỏ lỡ bit 'yêu cầu mã thông báo' trong câu trả lời của bạn. Tôi nghĩ rằng bạn có nghĩa là để nói cùng một chính sách gốc ngăn chặn CSRF. –

2

Vấn đề chính với XHR là họ không thể chỉ gửi yêu cầu nhưng bạn cũng có thể đọc câu trả lời. Gửi yêu cầu gần như tùy ý là đã có thể. Nhưng đọc phản hồi của họ thì không. Đó là lý do tại sao XHR gốc không cho phép bất kỳ yêu cầu xuất xứ chéo nào cả.

Sau đó, khi yêu cầu các yêu cầu xuất xứ chéo với XHR phát sinh, CORS được thiết lập để cho phép các yêu cầu gốc xuất phát trong các điều kiện cụ thể. Một điều kiện là các phương thức yêu cầu cụ thể, các trường tiêu đề yêu cầu và các yêu cầu có chứa thông tin xác thực người dùng yêu cầu một yêu cầu pref2 preflight mà khách hàng có thể kiểm tra xem máy chủ có cho phép yêu cầu hay không. Với điều này, máy chủ có khả năng hạn chế quyền truy cập vào các nguồn gốc cụ thể, nếu không thì bất kỳ nguồn gốc nào cũng có thể gửi yêu cầu.

+0

Phải, tôi hiểu cách CORS hoạt động, nhưng tại sao lại có thể đọc một câu trả lời nguy hiểm? – Domenic

+1

Mặc dù đó là tài liệu khởi tạo yêu cầu, nhưng đó là trình duyệt của người dùng thực sự gửi yêu cầu. Và trình duyệt sẽ gửi bất kỳ thông tin đăng nhập nào với nó như thể người dùng đã yêu cầu nó trực tiếp. Phản hồi có thể chứa thông tin nhạy cảm chỉ có thể truy cập được cho người dùng nhưng sau đó tập lệnh khởi tạo có thể truy cập. Đó là lý do tại sao XHR ban đầu không cho phép bất kỳ yêu cầu gốc nào. – Gumbo

+1

Nhưng bây giờ XHR 'mở rộng' (trước đây gọi là XHR cấp 2) cho phép yêu cầu xuất xứ chéo khi các quy tắc của CORS được tuân theo. – Gumbo

Các vấn đề liên quan