2011-11-17 14 views
25

私が仕事をしている製品は、潜在的な顧客からの厳しいセキュリティ監査を受けて、認証が行われる前にTomcatがJSESSIONIDクッキーを設定すると怒っています。つまり、Tomcatはステートレスなログインページが読み込まれたときに、ログイン前にこのCookieを設定します。 (認証が起こったの前に、すなわち) ログイン後にJSESSIONIDクッキーをリフレッシュする方法

  • は、ログインページ上の最初の場所に設定されているからJSESSIONIDクッキーを防ぐログイン後

    1. 問題新しいJSESSIONIDクッキー:

      彼らは、次のいずれかを示唆します

    私はこのサイトのJSESSIONID関連のすべてを掘り下げており、簡単な答えは見つけられません。私はちょうどいくつかのアイデアを期待しています。それぞれの私の最善の解決策は以下のとおりです。

    1. 右ログイン後、要求と関連付け、値をコピー、新しいものを作成し、古いセッションを無効に、すべての属性をコピーして、セッション(マイナスID)をクローンそれが働くことを期待しています。
    2. サーブレットを作成するログインページが最初にロードされる前にJSESSIONIDクッキーを取り除くチェーンの最後にフィルターをかけます。そして、JSESSIONIDが設定されていない状態でログインリクエストがうまくいくことを願ってください。

    私は睡眠を取らなければなりませんが、午前中にこれらを試みます。私よりもはるかに賢い人からのフィードバックやより良い提案を得ることは素晴らしいことでしょう - あなたのように!

    それにかかわらず、他の多くの人が同様のことをしたいと思っているように私は結果をここに掲載します。

  • 答えて

    34

    あなたは直前に更新することはありません。ログインアクションを実行するときに最初に実行します。

    HttpSession session = request.getSession(false); 
    if (session!=null && !session.isNew()) { 
        session.invalidate(); 
    } 
    

    は、その後の操作を行います。

    HttpSession session = request.getSession(true); // create the session 
    // do the login (store the user in the session, or whatever) 
    

    がFYIあなたがこのトリックで解決されていることhttp://www.owasp.org/index.php/Session_Fixation

    ある最後に、あなたは、セッションの自動作成を無効にすることができますし、唯一の作成あなたが本当にそれを必要とするときのセッション。JSPを使用している場合は、次のようにします。

    <%@page contentType="text/html" 
         pageEncoding="UTF-8" 
         session="false"%> 
    
    +0

    面白いもの。私はWicket 1.3を使用していますが、 'session = false'(ビュー側はJSPベースではありません)を設定する方法を見つけることができません。私は今getSession(false)のアイデアを試してみるつもりです...ありがとう! –

    +0

    ログイン前にセッションを無効にするとWicketの混乱が起こります(ログインページにリダイレクトされます)。それでもまだまだ... –

    +1

    @RichardsonHeights:https://issues.apache.org/jira/browse/WICKET-1767を見てください。それは文書化され、解決されたようだ。 – cherouvim

    1

    JSESSIONIDがブラウザに表示されているか、Cookieにまったく設定されていないという問題がありますか?私はそれがあなたの場合の後者であると仮定しています。

    1.issueログイン

    後の新しいJSESSIONIDクッキー

    あなたはログイン時にHTTPからHTTPSに切り替えた場合、これがデフォルトのTomcatの動作です。古いものは破棄され、新しいものが生成されます。

    ログイン自体がHTTP経由であれば、私は会計監査人のための別のセキュリティ問題だと思う;)

    またはHTTPS上で、すべてのページがありますか?

    +0

    JSESSIONIDクッキーがブラウザに設定され、Firefoxクッキービューア(たとえば)に表示されるという問題があります。 cherouvimが上で指摘したように、それは「セッション固定」のセキュリティホールです。 http/httpsスイッチに興味があります...しかし、アプリケーションはhttpsでしか動作しません。 –

    1

    他にも役立つことが2つあります。

    1. Apache Wicketを使用している場合は、バージョン1.4以降の解決策があります。私のアプリはまだ1.3になっているので、わかりませんでしたが、自分のWebSessionクラスで簡単に移植することができました。 Wicket 1.4はreplaceSession()メソッドをWebSessionに追加します。これはうまく機能します。あなたは認証の直後にそれを呼び出すことができ、新しいJSESSIONIDを取得します。それは基本的に私にとってこの問題を解決しました。詳細はこちらhttps://issues.apache.org/jira/browse/WICKET-1767

    2. バージョン5.5.29以降で使用可能なApache Tomcatバルブがあり、これをcontext.xmlに追加できます。認証後に新しいJSESSIONIDの発行を処理します。詳細はこちらhttps://issues.apache.org/bugzilla/show_bug.cgi?id=45255をご覧ください。バルブのエントリは次のようになります。<Valve className="org.apache.catalina.authenticator.FormAuthenticator" changeSessionIdOnAuthentication="true"/>

    4

    私は十分なポイントを持っていないとして、上記の@ cherouvimの答えにコメントすることはできません。新しいセッションIDは、セッションの固定を避けるために、ユーザーが正常にログインした後に設定する必要があります。私は自分の推理を説明しようとします。

    セッション固定とは、攻撃者が何らかの形でユーザーを攻撃して、攻撃者が知っている値を使用することを意味します。簡単にするために、攻撃者がユーザーの机に移動し、Firebugを使用してユーザーのCookieを編集したとします。ユーザーがログインすると、攻撃者が制御するCookieでログインします。攻撃者はこの値を知っているため、ブラウザを更新し、そのセッションID(犠牲者のリソース)にマップされたリソースがそれらに配信されます。それがセッションの固定です。正しい?

    犠牲者のユーザーがログインする前にsession.invalidateを実行したとします。Cookieの初期値はabcです。 session.invalidateを実行すると、値abcはサーバーのセッションから削除されます。

    ここで私が反対する部分があります。ユーザーが実際にログインする前に新しいセッションを生成することをお勧めします(ユーザー名とパスワードを入力して送信をクリックします)。これにより、間違いなく新しいCookieが生成されますが、ログインする前にユーザーのブラウザに表示されます。そのため、攻撃者が再び「プレログイン」Cookieを編集できる場合、ユーザーがログインしても同じCookieが使用されるため、攻撃は継続します。

    これは正しいフローだと思います。

    • ユーザーがどんなクッキーとGETの/login.html
    • 戻るログインページがブラウザに現在存在しない
    • ユーザーの資格情報とクリックが
    • アプリケーションがあることを見つけることに資格情報
    • を検証提出入り資格情報が正しい。 session.invalidate()が実行され、古いCookieが破棄されます。
    • NOWこれが何を意味するのかでrequest.getSession(真)

    を使用して、新しいクッキーを生成するには、攻撃者が前のログインに制御値を使用してにあなたをだまして管理していても、あなたがしているということですまだ保護されています。あなたがログインした後でアプリケーションが強制的に値を変更すると、私は古いセッションから新しいセッションを再生成するために以下の方法を踏襲しているhttps://blog.whitehatsec.com/tag/session-fixation/

    3

    - ここ

    は、この問題についての良いブログです。あなたがそれから恩恵を受けることを願っています。

    private void regenerateSession(HttpServletRequest request) { 
    
        HttpSession oldSession = request.getSession(); 
    
        Enumeration attrNames = oldSession.getAttributeNames(); 
        Properties props = new Properties(); 
    
        if (attrNames != null) { 
         while (attrNames.hasMoreElements()) { 
          String key = (String) attrNames.nextElement(); 
          props.put(key, oldSession.getAttribute(key)); 
         } 
    
         //Invalidating previous session 
         oldSession.invalidate(); 
         //Generate new session 
         HttpSession newSession = request.getSession(true); 
         attrNames = props.keys(); 
    
         while (attrNames.hasMoreElements()) { 
          String key = (String) attrNames.nextElement(); 
          newSession.setAttribute(key, props.get(key)); 
         } 
        } 
    
    -1
    session=request.getSession(true); 
    Enumeration keys = session.getAttributeNames();  
    HashMap<String,Object> hm=new HashMap<String,Object>(); 
    while (keys.hasMoreElements()) 
    { 
        String key = (String)keys.nextElement(); 
        hm.put(key,session.getValue(key)); 
        session.removeAttribute(key);  
    } 
    session.invalidate(); 
    session=request.getSession(true); 
    for(Map.Entry m:hm.entrySet()) 
    { 
        session.setAttribute((String)m.getKey(),m.getValue()); 
        hm.remove(m); 
    } 
    
    0

    春使用して、あなたはSessionFixationProtectionStrategyを使用する必要があります。 source codeを検査する場合

    <property name="sessionAuthenticationStrategy" ref="sas"/> 
    ... 
    <bean id="sas" class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"/> 
    

    、あなたはこれがharsha89のアプローチに似ていることがわかります:それは

    1. が新しいセッションに古いセッションの
    2. tranferの属性を作成します。 Tomcatを使用してTomcatの認証メカニズムを使用するすべてのサーブレットにグローバルにこれを適用したい場合
    0

    、あなたが使用している場合は、このsample code.

    0

    に示すように、この動作を強制的にバルブを書くことができますjboss 4のような古いバージョンのjboss 4では、session.invalidate()呼び出しのあとrequest.getSession(true)を呼び出すだけでセッションIDは変更されません。

    バルブを使いたくなく、アクションクラスのセッションIDを変更したい場合は、リフレクションを使用してアーカイブすることができます.CatalinaRequestはアクションクラスで直接利用できないためです。

    サンプルコード

    private HttpSession changeSessionId(HttpServletRequest request) 
    { 
        HttpSession oldSession = request.getSession(false); 
        HttpSession newSession = null; 
    
        try 
        { 
         //get all cookies from request 
         Cookie[] cookies = request.getCookies(); 
    
         //Get all attribute from old session 
         Enumeration<Object> attrNames = oldSession.getAttributeNames(); 
    
         Properties attributFromOldSession = new Properties(); 
    
         while (attrNames.hasMoreElements()) 
         { 
          String key = (String)attrNames.nextElement(); 
          attributFromOldSession.put(key, oldSession.getAttribute(key)); 
         } 
    
         //Actual logic to change session id 
    
         Field catalinaRequestField; 
    
         //Getting actual catalina request using reflection 
         catalinaRequestField = request.getClass().getDeclaredField("request"); 
         catalinaRequestField.setAccessible(true); // grant access to (protected) field 
         Request realRequest = (Request)catalinaRequestField.get(request); 
    
         //Invalidating actual request 
         realRequest.getSession(true).invalidate(); 
         realRequest.setRequestedSessionId(null); 
         realRequest.clearCookies(); 
    
         //setting new session Id 
         realRequest.setRequestedSessionId(realRequest.getSessionInternal(true).getId()); 
    
         //Put back the cookies 
         for (Cookie cookie : cookies) 
         { 
    
          if (!"JSESSIONID".equals(cookie.getName())) 
          { 
           realRequest.addCookie(cookie); 
          } 
         } 
    
         // put attribute from old session 
         attrNames = attributFromOldSession.keys(); 
    
         while (attrNames.hasMoreElements()) 
         { 
          String key = (String)attrNames.nextElement(); 
          newSession.setAttribute(key, attributFromOldSession.get(key)); 
         } 
        } 
        catch (Exception e) 
        { 
         e.printStackTrace(); 
        } 
        return newSession; 
    
    } 
    
    0

    HttpServletRequest.changeSessionId()は、時間の任意の時点で、セッションIDを変更するために使用することができます。

    関連する問題