Strutsの脆弱性について

  • Struts脆弱性の根本原因には、ClassLoaderを直接操作できてしまう仕様に起因するものが多い。

    • 攻撃手法として、クライアントからの不正なリクエストが使われる。すなわち、脆弱性対応を理解するためには、リクエストパラメータとActionFormのマッピング方式を知ることが大事
    • Struts1.x系では、このマッピングにBeanUtilsクラスを使っているっぽい。RequestUtils#populateの中でBeanUtils#populateを呼び出している。TERAでのstruts脆弱性対応は、RequestUtils#populateに対して実施される(ことが多い?)。
  • Qiitaの記事

    • http://qiita.com/kawasima/items/670d2591bc8fea19dc1d
    • 一部引用

      RequestUtils.javaでBeanUtils.populate(bean, properties)で値を検証すること無く、populateを呼んでることに起因します。
      populateはBeanUtilsBeanのsetPropertyを順次呼び出していくわけですが、ここに問題があります。
      BeanUtilsの仕様にNestedPropertyというのがあって、要はA.B.Cとプロパティをドットつなぎで書いておくと、bean.getA().getB()と順次呼び出され、最後にsetC()で値がセットされます。ここがノーチェックなので、class.classLoader.などと書いておくと、getclass().getClassLoader()と等価であり、クラスローダにもアクセスできてしまうことになるわけです。

  • EvidenceLogFilterでリクエストパラメータのログ出力をするとき、マルチパートデータで送るとログに記録されないのは、仕様?

    • http://www.mitchy-world.jp/java/webapp/multipart.htm
    • (一部引用)

      しかし、こうするとサーバ側での処理がなかなか厄介なことになります。

      具体的には以下のような問題が起こります。
      ・通常の Request.Parameter ではパラメータを読めない
      ・アップロードされたデータはストリーム(Stream)で読み込むことになるが、一度読み込むと中身が空っぽになる
      →これが原因で サーブレット・フィルタ(Servlet Filter)でパラメータを取得してしまうとアクション・クラス(Action)ではパラメータが空になってしまう
      ・アクション・クラスで別のアクションにフォワードしてしまうとパラメータが空になってしまう

    • http://www.ecoop.net/memo/archives/2005-06-18-1.html

    • (一部引用)

      form タグで ENCTYPE=”multipart/form-data” にすると ServletRequest.getParameter(Sting) 系ではパラメータを解釈できず全く値が渡って来なくなるため、Jakarta Commons FileUpload の org.apache.commons.fileupload.DiskFileUpload.parseRequest(…) 等を使うとよい。

  • ActionFormにあるMap型のプロパティ(ここではxxxmapとする)にリクエストパラメータ「xxxmap(key)」形式でパラメータを設定すると、Mapから値を取り出すとき「getXxxmap().get("key")」の戻り値は配列となる(Stringで取り出す場合はString[]でキャストする)

  • get(set)MultipartRequestHandler()はActionFormに実装されているので、ValidatorActionFormExでもDynaValidatorActionFormExでも除去される(ポピュレートされない)。

    • これ(以下)、間違いでは???DynaValidatorFormにも実装されてるはず。

      get(set)ValidatorResults()はValidatorFormに実装されているため、(ValidatorFormを継承していない)DynaValidatorActionFormExを使ったときは除去されない(ポピュレートされる)。
      ⇒struts1.2.9-sp3のRequestUtils#populateでリクエストパラメータの「ValidatorResults.」を除去するロジックは、引数のbeanがValidatorFormのときのみ処理を行う。そもそもDyna~を使うときは除去の必要がないため。

  • CVE-2016-1182がDyna**Formに影響しない理由

    • 【仮説】 ・ValidatorFormの実装に依存? ・Dyna**Formの場合、リクエストパラメータでValidatorResultsを改ざんできない? ⇒なぜ?