2009-09-14 19 views
15

私のweb.xmlに私はいくつかのリソースに対するユーザ・データ制約を定義した:tomcatセッションのハイジャックを防ぐ方法は?

<security-constraint> 
    <web-resource-collection> 
     <web-resource-name>Personal Area</web-resource-name> 
     <url-pattern>/personal/*</url-pattern> 
    </web-resource-collection> 
    <web-resource-collection> 
     <web-resource-name>User Area</web-resource-name> 
     <url-pattern>/user/*</url-pattern> 
    </web-resource-collection> 
    <user-data-constraint> 
     <transport-guarantee>CONFIDENTIAL</transport-guarantee> 
    </user-data-constraint> 
</security-constraint> 
  1. 私はhttpでページをロードすると、私は私のクッキーで私のJSESSIONID ID1を持っています。
  2. context/user/sample.facesに変更すると、TomcatはHTTPSへの302リダイレクトを行います。しかし私のJSESSIONIDはまだID1です。

これは脆弱性だと思いますか?それとも私の設定ミスですか?

私が見ている問題は次のとおりです。クッキーID1でHTTP経由でブラウジング中、ネットワークトラフィックを受信して​​いる攻撃者がいます。彼は私のクッキーID1を "盗む"。今私はHTTPSに切り替えて、私のクッキーはまだID1です。私はログインします。攻撃者は自分のクッキーを知っているので、私のセッションを引き継ぐことができます...

+0

あなたのコメントを再投稿してください:SSLIDが同じ理由は、セッションが同じであることです(私はちょうどFirefoxでリフレッシュをクリックしました)。セッション管理でこの事実を使用することができます。 SSLIDがどのように構築されているかについては、各ベンダーが独自のメカニズムを使用できるように、サーブレット仕様ではカバーされていません。 Tomcatのソースをチェックする必要があります。とにかく、特定の実装に頼るべきではありません。JSESSIONIDを不透明な値として使用するだけです。 –

答えて

11

最新版のTomcatの場合は、問題がない可能性があります。ただし、セッションに関連付けられているSSL IDを確認することによって異なります。これは、

String sslId = (String) req.getAttribute("javax.servlet.request.ssl_session"); 

( - サーブレット3.0仕様の一部として、属性キーがjavax.servlet.request.ssl_session_idに将来変更されることに留意されたい)などのコードを使用して利用可能です。

は、私は次のdoGetの方法でサーブレットを設定します。

protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException { 
    HttpSession session = request.getSession(true); 
    String sid = session.getId(); 
    String sslId = (String) request.getAttribute(
       "javax.servlet.request.ssl_session"); 
    String uri = request.getRequestURI(); 
    OutputStream out = response.getOutputStream(); 
    PrintWriter pw = new PrintWriter(out); 
    HashMap<String, Object> secrets; 
    Object secret = null; 
    Object notSecret; 
    Date d = new Date(); 

    notSecret = session.getAttribute("unprotected"); 
    if (notSecret == null) { 
     notSecret = "unprotected: " + d.getTime(); 
     session.setAttribute("unprotected", notSecret); 
    } 
    secrets = (HashMap<String, Object>) session.getAttribute("protected"); 
    if (secrets == null) { 
     secrets = new HashMap<String, Object>(); 
     session.setAttribute("protected", secrets); 
    } 
    if (sslId != null) { 
     if (secrets.containsKey(sslId)) 
      secret = secrets.get(sslId); 
     else { 
      secret = "protected: " + d.getTime(); 
      secrets.put(sslId, secret); 
     } 
    } 
    response.setContentType("text/plain"); 
    pw.println(MessageFormat.format("URI: {0}", new Object[] { uri })); 
    pw.println(MessageFormat.format("SID: {0}", new Object[] { sid })); 
    pw.println(MessageFormat.format("SSLID: {0}", new Object[] { sslId })); 
    pw.println(MessageFormat.format("Info: {0}", new Object[] { notSecret })); 
    pw.println(MessageFormat.format("Secret: {0}", new Object[] { secret })); 
    pw.println(MessageFormat.format("Date: {0}", new Object[] { d })); 
    pw.close(); 
} 

私はその後、セッションクッキーを取得するには、FirefoxやライブHTTPヘッダーの拡張機能を使用して、適切な保護されていないURLを呼び出しました。これは私が

http://localhost:8080/EchoWeb/unprotected 

にナビゲートしたときに送信された応答だった(私のweb.xmlは、あなたのように、唯一の保護/ユーザー/ *および/個人/ *):

 
URI: /EchoWeb/unprotected 
SID: 9ACCD06B69CA365EFD8C10816ADD8D71 
SSLID: null 
Info: unprotected: 1254034761932 
Secret: null 
Date: 27/09/09 07:59 

次に、私がしようとしました保護されたURL

http://localhost:8080/EchoWeb/personal/protected 

にアクセスすると、予想通り、私は

https://localhost:8443/EchoWeb/personal/protected 
にリダイレクトました

と応答がクッキー/セッションIDが同じであること

 
URI: /EchoWeb/personal/protected 
SID: 9ACCD06B69CA365EFD8C10816ADD8D71 
SSLID: 4abf0d67549489648e7a3cd9292b671ddb9dd844b9dba682ab3f381b462d1ad1 
Info: unprotected: 1254034761932 
Secret: protected: 1254034791333 
Date: 27/09/09 07:59 

お知らせでしたが、私たちは今、新しいSSLIDを持っています。では、セッションCookieを使用してサーバーを偽装しようとします。

私は spoof.py、Pythonスクリプトを設定

import urllib2 

url = "https://localhost:8443/EchoWeb/personal/protected" 
headers = { 
    'Host': 'localhost:8080', 
    'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3', 
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 
    'Accept-Language': 'en-gb,en;q=0.5', 
    'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 
    'Cookie' : 'JSESSIONID=9ACCD06B69CA365EFD8C10816ADD8D71' 
} 
req = urllib2.Request(url, None, headers) 
response = urllib2.urlopen(req) 
print response.read() 

さて、あなたは特に、Pythonのを知っている必要はありません - 私は(異なる)保護されたリソースへのHTTPリクエストを送信しようとしていますCookie内に同じセッションIDを持つここでは、応答は、私は二回私のパロディースクリプトを実行したときです:セッションデータまず、保護されていない要求に設定された(1254034761932のタイムスタンプを持つ値)は、全体に送信されたことを上記の回答で

 
C:\temp>spoof 
URI: /EchoWeb/personal/protected 
SID: 9ACCD06B69CA365EFD8C10816ADD8D71 
SSLID: 4abf0eafb4ffa30b6579cf189c402a8411294201e2df94b33a48ae7484f22854 
Info: unprotected: 1254034761932 
Secret: protected: 1254035119303 
Date: 27/09/09 08:05 


C:\temp>spoof 
URI: /EchoWeb/personal/protected 
SID: 9ACCD06B69CA365EFD8C10816ADD8D71 
SSLID: 4abf0eb184cb380ce69cce28beb01665724c016903650539d095c671d98f1de3 
Info: unprotected: 1254034761932 
Secret: protected: 1254035122004 
Date: 27/09/09 08:05 

お知らせこれは、セッションIDが同じであるためTomcatが同じセッションを使用しているためです。もちろんこれはで、安全ではないです。ただし、SSL ID はそれぞれと異なり、などを使用してセッションデータをキー入力すると安全です。私はFirefoxのタブを更新する場合は、ここでの応答があります:SSLIDは以前のFirefoxの要求のためとして同じであることを

 
URI: /EchoWeb/personal/protected 
SID: 9ACCD06B69CA365EFD8C10816ADD8D71 
SSLID: 4abf0d67549489648e7a3cd9292b671ddb9dd844b9dba682ab3f381b462d1ad1 
Info: unprotected: 1254034761932 
Secret: protected: 1254034791333 
Date: 27/09/09 08:05 

注意してください。したがって、サーバーはSSL ID値を使用してセッションを区別できます。特に、「保護されたデータ」は、Firefoxセッションからの各要求に対して同じですが、とは異なるが、偽装されたセッションごとに異なり、Firefoxセッションとは異なります。

+0

大きな説明!しかし、私はまだ1つの質問があります:どのように動作するのか、firefoxでの最後の呼び出しで古いSSLIDが送信されます。そのIDはどのように構築されていますか?この機能はどこに文書化されていますか? – Marcel

2

このように設計されていると思います。あなたはアクセスコントロールのセッションをベースにすることはできません。他のパラメータを使用する必要があります。認証を追加し、ロールベースの制御を使用する必要があります。

Tomcatでは保護がありますが、正反対です。セキュアエリアでセッションを取得した場合、そのセッションは保護されていないエリアには転送されません。 Tomcatは、CookieがHTTP接続に送信されないように、Cookieに「セキュア」フラグを設定することでこれを実現します。

+0

私は、セッションのアクセス制御をベースにしていません。上記のweb.xmlは、web.xml全体のほんの一部です。もちろん、私はJAASベースの認証メソッドを実装しています。私は私の説明でもう少し明確にしようとしています。 – Marcel

2

セッションを認証するときにsessionIdを変更することをお勧めします。
このように古いセッションIDは役に立たなくなり、セッションのハイジャックは不可能になります。サーブレットコンテナでセッションIDを変更するには

  • が一時コレクションで、現在のセッションのすべての属性をコピー
  • はsession.invalidate()
  • セッション= req.getSession(真)
  • 新しいセッションにテンポラリコレクションの属性を入力してください

SSLIDについて、クライアントとサーバの両方で自由に接続を閉じることができます時間。 新しいSSLハンドシェイクが行われ、新しいSSIDが生成されます。 したがって、IMO SSLIDはセッションをトラッキングする(または追跡するのを助ける)信頼できる方法ではありません。

関連する問題