Brakeman - Rails Security Scanner というgemを使うとCSRFやXSS等Railsに施されているRailに乗れていないマナーの悪いコードを静的解析してくれるツールです。
Railsはバージョンが上がるにつれて、例えばRails4ではMass Assignment脆弱性に対応したStrong Parametersに対応するといったように近年ホットになった脆弱性に関してはかなり早いスピードで対応してくれます。
世の中には外部からアプリをブラックボックス化したところで動的解析を行って脆弱性チェックを行うサービスもある様ですが、個人的にはRailsに乗っている限りは金融取引など、よほどクリティカルな情報を扱う様なアプリ以外はBrakemanで軽くチェックしてwarningを潰す程度でリリースしても良いんじゃ無いかと思います。
スポンサーリンク
目次
使い方
Gemfileにbrakeman
を追加します。2018/3/13現在の最新バージョンは2018/2/21にリリースされた4.2.0で比較的頻繁に更新されており安心して使えます:
group :development do
gem 'brakeman'
end
あとはbundle install
して、brakeman
コマンドをRailsアプリフォルダ上で打つだけです:
$ brakeman
実際にアプリで実行してみる
web-k/tiramisu: WebSocket(Pusher)を使ったチャット&囲碁Railsアプリで実際に組み込んで実行してみました。すると4つほどwarningが出ました:
== Brakeman Report ==
Application Path: /home/toshi/tiramisu
Rails Version: 5.1.5
Brakeman Version: 4.2.0
Scan Date: 2018-03-13 10:03:35 +0900
Duration: 0.52445335 seconds
Checks Run: BasicAuth, BasicAuthTimingAttack, ContentTag, CreateWith, CrossSiteScripting,
DefaultRoutes, Deserialize, DetailedExceptions, DigestDoS, DynamicFinders, EscapeFunction,
Evaluation, Execute, FileAccess, FileDisclosure, FilterSkipping, ForgerySetting, HeaderDoS,
I18nXSS, JRubyXML, JSONEncoding, JSONParsing, LinkTo, LinkToHref, MailTo, MassAssignment,
MimeTypeDoS, ModelAttrAccessible, ModelAttributes, ModelSerialize, NestedAttributes,
NestedAttributesBypass, NumberToCurrency, PermitAttributes, QuoteTableName, Redirect,
RegexDoS, Render, RenderDoS, RenderInline, ResponseSplitting, RouteDoS, SQL, SQLCVEs,
SSLVerify, SafeBufferManipulation, SanitizeMethods, SelectTag, SelectVulnerability, Send,
SendFile, SessionManipulation, SessionSettings, SimpleFormat, SingleQuotes, SkipBeforeFilter,
StripTags, SymbolDoSCVE, TranslateBug, UnsafeReflection, ValidationRegex, WithoutProtection,
XMLDoS, YAMLParsing
== Overview ==
Controllers: 6
Models: 7
Templates: 8
Errors: 0
Security Warnings: 4
== Warning Types ==
Cross-Site Request Forgery: 2
Cross-Site Scripting: 1
Session Setting: 1
== Warnings ==
Confidence: High
Category: Cross-Site Request Forgery
Check: ForgerySetting
Message: 'protect_from_forgery' should be called in AuthenticationController
File: app/controllers/authentication_controller.rb
Line: 1
Confidence: High
Category: Cross-Site Scripting
Check: CrossSiteScripting
Message: Unescaped model attribute
Code: Channel.new(params.require(:channel).permit(:name)).name
File: app/views/layouts/application.html.erb
Line: 43
Confidence: High
Category: Session Setting
Check: SessionSettings
Message: Session secret should not be included in version control
File: config/initializers/secret_token.rb
Line: 12
Confidence: Medium
Category: Cross-Site Request Forgery
Check: ForgerySetting
Message: protect_from_forgery should be configured with 'with: :exception'
File: app/controllers/application_controller.rb
CSRFが2つとXSSが1つ、セッション絡みで1つある様です。ワーニングの詳しい内容についてはBrakeman - Rails Security Scanner: Warning Typesから詳しい説明が参照出来ると思います。一つづつ見ていきます。
Check: ForgerySetting
1つめのAuthenticationController
でprotect_from_forgery
が呼ばれてないというのをみてソースを見てみると、
class AuthenticationController < ActionController::Base
となっていてprotect_from_forgery
を呼んでいるApplicationControllerを継承してませんでした。特に理由も無いので継承しておきます:
class AuthenticationController < ApplicationController
Check: CrossSiteScripting
2つめはXSSの警告でソースを見ると、
<div id="channel_name_static" style="display:inline;"><%== @channel.name %></div>
<div id="channel_name_edit" style="display:none;"><%== f.text_field :name %></div>
で、<%== @channel.name %>
の<%==
はHTMLエスケープしてしないで出力となってました。この部分は@channel.name
をユーザー入力で変更出来るようにしていたみたいですが、<script>alert();</script>
をぶち込んで見ると見事にXSS発生w・・・なんでこうしたかは過去のコード過ぎて分かりませんが、エスケープしても正常に動作するのでエスケープしておきます:
<div id="channel_name_static" style="display:inline;"><%= @channel.name %></div>
<div id="channel_name_edit" style="display:none;"><%= f.text_field :name %></div>
Check: SessionSettings
3つめのSessionSettings警告はBrakeman - Rails Security Scanner: Session Settingsを見る(日本語訳す)と、
config/initializers/secret_token.rbがリポジトリに含まれていると警告します。secret_token.rbは.gitignoreで除外することを推奨します。
とのこと。素直に外せば良さそうです。また、secret_token.rbは4.0以前で使っていたもので4.1以降はconfig/secrets.yml
を利用している様なのでgit rm config/initializers/secret_token.rb
してしまいます。
Check: ForgerySetting
4つめの警告はCSRFに引っかかった場合の挙動を指定しろってことなので、例外吐いて弾くようにした:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
積極的にBrakemanを活用しよう
修正した内容はBrakemanによるセキュリティ警告の対処 · web-k/tiramisu@ff13f9aとなり、これで全ての警告が消えました。日頃ちょっとセキュリティを気にしておけばそれ程警告も出ないでしょうからコミット前、若しくはリリース前にbrakemanを走らせて対処しておくと良いでしょう。