てきとうなメモ

本の感想とか技術メモとか

CVE2014-0094のStruts1のパッチ

パッチというか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);