このページの本文へ

F-Secure研究者が講演で警鐘、コマンドインジェクション攻撃防ぐコードレビューを―「Black Hat 2019」レポート

F5「BIG-IP」のiRule、コーディング次第で脆弱性量産リスクあり

2019年09月09日 07時00分更新

文● 谷崎朋子 編集● 大塚/TECH.ASCII.jp

  • この記事をはてなブックマークに追加
  • 本文印刷

コマンドインジェクション攻撃でiRuleスクリプトが外から“丸見え”に

 今回の脆弱性は具体的にどのようなものなのか。Black Hat USAの講演で、ジャーカビー氏はTclの基本や脆弱性、デモを交えた攻撃の実演を行った。

 まずはTclの基礎を押さえておこう。Tclでは、コマンドと引数のセット(コマンドライン)で実行したい内容を指定する。先頭にはコマンド(以下の例では「set」)を書き、次にスペース区切りで引数(「a」と「1」)を書く。変数に格納されている値を取り出す場合は、変数名の前に「$」を付ける。

 %set a 1  ←変数aに値「1」を格納
 %set b $a  ←変数bに変数aの値(つまり「1」)を格納
 1  ←値「1」が格納された

 また複数のデータを配列として変数に格納したいときは、「{}」(波カッコ)で囲む。

 %set a {1 2 3 4}  ←配列aに値「1」「2」「3」「4」を格納
 1 2 3 4  ←値「1」「2」「3」「4」が格納された

 「[]」(角カッコ)や「""」(二重引用符)で囲むと、1つの要素と見なされる。たとえばコマンドラインを「[]」で囲んで引数として渡すと、囲み内のコマンドラインを先に実行したうえで、その結果の値を引数として使う。この仕組みを「ダブル置換(Double Substitution)」と呼ぶ。なおダブル置換の囲みは何重もの入れ子構造にすることができ、その場合は一番内側にある囲み内のコマンドラインから順に実行される。

 %set a [expr 2 + 3]  ←「2+3」の計算結果を変数aの値に格納(ダブル置換)
 5  ←計算結果の値「5」が格納された

 そのほか、BIG-IP/iRule独自のコマンドとして「TCP::respond」や「HTTP::respond」といったものもある。これらは、引数に指定された文字列をブラウザにレスポンスするコマンドだ。

 ダブル置換は、複雑な処理を行うスクリプトを書くうえで便利な機能である。だが、スクリプト処理の中でまず囲み内のコマンドラインが「実行」されるため、攻撃者が何らかの方法でそこに不正なコマンドラインを挿入できた場合に、BIG-IPは図らずも不正なふるまいをしてしまうことになる。簡単に言えば、ダブル置換の中で変数を扱っており、外部からその変数に予期しない値(コマンドライン)を渡すことができれば、たやすく不正なコマンドを実行できてしまう。

 現実にこれが攻撃に悪用できるかどうか。ジャーカビー氏はまず、BIG-IPが設置されたWebアプリケーション環境で、外部からinfoコマンド(Tcl実行環境の各種情報を取得するコマンド)などを実行させて、iRuleスクリプトの内容を抜き出すことを試みた。ちなみにBIG-IPが設置されたWebサイトは、HTTPのレスポンスヘッダから簡単にわかり、F-Secureの独自調査では、Web上で世界30万台以上のBIG-IPが実稼働しているという。

HTTPレスポンスヘッダを見れば、BIG-IPが設置されたサイトであることがわかる

 攻撃デモは、ブラウザとWebアプリケーション間の通信内容を可視化するプロキシツール「Burp Suite」を使って行われた。まず、Webアプリケーションのログアウト操作時にブラウザから送信されるリクエスト内容をチェックして、そこに「logged out」という文字列を発見した。これはセッションIDの値として、ログアウト状態にあるブラウザのCookieにセットされる文字列だ。

 ここでCookieの「logged out」を「[TCP::respond [info level 0]]」という文字列に書き換えてリクエストを送信すると、BIG-IPは「[]」内のコマンドラインを実行してしまった。その結果、レスポンスにはBIG-IPで実行中のiRuleスクリプト(Cookie処理に関する内容)が挿入されて返ってきた。これにより、BIG-IPでどんな制御が行われているのかが“丸見え”になり、次の攻撃の足がかりができる。

Cookieデータにinfoコマンドを挿入すると、通常のレスポンスの前に実行されたiRuleスクリプトの内容が含まれて戻ってきた(オレンジの強調部分)

格納されたキャッシュを上書きしてMITM攻撃を仕掛ける

 次はいよいよBIG-IPを乗っ取る方法を考える。ターゲットとする侵害ポイントは「セッションテーブル」だ。

 セッションテーブルは、ブラウザとWebサーバー間のセッションを一時的にキャッシュしている一覧表(テーブル)だ。具体的にはKey-Valueストアのようなもので、テーブルの内容はすべてのBIG-IPインスタンス間で同期されている。そしてテーブルの内容は「table」コマンドを使って操作できる。

 だが、攻撃者がこれを悪用できたらどうなるのか。たとえば「table lookup admin」コマンドで特定ユーザーのCookieを探し出し、そこに保存された認証情報を不正取得したり、そのCookie自体に不正なコードを上書きして実行させたりすることもできてしまう。

 デモでは、Webアプリケーションとして提供されているDNS lookupサービスを介して攻撃を行う手法が紹介された。「GET /dns?host=(ホスト名)」というリクエストを送ればサーバーがDNSクエリを実行し、IPアドレスをレスポンスするような簡単なサービスをイメージしてほしい。ただし同じホスト名の問い合わせは、すでにBIG-IPがテーブルにキャッシュしてある内容がレスポンスされる。

 ここでジャーカビー氏はまず、クエリのパラメーターとして「[TCP::respond [info level 0]]」という、ダブル置換を使ったコマンドラインを送信してみた。すると、BIG-IPで実行されているiRuleスクリプトがレスポンスに含まれるかたちで返ってきた。つまり前出の例と同様に、外部からinfoコマンドが実行できたわけだ。

 続いて、このiRuleスクリプトから「eval」コマンドが使われている行を探す。同氏によると、eval(連続する引数を1つのコマンドラインとして解釈、実行)、subst(バックスラッシュ、コマンド、変数を置き換える)、expr(角カッコ内をコマンドラインと解釈して実行)という3つのコマンドは、ほかのコマンドを実行する性質を持つことから、コマンドインジェクション先として「特に魅力的だ」という。

DNSサービスのリクエストパラメーターを介してinfoコマンドを実行させ、表示されたiRuleスクリプトから「eval」コマンドが使われている行を探す

eval、subst、exprといったコマンドは、ほかのコマンドを実行する機能を持つため、iRuleスクリプトで使う場合には特に注意が必要だ

 evalコマンドを使っている行を見つけたら、キャッシュの内容をどのように扱っているかを確認する。前掲画面にある1つめのevalを含む行(「HTTP::respond 200 -content [eval [table lookup~」のコマンドライン)が、テーブルにキャッシュ済みの内容をレスポンスするものだと分かった。ブラウザからのリクエストに含まれるパラメーター(ホスト名)が、そのまま変数「host」で参照されているらしいことも分かる。

 そこで、今度はリクエストのパラメーターに「host=localhost; table set -subtable "cache" localhost [TCP::respond owned]」を指定して送信してみる。最初の「localhost」はクエリ対象のホスト名だが、ここでは「;」以後に新たなコマンドラインを書き足している。具体的にはテーブルを書き換える「table set」コマンドを実行し、localhostのクエリ結果の冒頭に「owned」という文字列を挿入するという内容だ。もしもこのiRuleスクリプトがパラメーターの内容をチェックしていなければ、このコマンドラインがそのまま「$host」部分に挿入(インジェクション)されて実行されるだろう。

 再びDNSサービスに「host=localhost」を指定してクエリを投げてみると、レスポンスの頭に「owned」の文字列が挿入された形で返ってきた。つまり、外部のブラウザからテーブルのキャッシュを上書きすることができたわけだ。

 テーブルのキャッシュ内容を書き換えるこの攻撃手法を応用すれば、ユーザーからのリクエストに対して本来のキャッシュ内容ではなく、攻撃者が書いた偽のレスポンスを返すMITM攻撃(Man-In-The-Middle、中間者攻撃)が可能になると、ジャーカビー氏は説明する。

BIG-IPのキャッシュを書き換える攻撃デモ。キャッシュされているレスポンスの冒頭に「owned」の文字が書き足されている

カテゴリートップへ

  • 角川アスキー総合研究所
  • アスキーカード