もた日記

くだらないことを真面目にやる

Railsメモ(25) : Brakemanでセキュリティチェックする

github.com

RuboCopとRails Best Practicesに似たようなもので、Brakemanというセキュリティチェックに特化したgemがあるので試してみる。

Brakemanのインストール


Gemfileに下記行を追加してbundle installする。

group :development do
  gem 'brakeman', require: false
end

これでbrakemanコマンドが使えるようになったので、アプリのディレクトリに移動して実行してみる。

$ brakeman
Loading scanner...
Processing application in /home/vagrant/rails/billboard
Processing gems...
[Notice] Detected Rails 4 application
Processing configuration...
[Notice] Escaping HTML by default
Parsing files...
 …省略…
Checks run: BasicAuth, ContentTag, CreateWith, CrossSiteScripting, DefaultRoutes, Deserialize, DetailedExceptions, DigestDoS, EscapeFunction, E
valuation, Execute, FileAccess, FileDisclosure, FilterSkipping, ForgerySetting, HeaderDoS, I18nXSS, JRubyXML, JSONEncoding, JSONParsing, LinkTo
, LinkToHref, MailTo, MassAssignment, ModelAttrAccessible, ModelAttributes, ModelSerialize, NestedAttributes, NumberToCurrency, QuoteTableName,
 Redirect, RegexDoS, Render, RenderDoS, RenderInline, ResponseSplitting, SQL, SQLCVEs, SSLVerify, SafeBufferManipulation, SanitizeMethods, Sele
ctTag, SelectVulnerability, Send, SendFile, SessionSettings, SimpleFormat, SingleQuotes, SkipBeforeFilter, StripTags, SymbolDoSCVE, TranslateBu
g, UnsafeReflection, ValidationRegex, WithoutProtection, XMLDoS, YAMLParsing


+SUMMARY+

+-------------------+-------+
| Scanned/Reported  | Total |
+-------------------+-------+
| Controllers       | 3     |
| Models            | 3     |
| Templates         | 4     |
| Errors            | 0     |
| Security Warnings | 0 (0) |
+-------------------+-------+

結果を見ると、エラーと警告は0になっている。Checks run:にチェックした項目がリストアップされているが、簡単な説明は下記コマンドで確認できる。

$ brakeman -k
Available Checks:
------------------------------
CheckBasicAuth                Checks for the use of http_basic_authenticate_with
CheckCrossSiteScripting       Checks for unescaped output in views
CheckContentTag               Checks for XSS in calls to content_tag
CheckCreateWith               Checks for strong params bypass in CVE-2014-3514
CheckDefaultRoutes            Checks for default routes
 …

エラーや警告になるとどうなるか見てみたいので、下記ページを参考にコードを追加してみるとちゃんと警告になった。

http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index
$ brakeman
 …
+SUMMARY+

+-------------------+-------+
| Scanned/Reported  | Total |
+-------------------+-------+
| Controllers       | 3     |
| Models            | 3     |
| Templates         | 4     |
| Errors            | 0     |
| Security Warnings | 1 (1) |
+-------------------+-------+

+--------------+-------+
| Warning Type | Total |
+--------------+-------+
| Basic Auth   | 1     |
+--------------+-------+

Controller Warnings:

+------------+-----------------------+--------------+---------------------------------------------------------------------------------------->>
| Confidence | Controller            | Warning Type | Message                                                                                >>
+------------+-----------------------+--------------+---------------------------------------------------------------------------------------->>
| High       | ApplicationController | Basic Auth   | Basic authentication password stored in source code near line 2: http_basic_authenticat>>
+------------+-----------------------+--------------+---------------------------------------------------------------------------------------->>

なお-o test.htmlのようにオプションを指定すればhtmlに出力が可能。

f:id:wonder-wall:20150820202056p:plain


Brakemanの警告を無視する設定


Brakemanの警告を意図的に無視したい場合もあるので、そのときは警告を無視する設定を追加する。例として、さきほど追加したBasic Authの警告を無視してみる。
-Iオプションを指定すると対話的に設定を追加できる。

$ brakeman -I
 …
Input file: |config/brakeman.ignore|

設定ファイルはまだ存在していないのでリターンを押す。

No such file. Continue with empty config? y

確認されるのでyを入力してリターンを押す。

1. Inspect all warnings
2. Hide previously ignored warnings
3. Skip - use current ignore configuration
? 1

全ての警告を対象にしたいので1を入力してリターンを押す。

--------------------
Confidence: High
Category: Basic Auth
Message: Basic authentication password stored in source code
Code: http_basic_authenticate_with(:name => "h", :password => "secret", :except => :index)
File: app/controllers/application_controller.rb
Line: 2
Action: (i, n, k, u, a, s, q, ?) i

それぞれの警告に対してどうするか聞いてくるので?で選択肢を確認してみる。

i - Add warning to ignore list
n - Add warning to ignore list and add note
s - Skip this warning (will remain ignored or shown)
u - Remove this warning from ignore list
a - Ignore this warning and all remaining warnings
k - Skip this warning and all remaining warnings
q - Quit, do not update ignored warnings
? - Display this help

無視する警告として追加するのでiを入力してリターンを押す。

--------------------
Ignoring 1 warnings
Showing 0 warnings
1. Save changes
2. Start over
3. Quit, do not save changes
? 1 

全ての警告に対して処理が完了すると変更をどうするか聞いてくるので、変更を保存するために1を入力してリターンを押す。

Output file: |config/brakeman.ignore|

ファイル名はそのままでリターンを押す。
正しく処理が完了するとconfig/brakeman.ignoreというファイルが作成され、Brakemanの結果がIgnored Warningsに変わる。

+SUMMARY+

+-------------------+-------+
| Scanned/Reported  | Total |
+-------------------+-------+
| Controllers       | 3     |
| Models            | 3     |
| Templates         | 4     |
| Errors            | 0     |
| Security Warnings | 0 (0) |
| Ignored Warnings  | 1     |
+-------------------+-------+


guard-brakemanで自動実行する


github.com

例のごとくGuardで自動実行してみる。
Gemfileに下記行を追加してbundle installする。

group :development do
  gem 'guard'
  gem 'guard-brakeman'
end

Guardfileに設定を追加するために下記コマンドを実行。

$ guard init brakeman
22:41:30 - INFO - brakeman guard added to Guardfile, feel free to edit it

以下の内容がGuardfileに追記される。

guard 'brakeman', :run_on_start => true do
  watch(%r{^app/.+\.(erb|haml|rhtml|rb)$})
  watch(%r{^config/.+\.rb$})
  watch(%r{^lib/.+\.rb$})
  watch('Gemfile')
end

設定可能なオプションを参考に、結果だけを表示するようにquiet: trueを追加して、Guard起動時に実行しないようにrun_on_start: falseにする。デフォルトでは新規または修正したエラーしか表示されないみたいなので、全ての変更を通知したい場合はchatty: trueを設定する。

:quiet          => false    # set the "quiet" option in brakeman (only results will be printed)
:ignore_file    => 'config/brakeman.ignore'
:output_files   => %w(donkey.html) # write the results to the specified files
:notifications  => false    # display Growl notifications, defaults to true
:run_on_start   => true     # run all checks on startup, defaults to false
:min_confidence => 3        # only alert on warnings above a threshold, defaults to 1
:chatty         => true     # notify on ALL changes.  Defaults to false, only new or fixed warnings trigger a Growl
:url_safe_methods => %w(method1 method2) # list methods which are safe for use in link_to URLs
# guard 'brakeman', :run_on_start => true do
guard 'brakeman', run_on_start: false, quiet: true do

f:id:wonder-wall:20150820211934p:plain

パーフェクト Ruby on Rails

パーフェクト Ruby on Rails