6時だョ!!全員集合!!

Rails・JavaScrictを中心にアウトプットします。

2021年8月25日 現場Rails Chapter6-7-3 インジェクションに注意する(その2)

Rubyコードインジェクション

Rubyコードインジェクションとは、コードインジェクションのうちRubyソースコードを対象とする攻撃のことを指します。

sendとevalってなに??

sendメソッドは、引数で渡された文字列のメソッドを呼び出して実行します。

しかし、渡される引数に危険な値が渡される可能性があるため、条件分岐させてホワイトリスト形式で特定の文字列のみ許可してあげる方が安全です。

ホワイトリスト方式は原則許可せず、許可するリストをこちらで指定するため、ブラックリスト方式よりも原則漏れが起きづらいという特徴があります。)

sendメソッドは動的なメソッド呼び出しができて便利だが、セキュリティ面を考慮し、外部の入力に依存する値は渡さないようにします。(特に、ユーザーからの入力をそのままsendに引き渡すと、意図せぬ範囲のデータやプライベートメソッドにまで影響が及ぶ可能性があります)

#sendメソッド
#第二引数で呼び出したメソッドに与える引数を渡しています。
send("メソッド名", "引数")

evalメソッドも、第一引数で文字列を渡すことができますが、渡された文字列のコードをそのまま実行することができます。しかし、sendメソッド同様に悪意のあるコードを渡されて、プログラムを実行される恐れがあります。

#evalメソッド
eval('rubyコード')

sendの使用例 プロを目指す人のためのRuby入門 P420

str = 'a,b,c'

# str.upcaseを呼ぶのと同じ
str.send('upcase')  #=> "A,B,C"

# str.split(',')を呼ぶのと同じ
str.send('split',',') #=> ["a","b","c"]

evalの使用例 プロを目指す人のためのRuby入門 P420

# 文字列としてRubyのコードを記述する
code = '[1,2,3].map { |in| n * 10 }'

#evalメソッドに渡すと、文字列がRubyのコードとして実行される
eval(code) #=> [10,20,30]

eval攻撃例(予想) eval(params[:hoge])

上記のparams[:hoge]に、「データベースのUsersテーブルにあるメールアドレスを1行ずつfuga変数に配列として代入し、その後fuga変数を外部(悪意を持った者のメールアドレスetc)に送信する」みたいな記述を渡してしまうと、それが実行されてしまう危険性があります。

# ユーザー全件削除
params[:hoge] = User.destroy_all
eval(params[:hoge])

大事なことは、ユーザーから渡された生の値をそのまま使わないことです。 sendメソッドやevalメソッドを使う場合、ストロングパラメータのような、ユーザーから渡された値を評価する仕組みを作る必要があると思われます。

コマンドラインインジェクション

コントローラーにコマンドライン(例: mkdir hogefuga)などを組み込んだ際に注意する必要があります。

@group = mkdir #{params[:input]} (←使用イメージ) (params[:input]で送られた値のファイルを作成及びそれを@groupに代入)

バッククォートで囲まれた文字列はコマンドとして出力されます。

`date`
%x{ date }

バッククォートで囲まれた文字列は、ダブルクォートで囲まれた文字列と同様にバックスラッシュ記法 の解釈と式展開 が行なわれた後、コマンドとして実行され、その標準出力が文字列として与えられます。コマンドは評価されるたびに実行されます。コマンドの終了ステータスを得るには、$? を参照します。

%記法 による別形式のコマンド出力もあります。

考え方はストロングパラメータの時と同じで良いと思います。生の値をそのまま使うのはご法度です。

Content Security Policy(CSP)

HTTPリクエスト⇔HTTPレスポンスのやり取りの中で、約束事をホワイトリスト形式でブラウザに伝えるイメージです。

クロスサイトスクリプティング (XSS) やデータインジェクション攻撃などのような、特定の種類の攻撃を検知し、影響を軽減するために追加できるセキュリティレイヤーです。CSP を有効にするには、ウェブサーバーから Content-Security-Policy HTTP ヘッダーを返すように設定する必要があります。

CSPの適用前に通信のコネクション自体確立していて、データ送受信(HTTPリクエストを送信する)段階で、ヘッダーにContent-Security-Policyを組み込むことにより攻撃の軽減(想定しないユーザーのパケット傍受などを防ぐ)を目指しています。

CSPを適用すると、、、

CSP の第一の目的は XSS 攻撃の軽減と報告です。 XSS 攻撃とは、サーバーから取得したコンテンツをブラウザーが信頼する性質を悪用した攻撃です。サーバー管理者が CSP を利用する場合、実行を許可するスクリプトの正しいドメインブラウザーに向けて指定することにより、 XSS の発生する箇所を削減・根絶することができます。 CSP をサポートするブラウザーは、サーバーから指定された許可リストに載っているドメインスクリプトのみ実行し、他のスクリプトはすべて無視します。

CSP適用方法

メッセージヘッダーにcontent-security-policyが追加されるイメージ

#CSPの適用
#config/initializers/content_security_policy.rbに記述
Rails.application.config.content_security_policy do |policy|
  policy.default_src :self, :https # サイト自身のドメインとHTTPSを使用した全ドメインを許可する
  policy.style_src   :self, :https, :unsafe_inline # インラインの<style>要素を許可(危険)
  ...
end
# コントローラで設定をカスタマイズするには、content_security_policyメソッドを使用
class ArticlesController < ApplicationController
  content_security_policy do |policy|
    policy.upgrade_insecure_requests true # httpをhttpsへリダイレクト(対応ブラウザの場合)
  end
end

ドメイン = インターネット上に存在するコンピュータやネットワークを識別するためのコンピュータの名前のことを言います。ネットワーク上の住所を表すイメージです。ドメイン名は重複するのことない一意な名前になるように管理されています。

ディレクティブとは

ディレクティブとは、和訳すると指示文です。
コンピュータプログラムのソースコードに記述される要素の一つで、そのコードを解釈・変換するソフトウェア(コンパイラプリプロセッサなど)への指示や指定などを与えるためのものです。

参照

Ruby on Rails】sendメソッドのいろんな書き方
https://qiita.com/ngron/items/05d3a9624c2c3ec5dbb6

Kernel.#eval公式
https://docs.ruby-lang.org/ja/latest/method/Kernel/m/eval.html

exitメソッド
https://techacademy.jp/magazine/20564

rubyで使うリテラル
https://docs.ruby-lang.org/ja/latest/doc/spec=2fliteral.html

Rubyのsendメソッドを使用するメリットと注意点
https://qiita.com/hogucc/items/79da134520ee731fe298

Linuxコマンドを連続して実行する
https://webkaru.net/linux/execute-combine-multiple-commands/

git logのオプション
https://atmarkit.itmedia.co.jp/ait/articles/2004/09/news018.html

パケットとは
https://www.otsuka-shokai.co.jp/words/packet.html

Ruby on Rails 5.2の新機能(Active Storage, Content Security Policyなど)
https://qiita.com/ryohashimoto/items/75f48fa5a3846c58f735

コンテンツセキュリティポリシー (CSP)
https://developer.mozilla.org/ja/docs/Web/HTTP/CSP

ディレクティブとは
https://www.javadrive.jp/servlet/jsp_directive/index1.html