web-dev-qa-db-ja.com

Spring MVCでのCSRF(クロスサイトリクエストフォージェリ)保護

春のこのCSRF(クロスサイトリクエストフォージェリ)保護については、少し混乱しています。いいえ、jspとコントローラーおよびWebサービスがあります。私がやりたいのは、Webサービスレベルでトークンを検証し、トークンが一致する場合は、Webサービスを実行することです(私の場合はdb挿入を実行します)

JSPファイル

    <form:input type="text" class="form-control" path="mName" />

    <input type="hidden" name="${_csrf.parameterName}"
        value="${_csrf.token}" />

    <div class="form-action">
        <input type="submit" value="Save" class="btn btn-primary" />
    </div>
</form:form>

隠しタグも挿入しました。次に、このトークンを検証するにはどうすればよいですか。私はそこで少し迷っています。

コントローラクラスで、フォームからオブジェクトに値を取得し、Webサービスを呼び出してデータを保存します

@RequestMapping(method = RequestMethod.POST)
  public String processForm(@ModelAttribute(value = "userForm") @Valid UserForm userForm, BindingResult result, ModelMap model) {      

   //call the web service
  }
8
Ravindu

どうやら私は春のセキュリティ3.1.4.RELEASEを使用していました。ここでは、これを手動で行っています。それから私はそれを3.2.2.RELEASEに変更し、それから私はただ使用しなければなりませんでした

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />

Spring Security 3.2の新機能については、このリンクを参照してください

http://docs.spring.io/spring-security/site/docs/3.2.0.RELEASE/reference/htmlsingle/#new

3.1.4.RELEASEから3.2.2.RELEASEに変更するときは、混乱を招くリファクタリングがたくさんあることに注意してください。特にweb.xmlおよびspring-security.xmlファイル

4
Ravindu

OWASP Enterprise Security API には、CSRFに対する確実な保護を提供する非常に優れたオプションがあります。 CSRFは実際には非常に簡単に解決できます。 OWASP ESAPIは、以下のようにCSRF保護を実装するための仕様を提供します。

1。新しいCSRFトークンを生成し、ログイン時に一度ユーザーに追加して、ユーザーをhttpセッションに保存します。

これはデフォルトのESAPI実装で行われ、Userに格納されるsessionオブジェクトのメンバー変数として格納されます。

_/this code is in the DefaultUser implementation of ESAPI
/** This user's CSRF token. */
private String csrfToken = resetCSRFToken();
...
public String resetCSRFToken() {
    csrfToken = ESAPI.randomizer().getRandomString(8, DefaultEncoder.CHAR_ALPHANUMERICS);
    return csrfToken;
}
_

2。保護する必要のあるフォームまたはURLで、トークンをパラメーター/非表示フィールドとして追加します。

以下のaddCSRFTokenメソッドは、CSRF保護が必要なレンダリングされるURLに対して呼び出す必要があります。または、フォームを作成する場合、またはURLをレンダリングする別の手法(_c:url_など)がある場合は、「ctoken」という名前とDefaultHTTPUtilities.getCSRFToken()の値を持つパラメーターまたは非表示フィールドを必ず追加してください。 。

_//from HTTPUtilitiles interface
final static String CSRF_TOKEN_NAME = "ctoken";
//this code is from the DefaultHTTPUtilities implementation in ESAPI
public String addCSRFToken(String href) {
    User user = ESAPI.authenticator().getCurrentUser();
    if (user.isAnonymous()) {
        return href;
    }
    // if there are already parameters append with &, otherwise append with ?
    String token = CSRF_TOKEN_NAME + "=" + user.getCSRFToken();
    return href.indexOf( '?') != -1 ? href + "&" + token : href + "?" + token;
}
...
public String getCSRFToken() {
    User user = ESAPI.authenticator().getCurrentUser();
    if (user == null) return null;
    return user.getCSRFToken();
}
_

3。これらの保護されたアクションのサーバー側で、送信されたトークンがセッション内のユーザーオブジェクトからのトークンと一致することを確認します。

このメソッドは、servletまたはspringアクションまたはjsfコントローラー、あるいはリクエストの処理に使用しているサーバー側のメカニズムから呼び出すようにしてください。これは、CSRF保護を検証する必要があるすべてのリクエストで呼び出す必要があります。トークンが一致しない場合、偽造されたリクエストの可能性があると見なされることに注意してください。

_//this code is from the DefaultHTTPUtilities implementation in ESAPI
public void verifyCSRFToken(HttpServletRequest request) throws IntrusionException {
    User user = ESAPI.authenticator().getCurrentUser();
    // check if user authenticated with this request - no CSRF protection required
    if( request.getAttribute(user.getCSRFToken()) != null ) {
        return;
    }
    String token = request.getParameter(CSRF_TOKEN_NAME);
    if ( !user.getCSRFToken().equals( token ) ) {
        throw new IntrusionException("Authentication failed", "Possibly forged HTTP request without proper CSRF token detected");
    }
}
_

4。ログアウトおよびセッションタイムアウト時に、ユーザーオブジェクトがセッションから削除され、セッションが破棄されます。

このステップでは、ログアウトが呼び出されます。その場合、セッションが無効になり、現在のユーザーオブジェクトが匿名ユーザーにリセットされるため、現在のユーザーへの参照が削除され、それに応じてcsrfトークンが削除されることに注意してください。

_//this code is in the DefaultUser implementation of ESAPI
public void logout() {
    ESAPI.httpUtilities().killCookie( ESAPI.currentRequest(), ESAPI.currentResponse(), HTTPUtilities.REMEMBER_TOKEN_COOKIE_NAME );
    HttpSession session = ESAPI.currentRequest().getSession(false);
    if (session != null) {
        removeSession(session);
        session.invalidate();
    }
    ESAPI.httpUtilities().killCookie(ESAPI.currentRequest(), ESAPI.currentResponse(), "JSESSIONID");
    loggedIn = false;
    logger.info(Logger.SECURITY_SUCCESS, "Logout successful" );
    ESAPI.authenticator().setCurrentUser(User.ANONYMOUS);
}
_

出典: http://www.jtmelton.com/2010/05/16/the-owasp-top-ten-and-esapi-part-6-cross-site-request-forgery-csrf/ ==

これがお役に立てば幸いです。

シシル

9
Shishir Kumar