最近のお仕事で、StrutsっぽいWebアプリでGETとかPOSTパラメータ名が
foo.bar=...
みたいなドット区切りのを見かけるようになった。
PHPだと"_"に強制的に変換されてしまうのだが、Javaの世界だとどうなってるのだろう、と、数年ぶりにStrutsを触ってみた。
現在はStrutsが2.2.3まで出てる。
自分が最後に触ったStrutsは1.x系で、まさしくXML地獄となっていたのがだが、あれから多少楽になったようだ。
煩わしいForm定義から解放され、DIコンテナとの統合もなされ、洗練された印象を受ける。
で、肝心のドット区切りのパラメータについてだが、どうやらStruts2系ではパラメータの解釈でOGNLというのを使い、式評価によりJavaのオブジェクトに変換しているようだ。
例えば
user.address.city=FooBar
なら
action.getUser().getAddress().setCity("FooBar")
となり(actionというのは、Struts2ではFormを介さずに直接Actionクラス(POJO)に値を渡す形式になっているから。)、
user['favoriteDrink']=green-tea
なら
action.getUser().setFavoriteDrink("green-tea")
と解釈される。
なるほど、こりゃ楽でいいわ・・・と喜んだのも束の間。
Struts2の公式サイトのドキュメントを漁ってたら、
の"S2-005"経由で、
OGNLの式評価ではメソッドの実行やインスタンスの生成なども可能なので、悪意のあるパラメータを設定することで任意のJavaコードを実行できてしまう可能性が・・・(´・ω・`)。
ということで、最新版のStrutsを使うか、ParametersInterceptorのexcludeParamsでホワイトリストorブラックリストで受け付ける文字種を限定しましょう、というお話。
あと、OGNLとして受け付けられない不正な値が入力された場合、裏側でOGNLのparseに失敗してればログを出力してくれるので、その辺もチェックしてみると良いかも。