Railsアプリケーションの
脆弱性動的自動検査

2019-08-16 Cookpad 夏季就業型インターン成果発表会 中間報告

@hakatashi

(中間成果報告)

@hakatashi

  • 大学4年生
  • インターン (高難易度技術コース, ~8/30)
  • Webエンジニア
    • フロントエンド得意マン
  • 趣味
    • ルービックキューブ
    • 小説
    • CTF
    • アイマス
  • Twitter: @hakatashi
  • GitHub: @hakatashi
  • hakatashi.com

脆弱性に対処する

  • 脆弱性を生まない
    • 適切なフレームワークを使う
  • 脆弱性を発見する
    • 人間が頑張る
      • エンジニアが頑張る
      • 報奨金制度
    • 自動で脆弱性を見つける
      • 静的検査
      • 動的検査 ←今回のターゲット

静的検査

特にRailsに特化した静的脆弱性検査ツールとして、
brakemanが有名

class UsersController < ApplicationController
  def update
    id = params[:user][:id]
    user = User.where("id = '#{id}'")[0]
  end
end

静的検査の限界

複雑な脆弱性に対しては
検出されない or
確証を持って脆弱と言えない

# app/controllers/admin_controller.rb
class AdminController < ApplicationController
  def analytics
    if params[:field].nil?
      fields = "*"
    else
      fields =
        params[:field].map {|k,v| k }.join(",")
    end

    if params[:ip]
      @analytics =
        Analytics.hits_by_ip(params[:ip], fields)
    else
      @analytics = Analytics.all
    end
  end
end

# app/models/analytics.rb
class Analytics < ApplicationRecord
  scope :hits_by_ip, ->(ip, col = "*") { 
    select("#{col}")
      .where(ip_address: ip)
      .order("id DESC")
  }
end

/admin/analytics?field[(select+group_concat(password)+from+users+where+admin=%27t%27)]=f で発火 →
 

静的検査の限界

一般的な静的解析ツールでは、
「確実に脆弱と言えるもの」だけでなく、
「部分的に見れば脆弱かもしれない」ものまで報告される

→検出の精度が低い

動的脆弱性解析

動的脆弱性解析

実際に動いているアプリケーションに対して
攻撃を仕掛け、脆弱性が存在するかどうか
確認する

動的解析の利点

  • 実際に攻撃が通ったかまで検証できるので、
    偽陽性を極力少なくすることができる
    • 逆に、偽陰性は増える
  • つまり、動的解析で発見された脆弱性は
    「確実に直さないとヤバい」

欠点

  • 到達不能なアドレスは検知できない
  • 到達不能なパラメーターは検知できない
  • 重い

Ruby on Rails に特化した
動的脆弱性検査

インターンでの成果物

Railsアプリケーションの良さ

  • Rails way に則っていれば
    アプリケーションの構成は
    基本的にどれも一緒
  • Rails固有の処理に対応した
    脆弱性検査が可能

動的解析の欠点に対応

  • 到達不能なアドレスは検知できない
    • Railsならroutes.rbを見れば一発
  • 到達不能なパラメーターは検知できない
    • 静的解析を組み合わせて対処
  • 重い
    • Controllerのメソッド単位の呼び出しで
      オーバーヘッドを最小限に

デモ

対象の
Railsアプリ

DB

③アクセス
を監視

ファイル
システム

攻撃
スクリプト

②攻撃
ペイロード

①静的解析でURLと
パラメーターを取得

④実際に攻撃が発火したか
確認する

レスポンス
(XSSなどを検証)

今後

  • 汎用的なRailsアプリケーションに対して
    実行可能なgemにまとめる
  • SQLインジェクション以外の脆弱性にも
    対応する
  • パラメーターの抽出精度を上げる
  • Railsのいろんなバージョンに対応する

おまけ (時間があれば)

URLパラメーターの抽出

残念ながらRailsのURLパラメーター
統一的なインタフェースでアクセスできない。

現在、パラメーターの抽出はRubyのコードをパースして
静的解析で抽出している。

一言で言うとparams変数を見るだけだが⋯⋯

if params[:hoge] == 'fuga'
  # ここに脆弱なコードを入力
end
user = User.find_by(id: params[:user_id])
return not_found unless user.present?

# ここに脆弱なコードを入力
if params[:password] == params[:password_confirm]
  # ここに脆弱なコードを入力
end
if params[:user][:password].present?
  # ここに脆弱なコードを入力
end
class UserController
  before_action :set_user

  def show
    # ここに脆弱なコードを入力
  end

  private

  def set_user
    @user = User.find_by(id: params[:user_id])
    return not_found unless @user.present?
  end
end
%i[user password].each do |keyword|
  return bad_request if params[keyword].nil?
end
# ここに脆弱なコードを入力
class UserController
  def show
    parameters = user_params
    # ここに脆弱なコードを入力
  end

  private

  def user_params
    params.require(:user).permit(:name, :email)
  end
end

パターンが多くて大変!

→rspec-mockのdoubleみたいな手法で
paramsへのアクセスも動的に解析する?

パラメーターの抽出は今後の課題

おわり

Railsアプリケーションの動的脆弱性自動検査 (中間成果報告)

By Koki Takahashi

Railsアプリケーションの動的脆弱性自動検査 (中間成果報告)

2019-08-16 Cookpad 夏季就業型インターン成果発表会 中間報告

  • 1,164