2016-09-12 23 views
11

Tôi đang chạy vào một CSRF lạ nơi tôi đang cố gắng truy cập vào một tập tin javascript được tải lên trên máy chủ đường ray của tôi. Tôi có một bộ điều khiển như:Rails Bảo vệ Từ Forgery với Javascript

class SomeController < ApplicationController 
    def show 
    some_path = "/some/js/file/on/disk.js" 
    send_file(some_path, type: "text/javascript", disposition: :inline) 
    end 
end 

Tuy nhiên khi điều hướng đến http://localhost:3000/somes/1 Tôi nhận được thông báo lỗi:

Security warning: an embedded tag on another site requested protected JavaScript. If you know what you're doing, go ahead and disable forgery protection on this action to permit cross-origin JavaScript embedding.

Extracted source (around line #225):

if marked_for_same_origin_verification? && non_xhr_javascript_response? 
     logger.warn CROSS_ORIGIN_JAVASCRIPT_WARNING if logger 
     raise ActionController::InvalidCrossOriginRequest, CROSS_ORIGIN_JAVASCRIPT_WARNING 
    end 
    end 

Lưu ý rằng tôi đang truy cập vào trang này trực tiếp có nghĩa là không có bố trí nên tôi không thể bao gồm mã thông báo CSRF trong bố cục của tôi.

Có điều gì cần được thực hiện khác để truy cập đúng tài nguyên này không?

EDIT: Mỗi yêu cầu nhận xét, tôi đã thêm Dấu vết đầy đủ bên dưới.

actionpack (4.2.6) lib/action_controller/metal/request_forgery_protection.rb:225:in verify_same_origin_request' activesupport (4.2.6) lib/active_support/callbacks.rb:432:in block in make_lambda' activesupport (4.2.6) lib/active_support/callbacks.rb:239:in block in halting' activesupport (4.2.6) lib/active_support/callbacks.rb:506:in block in call' activesupport (4.2.6) lib/active_support/callbacks.rb:506:in each' activesupport (4.2.6) lib/active_support/callbacks.rb:506:in call' activesupport (4.2.6) lib/active_support/callbacks.rb:92:in __run_callbacks__' activesupport (4.2.6) lib/active_support/callbacks.rb:778:in _run_process_action_callbacks' activesupport (4.2.6) lib/active_support/callbacks.rb:81:in run_callbacks' actionpack (4.2.6) lib/abstract_controller/callbacks.rb:19:in process_action' actionpack (4.2.6) lib/action_controller/metal/rescue.rb:29:in process_action' actionpack (4.2.6) lib/action_controller/metal/instrumentation.rb:32:in block in process_action' activesupport (4.2.6) lib/active_support/notifications.rb:164:in block in instrument' activesupport (4.2.6) lib/active_support/notifications/instrumenter.rb:20:in instrument' activesupport (4.2.6) lib/active_support/notifications.rb:164:in instrument' actionpack (4.2.6) lib/action_controller/metal/instrumentation.rb:30:in process_action' actionpack (4.2.6) lib/action_controller/metal/params_wrapper.rb:250:in process_action' activerecord (4.2.6) lib/active_record/railties/controller_runtime.rb:18:in process_action' actionpack (4.2.6) lib/abstract_controller/base.rb:137:in process' actionview (4.2.6) lib/action_view/rendering.rb:30:in process' actionpack (4.2.6) lib/action_controller/metal.rb:196:in dispatch' actionpack (4.2.6) lib/action_controller/metal/rack_delegation.rb:13:in dispatch' actionpack (4.2.6) lib/action_controller/metal.rb:237:in block in action' actionpack (4.2.6) lib/action_dispatch/routing/route_set.rb:74:in dispatch' actionpack (4.2.6) lib/action_dispatch/routing/route_set.rb:43:in serve' actionpack (4.2.6) lib/action_dispatch/journey/router.rb:43:in block in serve' actionpack (4.2.6) lib/action_dispatch/journey/router.rb:30:in each' actionpack (4.2.6) lib/action_dispatch/journey/router.rb:30:in serve' actionpack (4.2.6) lib/action_dispatch/routing/route_set.rb:817:in call' bullet (5.1.1) lib/bullet/rack.rb:12:in call' warden (1.2.6) lib/warden/manager.rb:35:in block in call' warden (1.2.6) lib/warden/manager.rb:34:in catch' warden (1.2.6) lib/warden/manager.rb:34:in call' rack (1.6.4) lib/rack/etag.rb:24:in call' rack (1.6.4) lib/rack/conditionalget.rb:25:in call' rack (1.6.4) lib/rack/head.rb:13:in call' actionpack (4.2.6) lib/action_dispatch/middleware/params_parser.rb:27:in call' actionpack (4.2.6) lib/action_dispatch/middleware/flash.rb:260:in call' rack (1.6.4) lib/rack/session/abstract/id.rb:225:in context' rack (1.6.4) lib/rack/session/abstract/id.rb:220:in call' actionpack (4.2.6) lib/action_dispatch/middleware/cookies.rb:560:in call' activerecord (4.2.6) lib/active_record/query_cache.rb:36:in call' activerecord (4.2.6) lib/active_record/connection_adapters/abstract/connection_pool.rb:653:in call' activerecord (4.2.6) lib/active_record/migration.rb:377:in call' actionpack (4.2.6) lib/action_dispatch/middleware/callbacks.rb:29:in block in call' activesupport (4.2.6) lib/active_support/callbacks.rb:88:in run_callbacks' activesupport (4.2.6) lib/active_support/callbacks.rb:778:in _run_call_callbacks' activesupport (4.2.6) lib/active_support/callbacks.rb:81:in run_callbacks' actionpack (4.2.6) lib/action_dispatch/middleware/callbacks.rb:27:in call' actionpack (4.2.6) lib/action_dispatch/middleware/reloader.rb:73:in call' actionpack (4.2.6) lib/action_dispatch/middleware/remote_ip.rb:78:in call' actionpack (4.2.6) lib/action_dispatch/middleware/debug_exceptions.rb:17:in call' web-console (2.3.0) lib/web_console/middleware.rb:28:in block in call' web-console (2.3.0) lib/web_console/middleware.rb:18:in catch' web-console (2.3.0) lib/web_console/middleware.rb:18:in call' actionpack (4.2.6) lib/action_dispatch/middleware/show_exceptions.rb:30:in call' railties (4.2.6) lib/rails/rack/logger.rb:38:in call_app' railties (4.2.6) lib/rails/rack/logger.rb:20:in block in call' activesupport (4.2.6) lib/active_support/tagged_logging.rb:68:in block in tagged' activesupport (4.2.6) lib/active_support/tagged_logging.rb:26:in tagged' activesupport (4.2.6) lib/active_support/tagged_logging.rb:68:in tagged' railties (4.2.6) lib/rails/rack/logger.rb:20:in call' quiet_assets (1.1.0) lib/quiet_assets.rb:27:in call_with_quiet_assets' request_store (1.3.1) lib/request_store/middleware.rb:9:in call' actionpack (4.2.6) lib/action_dispatch/middleware/request_id.rb:21:in call' rack (1.6.4) lib/rack/methodoverride.rb:22:in call' rack (1.6.4) lib/rack/runtime.rb:18:in call' activesupport (4.2.6) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in call' rack (1.6.4) lib/rack/lock.rb:17:in call' actionpack (4.2.6) lib/action_dispatch/middleware/static.rb:120:in call' rack (1.6.4) lib/rack/sendfile.rb:113:in call' railties (4.2.6) lib/rails/engine.rb:518:in call' railties (4.2.6) lib/rails/application.rb:165:in call' rack (1.6.4) lib/rack/content_length.rb:15:in call' puma (3.5.0) lib/puma/configuration.rb:225:in call' puma (3.5.0) lib/puma/server.rb:569:in handle_request' puma (3.5.0) lib/puma/server.rb:406:in process_client' puma (3.5.0) lib/puma/server.rb:271:in block in run' puma (3.5.0) lib/puma/thread_pool.rb:116:in `block in spawn_thread'

+0

Bạn đang cố truy cập tài nguyên này từ đâu và như thế nào? Tên của tập tin đến từ đâu? – Leito

+0

@Leito Tôi không thực sự chắc chắn làm thế nào tên tập tin là có liên quan, nhưng nó được gọi là sketch.js và được lưu trữ sử dụng Carrierwave –

+0

Tôi có nghĩa là tập tin mà lỗi xảy ra. Một trong những nơi dòng # 225 là? – Leito

Trả lời

1

Một số gợi ý:

1) Hãy chắc chắn để thêm <%= csrf_meta_tag %> trong cách bố trí của bạn

2) Hãy chắc chắn rằng bạn đã bao gồm các lĩnh vực ẩn CSRF-token. Ví dụ: nếu bạn đang sử dụng biểu mẫu trong chế độ xem chương trình. Thông thường, trình tạo biểu mẫu tự động làm điều đó.

3) Thiết lập application/javascript" trong send_file

if request.format.js? 
    send_file(assetfilename, type: 'application/javascript') 
else 
    send_file(assetfilename) 
end 
+0

OP truy cập tệp trực tiếp thông qua 'GET localhost: 3000/some/1' gọi' send_file' để không có bố cục tại đây. –

+0

Như @KyleDecot đã nói, không có cách bố trí vì nó chỉ sử dụng sendfile với bố trí:: inline trong controller –

1

Như thông báo lỗi nói, bạn cần phải vô hiệu hóa bảo vệ giả mạo cho hành động này.

class SomeController < ApplicationController 
    skip_before_action :verify_authenticity_token, only: :show 

    def show 
    some_path = "/some/js/file/on/disk.js" 
    send_file(some_path, type: "text/javascript", disposition: :inline) 
    end 
end 
+0

Đây là giải pháp hiện tại mà tôi đang sử dụng, tuy nhiên nó có khả năng hiển thị ứng dụng cho một cuộc tấn công csrf. Một số tệp javascript có thể có khả năng nhạy cảm, vì vậy tôi không muốn để nó mở cho điều này. –

1

Kiểm tra ra các điều kiện mà bắn các lỗi:

marked_for_same_origin_verification? && non_xhr_javascript_response? 

tôi đến source và thấy:

# GET requests are checked for cross-origin JavaScript after rendering. 
    def mark_for_same_origin_verification! 
    @marked_for_same_origin_verification = request.get? 
    end 

    # If the `verify_authenticity_token` before_action ran, verify that 
    # JavaScript responses are only served to same-origin GET requests. 
    def marked_for_same_origin_verification? 
    @marked_for_same_origin_verification ||= false 
    end 

Vì vậy, điều đó dường như trở lại đúng nếu đó là một yêu cầu GET .

Trong khi đó,

def non_xhr_javascript_response? 
    content_type =~ %r(\Atext/javascript) && !request.xhr? 
    end 

Mà dường như để mô tả phản ứng của bạn - một yêu cầu không XHR năng suất một tập tin với text/javascript nội dung.

Tôi cho rằng bạn có thể tránh điều này (không phải bằng cách bỏ qua verify_authenticity_token) bằng cách giả mạo nhánh đường ray và thay đổi một trong các điều kiện đó, hoặc giới thiệu bố cục khác để phản hồi không chỉ là javascript.

1

Tôi sẽ không hỏi tại sao bạn đang sử dụng bộ điều khiển để gửi tệp javascript tới trình duyệt mặc dù điều đó dường như không phải là ý tưởng hay. Tôi hy vọng những gợi ý này sẽ giúp ích cho bạn.

Bạn có thể thử

class SomeController < ApplicationController 
    def show 
    some_path = "/some/js/file/on/disk.js" 

    respond_to do |format| 
     format.js { 
     send_file(some_path, type: "text/javascript", disposition: :inline) 
     } 
     format.html { 
     "Html request from browser. Try sending a js request to get <Javascript>" 
     } 
    end 
    end 
end 

Câu trả lời khác là thay đổi việc xử lý CSRF.Điều này tương tự câu trả lời Michal đã đề nghị,

class SomeController < ApplicationController 
     protect_from_forgery except: :show 
     ... 
    end 

Theo tôi thay đổi cách tiếp cận xử lý CSRF là rộng hơn nhiều trong phạm vi. Vô hiệu hóa CSRF cho một phương thức đã cho trong bộ điều khiển cho thấy những thứ mà bạn có thể không muốn tiếp xúc.


Dưới đây là một số đề xuất bổ sung.

Nó có thể lỗi thời, nhưng curl cho phép người dùng kiểm soát hoàn toàn các tiêu đề yêu cầu HTTP cũng như xem phản hồi HTTP đầy đủ. Bằng cách gọi curl -H "Content-Type: application/javascript" http://someurl/here/1, bạn sẽ có thể thấy chính xác những gì đang xảy ra và lý do tại sao trình duyệt của bạn không thể phân phát tệp javascript được yêu cầu hoặc nếu có cách giải quyết khác.

Cuối cùng, nếu bạn đang cố gắng phân phối tệp tĩnh (javascript) trong Rails, có rất nhiều chi phí bổ sung và rủi ro bảo mật tiềm ẩn khi sử dụng bộ điều khiển để thực hiện tác vụ đó. Trừ khi có một lý do rất tốt để sử dụng bộ điều khiển, giải pháp đơn giản hơn là lưu trữ các tệp trong thư mục con của thư mục ./public trên máy chủ, để bất kỳ ai và mọi người đều có thể đọc (các) tệp. Khi bạn triển khai ứng dụng vào một môi trường sản xuất, điều này có thể tiết kiệm được nhiều chi phí hơn, nhưng vượt quá phạm vi của câu hỏi ban đầu của bạn.

Chúc may mắn!

+0

btw, loại mime 'text/javascript' đã được chuẩn hóa thành' application/javascript'. Xem http://stackoverflow.com/questions/876561/when-serving-javascript-files-is-it-better-to-use-the-application-javascript-or –

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