Struts 2[1]はMVC(Model/View/Controller)モデルに基づくJava言語のWebアプリケーション開発用フレームワークである(図1).
Struts 2は脆弱性が多く,2016年以降から本稿執筆時点(2018年7月24日)までで,30件の脆弱性が見つかっている[2].Struts 2の脆弱性が見つかると,Struts 2を利用しているWebアプリケーションが攻撃を受ける可能性があるため影響範囲が広い.また,Struts 2はオープンソースであり,脆弱性が公開されると数時間で攻撃コードが公開され,攻撃が開始されることがある.そのため,被害が発生する前に開発者がセキュリティパッチを配布し,運用者がそれを適用することが難しい状況にある.Webアプリケーションに対する攻撃の防御策として,予め定義したシグネチャ☆1に基づいて不審なリクエストを遮断するシグネチャベースのWAF☆2やフィルター[3]が挙げられる.ただし,製品によってはネットワーク構成の変更などが必要になり,導入が難しい場合もある.また,シグネチャに基づいた検知の課題として,シグネチャ更新が間に合わないこともあり,文献[4]の事例では約72万件の個人情報が漏洩している.さらに,Webアプリケーションの内容やユーザが送信するリクエストの特徴によっては,誤検知が発生し,正規のリクエストを遮断してしまう可能性や見逃しが発生する可能性がある.そこで本稿では,リクエストに含まれる文字列に対してディープラーニングの処理を実行して,特徴的なリクエストを検知することにより,正規のリクエストとStruts 2の脆弱性を悪用する攻撃リクエストを見分ける手法を提案する.本稿では,Struts 2の脆弱性の中でも,近年特に多く見られるOGNL[5]に起因する脆弱性に着目する.さらに,Struts 2サーバで標準で利用できるサーブレットフィルタとディープラーニングを連携させることで,攻撃と判断したリクエストをリアルタイムに遮断する方法(図2)を提案する.
本章では,OGNLに起因するStruts 2 の脆弱性とその攻撃手法について述べる.
OGNLは,View(Webページ)を実装するコンテンツからModelを実装するJavaクラスにアクセスするための式言語 である.Struts 2はOGNLを用いたアプリケーションの開発をサポートしており,Struts 2内部のプログラムにおいても使われている.図3はOGNLの例で,「%{}」で囲った太字部分がOGNLである.
OGNLを使うとViewコンテンツをシンプルに実装できる一方,OGNLによって任意の Java コードを実行できるため,使い方によっては,セキュリティ問題を引き起こすリスクもある.
2016 年以降から本稿執筆時(2018年7月24日)までで,Struts 2には30 件の脆弱性が見つかっており,そのうちOGNL に起因する脆弱性は9件である.本稿では,OGNL に起因する脆弱性の中でも深刻な情報漏えいなどを引き起こす可能性が高い以下の条件に該当する脆弱性(表1)を対象とする.
(1)任意のコード実行を引き起こし,security ratingが“High”以上の脆弱性 かつ
(2)攻撃コードが公開されている脆弱性
なお,S2-046[11]も前述の条件に該当するが,S2-046はマルチパート 形式のリクエストを処理する際の脆弱性であり,サーブレットの仕様上,マルチパート形式のリクエストを読み取るのが難しいことから,本稿の対象外とする.
OGNLに起因する複数の脆弱性が存在するが,本質的な原因は共通しており,Struts 2がリクエストに含まれる文字列を意図せずOGNLとして評価してしまうことが原因である.攻撃手法にも共通点があり,OGNLを含むリクエストを送る手法が用いられる.ただし,攻撃コードが指定される部分はヘッダやボディなど脆弱性によって異なる.攻撃者はRuntime,ProcessBuilderなどの任意のプロセスを起動できるJavaの関数を実行するOGNLをリクエストにふくめて送信することで,Strutsサーバ上で任意のコマンドを実行しようと試みる.
Struts 2をはじめ,Webアプリケーションに対する攻撃を検知・防御する研究が行われている.本章ではそれらの研究について述べる.
本節では,Struts 2への攻撃の検知・防御に関する既存研究について述べる.(株)インターネットイニシアティブはStruts 2の攻撃を遮断するためのシグネチャを公開しており,OGNLを記載するための文字列「%{.*}」「${.*}」を遮断する方式を提案している[12].ただし,この方式では,S2-032,S2-037などの攻撃リクエストに上記パターンが含まれないため,誤検知が発生する.筆者らは,検知率の向上を目的にOGNLの脆弱性を悪用する攻撃リクエストに共通的に含まれる特定のJavaクラス名などを抽出した手法を提案した[3].しかし,Javaクラスやプロパティの名前が変更された場合や,攻撃者がノイズの混入や動的なコード生成などにより検知の迂回を試みた場合には,False Negative(攻撃であるにもかかわらず正常と判断すること)が発生する可能性がある.攻撃者はさまざまな手法で検知の迂回を試みる可能性があるが,典型的な例を付録Bに記載する.例1の様にスペースを混入された場合,シグネチャで「ognl.OgnlContext」という文字列をマッチングしている場合には,検知を迂回することが可能になる.例2の様に動的にコードを生成された場合,シグネチャで「java.lang.ProcessBuilder」という文字列をマッチングしている場合には,検知を迂回することが可能になる.
また,シグネチャに該当する文字列が入力される可能性があるWebサイトにおいては,正規のリクエストを遮断してしまう可能性がある.よって,正規のリクエストを疎通しつつ,より多くの種類の攻撃を防ぐことができる手法が必要である.
本節では,ディープラーニングや機械学習を用いたアノマリ検知に関する既存研究について述べる.ディープラーニングや機械学習を用いて文章やログなどの文字列を解析する構文解析について研究が行われている[13] [14] [15] [16] [17].Yoshihiro Andoらは,文章の類似性などを用いて分類するディープラーニング手法であるRNNおよび,RNNを改良したLong Short-Term Memory(以下「LSTM」)という手法を用いて,Webサイトに関するアクセスログを解析した結果,両方の手法とも高い精度での不審な挙動検知を達成している[14].また,Pankaj Malhotraらは,スペースシャトルやエンジンのデータセットに対してRNNとLSTMを用いて分析を行い,不正な挙動に関するアノマリ検知を行っている.本研究では,LSTMがRNNより高い検知率を達成している[16].Cheng Fengらは,制御システムネットワークに流れるトラフックに対して7種類のディープラーニング手法を用いた結果,LSTMが最も高い検知率となっている[15].
構文解析の手法としては,単語の出現順序を考慮する手法と考慮しない手法があり,RNNやLSTMについては順序を考慮する手法である.一方,単語の出現順序を考慮しない手法については,単語の出現頻度によって文章の類似性などを分類するBag of Words(BoW)という機械学習手法が一般的に使われており,Malek Ben Salemらは,BoWを用いて,コマンドを分析し,攻撃者が正規のユーザになりすました攻撃を検知している[17].既存の研究において,単語の出現順序を考慮した手法としてはLSTMが優れており,また単語の出現順序を考慮しない手法ではBoWが広く使われている.これらの結果を踏まえ,本稿では分析手法としてLSTMおよびBoWを採用し,検証を行うこととする.
本節では,既存手法と比較した提案手法の特徴および本稿の貢献について述べる.
・ディープラーニングを用いたリアルタイム分析と即時遮断による攻撃回避: OGNLを悪用する攻撃リクエストは,脆弱性が異なっていても,類似したパターンであることが多い.付録AにOGNLに起因する脆弱性を悪用する攻撃リクエストの例を掲載しているが,脆弱性が異なっても,OGNLを用いてJavaコードを実行するための特徴的なコード(OgnlContext,DEFAULT_MEMBER_ACCESSへのアクセスなど)や,Javaコードから外部プロセスを起動するための特徴的なコード(ProcessBuilder,Runtimeの使用など)を含んでおり,類似した攻撃リクエストが用いられていることが分かる.したがって,ディープラーニングで特徴的なリクエストを検知することで,検知が迂回されたり,Struts 2の未知の脆弱性を悪用する攻撃が行われた場合においても,検知できる可能性が高い.さらに,サーブレットフィルタと連携させ,攻撃と判断したリクエストをリアルタイムに遮断することで,攻撃を回避することが可能である.
・実運用に耐え得る性能を達成:提案手法の導入によるWebサイトの応答時間の増加は,実運用に耐え得るレベルであることを評価で確認済である.
・導入が容易かつ低コスト: Struts 2サーバ上で標準で利用できるサーブレットフィルタの機能を使用して,攻撃リクエストの遮断を行うため,商用WAFと比べて,比較的低コストかつ容易に既存システムに導入することができる.また,シグネチャを更新する必要がないため,運用コストを削減できる.
本稿では,ディープラーニングを用いて,Struts 2に対するリクエストを正規のリクエストであるか攻撃リクエストであるかを判別し,攻撃リクエストと判断した場合,サーブレットフィルタの機能を用いて,リクエストをリアルタイムに遮断する手法を提案する.
ディープラーニングとは大量の入力データから特徴を特徴モデルとして抽出し,未知のデータを解析する技術である.入力データと期待する出力(正解ラベル)を用いて学習する手法を教師あり学習と呼ぶ.Struts 2の脆弱性を悪用する攻撃リクエストが公開されているため,本稿ではそれらの攻撃リクエストと正規のリクエストを学習データとして,教師あり学習を行い,正規のリクエストと攻撃リクエストを分類する.
サーブレットはJavaで実装されたWebアプリケーションのサーバサイドプログラムで,MVCモデル☆5ではControllerの役割を持つ.サーブレットフィルタは,サーブレットの前に実行されるプログラムで,リクエストのフィルタリング処理や,サーブレット間で共通して必要な処理などを実装するためのプログラムである(図4).
サーブレットフィルタで攻撃の可能性があるリクエストを遮断することで,攻撃リクエストがModelに届くことを防ぐことができる.
提案手法は,以下2つのサーバで構成される.
・Strutsサーバ:Struts 2を使用するWebアプリケーションおよび防御用のサーブレットフィルタが稼働するサーバ
・AIサーバ:リクエストの特徴に関する学習モデルを保持し,入力された文字列が正規のリクエストであるか,攻撃リクエストであるかを判定して,結果を返却するサーバ
提案手法の処理の流れを図5に示す.
本節では,提案手法におけるディープラーニングのための前処理について記載する.
本節では,ディープラーニングを用いた検知アルゴリズムの詳細について述べる.
● ディープラーニングの手法
提案手法では,リクエストに含まれる文字列に対してディープラーニングを適用する.構文解析の手法として,1)単語の順番を考慮しない手法 および2)単語の順番を考慮する手法に分類される.本稿では,両手法を適用し,結果を比較する.
1)の具体的手法としては,単語の出現頻度によって文章の類似性などを分類するBag of Words(BoW)を用いる.2)の主な手法として,RNNとLSTMが存在する.RNNでは入力データが長いと,うまく学習モデルを更新できない勾配消失という事象が発生するのに対し,勾配消失を緩和した手法LSTM[18]は,既存研究でも高い検知率を達成してるため,本稿ではLSTMを採用する.
● 学習の方法
正規のリクエスト,および攻撃リクエストそれぞれに教師データを付与する(表3).Struts 2の攻撃に対する特徴を学習させることで,未知のリクエストを入力した際に特徴モデルと比較を行い,それが正常であるか攻撃であるかを分類することができる.本稿では,攻撃リクエストとして,対象とする脆弱性の中で最も過去に公開されたS2-032の脆弱性を悪用する攻撃リクエストを学習させる.
ディープラーニング用プログラムの実装には,Python上で動作するディープラーニングライブラリであるKerasを用いる.一方,サーブレットフィルタはJavaで実装する必要があり,異なるプログラミング言語で実装されたシステム間で連携を行う仕組みとして,表5に示す実装方式を比較検討する.性能を比較した結果,より高速なREST APIを採用することとする.比較結果の詳細は第6.3.3項に記載している.
本節では,提案手法で使用するサーブレットフィルタの実装方式について述べる.
● 防御用サーブレットフィルタの実装
防御用のサーブレットフィルタとして利用するJavaクラスを作成する必要がある.javax.servlet.Filterインタフェースを実装し, doFilterメソッドにリクエストのフィルタリングロジックを定義することで,特定の条件に該当するリクエストを許可したり,遮断することができる.提案手法では,防御用のサーブレットフィルタからディープラーニングの処理を呼び出し,判定結果によって,リクエストの許可,遮断を行う.サンプルプログラムは[19]に公開している.
● 検査対象
サーブレットフィルタはリクエストメッセージの内容を取得する機能を持ち,これを利用してリクエストメッセージを検査する.攻撃コードはリクエストメッセージの様々な部分に指定されることが分かっているため,表2に示すリクエストメッセージの項目を検査対象とする.
● サーブレットフィルタの適用
作成したサーブレットフィルタを使用して防御するためには,対象 Webアプリケーションのweb.xml☆8に防御用サーブレットフィルタの設定を追記する.注意事項として,サーブレットフィルタは複数定義することが可能で,定義した順に実行される.防御用サーブレットフィルタは全てのサーブレットフィルタの前に定義する必要がある.web.xmlの例を[19]に公開している.
評価環境は表6の通りである.
本節では,提案手法の有効性を検知率と性能の観点から評価する.検知率に関しては,表7に示すパターンで検証を行う.
性能に関しては,表5に示すパターンで検証を行う.
提案手法を用いた攻撃リクエストの検知精度を評価するために,学習するデータと評価に用いるデータを分離する(表3).公開されているS2-032の脆弱性の攻撃コードを用いて送信したリクエストを学習データとし,攻撃データとして学習させる.脆弱性の悪用が成功した際に実行するコマンドを変化させ,複数の攻撃リクエストを学習させる.その他の脆弱性(S2-033, S2-037, S2-045, S2-048)の攻撃リクエストについては,学習データからは除外し,評価のために使用する.評価データについても,実行するコマンドを変化させて,複数の攻撃リクエストを評価する.検証の結果を以下のように分類する.
検知精度は以下のように評価する.
False Positive (攻撃でないリクエストを攻撃と判断すること)の可能性に関する評価を実施する.評価に用いるデータは,既存研究で紹介されている検知用のシグネチャやJavaコードなど,False Positiveが発生する可能性が高いと考えられるデータや通常の自然言語を使用する(表8).
本提案手法の導入により,性能に対する影響が懸念されるため,性能評価として,StrutsサーバのWebアプリケーションにリクエストを送信した際の応答時間を測定する.具体的には,Strutsサーバが受信したリクエストをAIサーバに転送し,ディープラーニングの処理を行って,Strutsサーバに返却後,ユーザに応答を返却するまでの時間の測定を行う.比較対象は以下とする.
POSTリクエストで200文字(計1,788バイト)を送信した際のレスポンス時間を1,000回測定し,平均を算出する.
検知率を表9に示す.また,各脆弱性を悪用する攻撃の防御可否を表10に示す.
BoWはすべての脆弱性を悪用する攻撃を検知できた.これは,攻撃リクエストに含まれる特徴的な単語をBoWによって抽出することが出来たことが原因と考える.一方,LSTMではS2-045を悪用する攻撃リクエストは検知不可であった.これは,S2-033,S2-037,S2-048の脆弱性を悪用するリクエストが,学習データとして用いたS2-032を悪用するリクエストと類似しているのに対し,S2-045の攻撃リクエストは, OGNLの記述形式が異なるため,単語の順序を考慮するLSTMでは攻撃として見分けることができなかったことが原因と考えられる.
また,第3.1節に記載した通り,攻撃者は様々な手法で検知の迂回を試みる可能性がある.付録Bに示す様な典型的な手法によって,スペースを混入したり,動的にコードを生成するなどの検知迂回が試みられた場合,提案手法を用いて攻撃リクエストを検知することが可能であった.これは,検知の迂回が試みられた場合においても,ディープラーニングが攻撃リクエストの特徴を検知することが可能であったと考えられる.
結果を表11に示す.
結果より,JavaコードをやりとりするようなIT技術系のサイトなどの場合においても,False Positiveの発生が抑止できることが予想される.
結果を表12に示す.なお,プロセス呼び出しについては,応答時間が著しく遅かったため,測定回数を100回とした.
AIサーバをREST APIで実装した場合,適用前と比較して,レスポンス応答時間が遅くなったものの,運用に支障を与えない範囲であると考える.一方,プロセス呼び出しの場合は,レスポンス応答時間が著しく遅くなった.この結果から,CPU,メモリ等のリソースを必要とするディープラーニングの処理も,REST API化することで,性能への影響を抑えることが可能であると言える.
Struts 2はWebアプリケーションの開発において便利な反面,脆弱性が見つかった際の影響が大きい.また,攻撃が開始されるまでの期間が短く,防御するのが難しいため,運用面における防御策を適用することが重要である.本稿では,OGNLに起因する脆弱性を悪用する攻撃に着目し,ディープラーニングで正規のリクエストと攻撃リクエストを見分け,攻撃と判断したリクエストをサーブレットフィルタで遮断することで,低コストに防御する方法について提案した.特に,ディープラーニングのアルゴリズムとしてBoWを使用した場合に高い検知率を達成した.提案手法の導入により,性能が多少劣化したが,運用には支障がないレベルの劣化であることを評価で確認している.また,提案手法はStruts 2サーバ上で標準で利用できるため,WAFのシグネチャが配布されるまでの回避策としても有効であると考える.
OGNLに起因する脆弱性を悪用する攻撃は類似したリクエストが用いられる可能性が高い.付録AにOGNLに起因する脆弱性を悪用する攻撃リクエストの例を掲載しているが,脆弱性が異なっても,OGNLを用いてJavaコードを実行するための特徴的なコード(OgnlContext,DEFAULT_MEMBER_ACCESSへのアクセスなど)や,Javaコードから外部プロセスを起動するための特徴的なコード(ProcessBuilder,Runtimeの使用など)を含んでおり,類似した攻撃リクエストが用いられていることが分かる.したがって,提案手法は今後OGNLに起因する脆弱性が見つかった場合においても活用できると考える.今後は,False Negativeの調査を踏まえて,検知率向上を目指して手法を改善する予定である.さらには, 本手法を用いた以下の可能性について,継続して調査および評価を進める予定である.
・OGNL以外のStruts 2に対する攻撃の検知:本研究では,OGNLを悪用する攻撃に着目したが,Struts 2の脆弱性を悪用する攻撃は,OGNL以外にも存在し,多くは攻撃リクエストにJavaコードが含まれる[21].本研究の結果より,ディープラーニングを用いてJavaコードの特徴を抽出することに成功していることから,OGNL以外のStruts 2に対する攻撃も検知できる可能性が高いと考えている.
・SQLインジェクションなど,汎用的なWebアプリケーションに対する攻撃の検知:SQLインジェクションやOSコマンドインジェクションなどの攻撃は,リクエストに記号やコマンドの様な文字列が多く含まれることが特徴である[22].これらのパターンは通常時のリクエストには含まれないことが多いため,本手法を応用することによって検知できる可能性が高いと考えている.
本研究の評価で使用した攻撃リクエストを掲載する.攻撃リクエストはインターネットに公開されている脆弱性実証コードを使用して生成したものであり,脆弱性を悪用してサーバ上で実行するコマンドの一例として「cat /etc/passwd」を指定している.
攻撃者は以下の様な手法によって,WAF等に定義されているシグネチャを回避する可能性がある.
2004年~NECソリューションイノベータにて,ソフト開発やSIなどに従事.2015年~JPCERTコーディネーションセンターにて,脆弱性検証やログ分析に従事.2017年~東京大学情報学環にて,セキュリティ人材育成や研究に従事.
松田 亘(非会員)wataru.m@iii.u-tokyo.ac.jp2006年~NTT西日本にて,セキュリティオペレーションセンター の運用などに従事.2015年~JPCERTコーディネーションセンターにて,脆弱性検証やログ分析に従事.2017年~東京大学情報学環にて,セキュリティ人材育成や研究に従事.
満永 拓邦(正会員)takuho@iii.u-tokyo.ac.jp東京大学情報学環にて,セキュリティに関する情報収集・分析・研究,外部の組織や企業の経営層やシステム管理部門との連携などに従事.
会員種別ごとに入会方法やサービスが異なりますので、該当する会員項目を参照してください。