パッチというかorg.apache.struts.util.RequestUtils#populateを以下のように修正すれば良さげ。
テストちゃんとやっていないので、自己責任で。
public static void populate(Object bean, String prefix, String suffix, HttpServletRequest request) throws ServletException { ... while (names.hasMoreElements()) { // Populate parameters, except "standard" struts attributes // such as 'org.apache.struts.action.CANCEL' Pattern pat = Pattern.compile("(^|\\W)[cC]lass\\W"); Matcher matcher = pat.matcher(stripped); if (!(stripped.startsWith("org.apache.struts.")) && !matcher.find() ) { properties.put(stripped, parameterValue); } } ... }
(追記)
- 見た感じ、struts1.1,1.2,1.3でRequestProcessor→RequestUtilsの部分のコードはほぼ同じなので、同じ修正を加えればそれぞれのバージョンで対策済みになりそう。
- 上記のコードは毎回Patternをコンパイルしているので効率は悪い
- あくまでObject#getClass()を防ぐことができるだけであって、ObjectやActionFormのgetter/setter経由で何かを設定される可能性は0ではない。
- 今のところ、Objectのgetter/setterはgetClassのみだけども。
- リフレクションでObjectとActionFormのgetXXX/setXXXのXXXのリストを抽出→XXXのどれかにマッチしたら除外する、が頑健なやり方かな。ObjectやActionFormの仕様が変化しても対応できる
- ActionFormのプロパティのデータ型が実はObject以外のクラスを継承していてそのクラスのgetter/setterを呼ばれるという可能性もあるけど、これはアプリ作成者側が気をつけるべきことかな
- ObjectとActionFormのメソッドを正規表現で防ぐならば以下で良さげ
- たぶんCASE_INSENSITIVEはいらない気がするけど
Pattern.compile("(^|\\W)(class|servlet|servletWrapper|multipartRequestHandler)(\\W|$)", Pattern.CASE_INSENSITIVE);