Help us understand the problem. What is going on with this article?

S2-020類似攻撃のStruts1での対策方法

More than 5 years have passed since last update.

恐ろしいことですが、実装が全然違うStruts2の脆弱性S2-020と同様の攻撃手法で、Struts1も脆弱性があることが分かりました。
http://www.lac.co.jp/security/alert/2014/04/24_alert_01.html

ここではあまり明らかになっていませんが、原因は

https://github.com/apache/struts1/blob/STRUTS_1_2_BRANCH/src/share/org/apache/struts/util/RequestUtils.java#L493

RequestUtils.java
        // Set the corresponding properties of our bean
        try {
            BeanUtils.populate(bean, properties);
        } catch(Exception e) {
            throw new ServletException("BeanUtils.populate", e);
        } finally {
            if (multipartHandler != null) {
                // Set the multipart request handler for our ActionForm.
                // If the bean isn't an ActionForm, an exception would have been
                // thrown earlier, so it's safe to assume that our bean is
                // in fact an ActionForm.
                ((ActionForm) bean).setMultipartRequestHandler(multipartHandler);
            }
        }

BeanUtils.populate(bean, properties)で値を検証すること無く、populateを呼んでることに起因します。

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

なので、対策としてはStruts1というよりは、commons-beanutilsにチェックロジックを入れるべきかと思います。逆にいうとStruts1使っていなくても、commons-beanutilsのpopulateをユーザ入力値ノーバリデーションで使っていれば、同じ脆弱性が存在することになります。

commons-beanutilsのバージョン1.8.xからは、このプロパティを辿っていくロジックが定義できるようになりました。したがって、これを置き換えてしまえば、脆弱性はなくなるはずです。

https://gist.github.com/kawasima/11275430

(4/30 修正) nakamura-toさんにオシャレにしていただいたのでそちらをお使いください。
https://gist.github.com/nakamura-to/11347570

package example;

import org.apache.commons.beanutils.expression.DefaultResolver;

public class SafeResolver extends DefaultResolver {

    @Override
    public String next(String expression) {
        String property = super.next(expression);
        if ("class".equalsIgnoreCase(property)) {
            return "";
        }
        return property;
    }
}

(4/30 追記)
上記のBeanUtilsに対する修正は、Struts1だけでなく独自にユーザ入力値をBeanにマッピングするような処理にも有効ですが、ことStruts1だけの対応であれば、以下に示すようにRequestProcessorを置き換えることで脆弱性対応可能です。
古いシステムに対してBeanUtilsのバージョンアップがちょっとハードル高い(対応に時間がかかる)という声があったので、そういう場合にお使い頂ければよいかと思います。

@yuuyu さんからの指摘を受けて書き直しました。

https://gist.github.com/kawasima/c22a1c706656e4004d41

これで、struts-config.xmlで、このRequestProcessorを使うようにしておけば、悪意のあるパラメータにはServletExceptionがthrowされるようになります。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE struts-config PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
        "http://struts.apache.org/dtds/struts-config_1_2.dtd">

<struts-config>
    <controller processorClass="example.SafeRequestProcessor"/>
</struts-config>

そしてこれであれば、本記事のコメントServletFilterによる対処で指摘のあったMultipartリクエストに対しても、有効かと思います。


ちなみに、SAStrusはpublicフィールドもプロパティとして扱うため、BeanUtilsは使っていなく、かつ、
SnapCrab_NoName_2014-4-25_10-58-36_No-00.png

という状況なので、おそらく大丈夫かと思われます。

(4/30 追記) ひがさんからSAStrutsは大丈夫という声明が発表されております。
http://d.hatena.ne.jp/higayasuo/20140425/1398403491

kawasima
Clojure関連のことをブログがわりに書き綴ります。 ※ここでの発言はシステムエンジニアを代表するものであって、所属する組織は二の次です。
https://github.com/kawasima/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした