5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

今話題の脆弱性について自社サイトは大丈夫ですか?

Last updated at Posted at 2022-11-25

今某サイトの下記の脆弱性が話題です

最近弊社ではRuby on Railsなので自社での状況を確認しました

1. 認証CookieにSecure属性をつけていない

どのような問題が?

HTTP通信でCookieが送られてしまうため、暗号化されていないため、信用できないWiFiを利用した場合などに、登録している情報ややり取りの履歴が盗まれる可能性がある。

参考情報

Secure 属性がついた Cookie は HTTPS プロトコル上の暗号化されたリクエストでのみサーバーに送信され、安全でない HTTP では決して送信されないため、中間者攻撃者が簡単にアクセスすることはできません。(URL に http: を含む) 安全でないサイトは、 Secure 属性を使用して Cookie を設定することができません。
https://developer.mozilla.org/ja/docs/Web/HTTP/Cookies

弊社での対策

1. Secure属性を付与する

config/environments/production.rb
config.session_store(secure: true)

<追記>
ところが Secure 属性が付加されません

action_dispatch/middleware/cookies.rb
def []=(name, options)
# name: _server_rails_session
# options: {:value=>"...=", :same_site=>nil, :path=>"/", :domain=>nil, :expire_after=>nil, 
# :secure=>false, :httponly=>true, 
# :defer=>false, :renew=>false, :id=>"..."}
action_dispatch/middleware/session/cookie_store.rb
def set_cookie(request, session_id, cookie)
  cookie_jar(request)[@key] = cookie
end
rack/session/abstract/id.rb
  def context(env, app = @app)
    req = make_request env
    prepare_session(req)
    status, headers, body = app.call(req.env)
    res = Rack::Response::Raw.new status, headers
    commit_session(req, res)
    [status, headers, body]
  end
:
def commit_session(req, res)
  session = req.get_header RACK_SESSION
  options = session.options
# options: {
#  :path=>"/", :domain=>nil, :expire_after=>nil, :secure=>false, :httponly=>true, :defer=>false, :renew=>false, :id=>"..."
# }
:
set_cookie(req, res, cookie.merge!(options))
action_dispatch/middleware/session/abstract_store.rb
    module SessionObject # :nodoc:
      def commit_session(req, res)
        req.commit_csrf_token
        super(req, res)
      end
      :
      def prepare_session(req)
        # @default_options: {
        #  :path=>"/", :domain=>nil, :expire_after=>nil, :secure=>false, :httponly=>true, :defer=>false, :renew=>false, :id=>"..."
        # }
        Request::Session.create(self, req, @default_options)
      end

結局 @default_optionssecure: falseままでした。

以下を書き換えると修正できました

- config.session_store secure: true
+ config.session_store :cookie_store, secure: true

2. CloudFrontのビヘイビアでHTTPS通信だけに限定する

image.png

2. 他人の情報を書き換え可能

ユーザAでログインしてユーザAの認証Cookieを使い、ユーザBの情報を入手したり書き換えることができる。

なぜ起きるのか?以下のように書き換えるユーザのIDをリクエストパラメータで参照している。

user = User.find(params[:user_id])
user.update params[:user_name]

本来であれば以下のようにユーザIDはセッションから取得すること。またデータベースに渡すパラメーターは制限する必要がある。

user = User.find(current_user.id)
user.update params.require[:user].permit[:name]

またユーザが投稿した記事のような場合は単純にfindせずに事前にwhere句で対象となる記事を絞り込んでください

article = Article.where(author: current_user).find(params[:id])

さらに

RUNTEQ校長「ひさじゅ」さんより教えていただきました

BrakemanというGemを使うとよくある脆弱性を検知してくれるとのことです

5
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?