2016-09-12 5 views
11

私は奇妙なCSRFを実行しています。私は自分のレールサーバにアップロードされたjavascriptファイルにアクセスしようとしています。私は、次のようなコントローラがあります。私は何のレイアウトはので、私はできませんが存在しないことを意味し、直接このページにアクセスしていますがRailsはジャバスクリプトで偽造を防ぎます

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 

注:http://localhost:3000/somes/1に移動するとき

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

をしかし、私はエラーメッセージが表示されます私のレイアウトにCSRFトークンを含めてください。

このリソースに正しくアクセスするには、別の方法で行う必要がありますか?

EDIT:コメントごとに、以下のフルトレースを追加しました。

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

このリソースにはどこからアクセスしようとしていますか?ソースに由来するファイルの名前は何ですか? – Leito

+0

@Leitoファイル名がどのように関係しているかわかりませんが、sketch.jsと呼ばれ、Carrierwaveを使用して保存されています –

+0

私はエラーが発生しているファイルを意味しました。ライン#225があるのは? – Leito

答えて

1

ヒント:

1)あなたのレイアウト

2に<%= csrf_meta_tag %>を追加してください)あなたはCSRFトークン隠しフィールドを含めていることを確認します。たとえば、表示ビューでフォームを使用している場合です。通常はフォーム作成者が自動的に行います。

3)は、エラーメッセージが言うように、あなたはこのアクションの偽造保護を無効にする必要がありsend_file

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

OPは 'send_file'を呼び出す' GET localhost:3000/some/1'を介して直接ファイルにアクセスしていますので、ここにはレイアウトはありません。 –

+0

@KyleDecotが述べているように、コントローラ内にsendfileとdisposition::inlineをちょうど使っているので、レイアウトはありません –

1

application/javascript"を設定します。

エラーを発射条件のチェックアウト
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

これは私が使っている現在の回避策ですが、アプリケーションをcsrf攻撃にさらす可能性があります。いくつかのjavascriptファイルは機密性がある可能性がありますので、私はこれを開いたままにしたくありません。 –

1

marked_for_same_origin_verification? && non_xhr_javascript_response? 

私はsourceに行ってい:

# 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 

だから、それはGETリクエストだ場合は戻って叶うようです。一方

あなたの応答を記述しているようだ
def non_xhr_javascript_response? 
    content_type =~ %r(\Atext/javascript) && !request.xhr? 
    end 

- テキスト/ javascriptのコンテンツのファイルをもたらす非XHRリクエストを。

これは、(verify_authenticity_tokenをスキップする以外に)レールの分岐を壊してそれらの条件の1つを変更したり、レイアウトを導入して応答が単なるjavascriptではないようにすることができます。

1

コントローラを使用してブラウザにjavascriptファイルを送信する理由を尋ねることはありませんが、それは良い考えではありません。これらの提案が役立つことを願っています。

あなたは他の答えはCSRFの取り扱いを変更することです

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 

を試みることができます。これはMichalが既に提案した答えと同じです。私の意見では、CSRFの扱い方の変更は範囲がかなり広がっています。コントローラ内の特定のメソッドに対してCSRFを無効にすると、公開したくないものが公開されます。


ここにいくつかの追加の提案があります。

古臭いかもしれませんが、curlはHTTPリクエストヘッダーを完全に制御し、完全なHTTP応答を見ることができます。 curl -H "Content-Type: application/javascript" http://someurl/here/1を呼び出すと、何が起こっているのか、ブラウザが要求されたjavascriptファイルを提供できない理由、または回避策があるかどうかを正確に確認することができます。

最後に、静的(javascript)ファイルをRailsに配信しようとすると、コントローラを使用してその操作を実行する際に、余分なオーバーヘッドと潜在的なセキュリティリスクが発生します。コントローラーを使用する理由がない限り、誰かと誰もがファイルを読むことができるように、サーバー上の./publicディレクトリーのサブディレクトリーにファイルを保管するのが簡単な解決策です。プロダクション環境にアプリケーションをデプロイすると、オーバーヘッドはさらに削減できますが、これは元の質問の範囲を超えています。

幸運を祈る!

+0

btw、MIMEタイプ 'text/javascript'は' application/javascript'として標準化されています。 http://stackoverflow.com/questions/876561/when-serving-javascript-files-is-it-better-to-use-the-application-javascript-ororを参照してください。 –

関連する問題