アルパカログ

Webエンジニア兼マネージャーがプログラミングやマネジメント、読んだ本のまとめを中心に書いてます。

Elixir DoS脆弱性になり得るAtom枯渇と対策(Atom Exhaustion)

f:id:otoyo0122:20200819092955p:plain:w300

Erlang/Elixirにおいて、Atomを使うことはよくあります。

このエントリでは、DoS脆弱性になり得るAtom枯渇(Atom Exhaustion)とその対策について説明します。

GCとAtom枯渇

Erlang/Elixirにおいて、AtomはGC(garbage collection)されません。

Atomは一度生成されるとプログラムが終了するまで残り続け、上限(デフォルトでは1,048,576)を超えて生成しようとするとVMがクラッシュします。

Atom枯渇(Atom Exhaustion)とはこのように、Atomの生成可能数が枯渇してしまう状態を指します。

Atom枯渇がDoS脆弱性になるケースとしては、Webサーバー等において、リクエストパラメータなどの外部パラメータからAtomを生成している場合が挙げられます。

def show(conn, %{"step" => step}) do
  render conn, "show.html", step: String.to_atom(step)
end

Atom枯渇を防ぐには

Atom枯渇を防ぐには次の点に注意します。

Erlang

  • list_to_atom/1の代わりにlist_to_existing_atom/1を使用する
  • binary_to_atom/1,2の代わりにbinary_to_existing_atom/1,2を使用する
  • 信頼できない入力に対してbinary_to_term/2を呼ぶときはsafeオプションを使用する(*1)
  • 信頼できない入力に対してfile:consult/1file:path_consult/2を使用しない(*1)

Elixir

  • String.to_atom/1の代わりにString.to_existing_atom/1を使用する
  • List.to_atom/1の代わりにList.to_existing_atom/1を使用する
  • Module.concat/1,2の代わりにModule.safe_concat/1,2を使用する
  • 次のようなinterpolation(補間)によるAtom生成を使用しない
    • :"new_atom_#{index}"
    • :'new_atom_#{index}'
    • ~w[row_#{index} column_#{index}]a
  • 信頼できない入力に対して:erlang.binary_to_term/2を呼ぶときはsafeオプションを使用する(*1)

*1: Serialisation and deserialisation を参照

以上です。

このエントリでは、DoS脆弱性になり得るAtom枯渇とその対策について説明しました。

参考文献

付録: RubyのシンボルとGC

Rubyのシンボルは、Ruby 2.2以降ではGCされます。

詳しくは下記をご覧ください。