写真1●サンプルのトップページ
写真1●サンプルのトップページ
[画像のクリックで拡大表示]
写真2●リクエストに含まれたjavascriptが実行されてしまう
写真2●リクエストに含まれたjavascriptが実行されてしまう
[画像のクリックで拡大表示]

 11月末に,Strutsにクロスサイト・スクリプティングの脆弱性が報告された。今回は,この脆弱性についての原因と対策を紹介する。

Struts1.2.7を含むこれまでのリリースすべてに影響

 報告されたクロスサイト・スクリプティング(以降XSS)に関する脆弱性はStruts1.2.7を含むこれまでのリリースすべてに共通したものだ。XSSについての詳細は(IT Proの解説記事)を参照していただきたい。

 この脆弱性が利用された場合,Strutsで構築されたサイトを参照したユーザーが,被害に遭う可能性がある。具体的には,悪意のある第三者が記述した,Strutsで構築したサイトへのリンクをクリックした場合,ユーザーのファイルの削除や,情報漏えいなどの現象が発生する危険がある。ただし,この現象は特定のアプリケーションサーバー(およびWebコンテナ)でのみ発生すると,報告されている。

原因はSturtsのエラーメッセージ

 この脆弱性の原因はSturtsのエラーメッセージの表示方法にあった。Strutsは,定義のないURLに対するリクエストが行われた場合,そのURLを含んだ文字列をエラーメッセージとして返却するようになっていた。例えば, http://<host>/<AppName>/UNKNOWN.do というリクエストに対するアクションマッピング(リクエストパスと処理の対応を定義したもの)の定義がない場合,Strutsは

400 Invalid path /UNKNOWN was requested

というレスポンスを返却する(注:Struts1.2系は別のエラーコード)。このとき表示している UNKNOWN は,リクエストにて送信したパス文字列がそのまま利用されていた。このリクエストパスをスクリプトに置き換えることによってクロスサイト・スクリプティングが行えてしまうのだ。

脆弱性の検証

 筆者は,この現象が報告されている アプリケーションサーバー Resin 3.0.15を用いて,Struts1.0.2 および Struts 1.2.7 のサンプルアプリケーション struts-blank.warにて検証を行ってみた。struts-blankアプリケーションは,Strutsアプリケーションのテンプレートの役割をなすサンプルで,多くのStruts利用者がこのサンプルをベースにアプリケーションを構築しているものだ。

 struts-blankをResin3.0.15にデプロイし,サンプルのトップページ(http://localhost:8080/struts-blank/)にアクセスすると(写真1)のような正常なトップページが表示される。次に,このアプリケーションに対して,下記のようなポップアップが表示されるスクリプトを含むリクエストパスを送ってみた。

http://localhost:8080/struts-blank/<script>alert('XSS test')</script>.do

 その結果(写真2)のように,リクエストを送信したブラウザでスクリプトが実行されてしまった。非常に危険な状態である。

 報告されている 本脆弱性が露呈するアプリケーションサーバーはWebLogic 8.1 SP4,WebLogic 8.1 SP5,Resin Web Server となっているが,すべてのアプリケーションサーバーに対する調査が行われている訳ではないため,Strutsを使ったアプリケーションを構築した場合には早急に調査が必要と思われる。

 一方,Tomcat5.5.9と5.5.12では問題ないとの報告が挙げられている。筆者は,Tomcat4.1.31にて同様の検証を行ってみたが問題はなかった。これは,アプリケーションサーバーがアプリケーションがHTTPエラーを返却した際の動作の違いが起因していると思われる。

対策は3つ

 では,この脆弱性を修正するにはどうすればよいのだろうか。その方法は3つある。それぞれを紹介してゆこう。

  • アクションマッピングを追加する

     Strutsには定義のないアクションマッピングに対するリクエストが行われた場合,そのリクエストを処理するデフォルトのアクションマッピングを定義する機能が用意されている。このアクションマッピングを用意すれば,どのようなリクエストが送られても,すべては処理され HTTP エラーを発生する事はなくなり,結果として脆弱性を防ぐことができる。

     デフォルトのアクションマッピングの定義は非常に簡単だ。下記のように,unknown属性をtrueにしたアクションマッピングをモジュールに1つ用意すればよい。

    
    リスト1●struts-config.xml抜粋
    
    <struts-config>
      <action-mappings>
        <action   path="/unknown"
                  forward="/PageNotFoundError.jsp"
                  unknown="true" />
        ...略...
      </action-mappings>
    </struts-config>
    
    注)PageNotFoundError.jsp は別途用意する必要がある
    
    このようにすることで,不明のリクエストは path="/unknown" のアクションマッピングにて処理されることになり,Strutsが生成するエラー表示はされなくなる。

  • Webコンテナの設定を変える

     もう1つの方法は,Webコンテナに対する設定を行い,HTTPエラー時に表示するページを定義する方法だ。この方法はWebデプロイメントディスクリプタ(web.xml)にHTTPエラーのコードに対応して表示するページを定義する。アクションマッピングの定義がないリクエストが送信された場合,Struts1.2系では HTTPエラーコード404(Not Found)が,Struts1.0系では 400(Bad Request)が発生するため,それぞれを下記のようにweb.xmlに定義すればよい。

    
    リスト2●web.xml抜粋
    
      <error-page>
        <error-code>404</error-code>
        <location>/PageNotFoundError.jsp</location>
      </error-page>
      <error-page>
        <error-code>400</error-code>
        <location>/PageNotFoundError.jsp</location>
      </error-page>
    
    注)PageNotFoundError.jsp は別途用意する必要がある
    
     このようにすることで,不明のリクエストは/PageNotFoundError.jspに転送されることになり,Strutsが生成するエラー表示はされなくなる。

  • Struts 1.2.8へバージョンアップする

     Struts開発チームでは,脆弱性の報告を受けて対策を施したStruts1.2.8をリリースした。このバージョンでは,HTTPエラー発生時のメッセージ表記方法を変更することによって,脆弱性に対する対策が行われている。

    まとめ

     今回のStruts XSS脆弱性はStrutsの利用がWebアプリケーションのデファクトとなっているだけに,その影響は大きいだろう。しかし,その対策は前述したように簡単な記述で済むので,早急に対応をするべきだろう。

     既に開発が終了しているアプリケーションなどでは,Strutsのバージョンアップという選択は困難かもしれない。その場合,「アクションマッピングを追加する」「Webコンテナの設定を変える」のいずれかの方法をとるのがよいだろう。

    ◎関連資料
    Strutsのサイト
    Struts XSS脆弱性の報告

    ■著者紹介
    黒住幸光(くろずみ ゆきみつ)氏
    株式会社アークシステム システム構築スペシャリスト。1995年,スーパー・コンピュータ向け言語処理環境の研究中に,生まれて間もないJavaと出会う。のちにJavaに専念するため転職を決意。現在,株式会社アークシステムにてオープンソース・ソフトウエアを用いたWWWシステムの構築,コンサルティングを行うかたわら,雑誌への執筆,StrutsユーザーMLの管理,Ja-JakartaプロジェクトTurbine翻訳の取りまとめなど幅広く活動中。著書に「Apache Strutsハンドブック」(発行:ソフトバンクパブリッシング)がある。メール・アドレスは,yukimi_2@yahooo.co.jp