2009-09-14 18 views
15

मेरे web.xml में मैं कुछ संसाधनों के लिए एक उपयोगकर्ता के डेटा-बाधा परिभाषित किया है:टोमकैट सत्र अपहरण को कैसे रोकें?

<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. जब मैं संदर्भ/उपयोगकर्ता/sample.faces में बदल जाता हूं तो टॉमकैट 302 रीडायरेक्ट को HTTPS पर रीडायरेक्ट करता है। लेकिन मेरा JSESSIONID अभी भी आईडी 1 है।

मुझे लगता है कि यह एक भेद्यता है? या यह मेरी विन्यास गलती है?

समस्या जो मैं देखता हूं वह निम्न है: कुकी आईडी 1 के साथ HTTP पर ब्राउज़ करते समय एक हमलावर होता है जो मेरे नेटवर्क यातायात को सुन रहा है। वह मेरी कुकी आईडी 1 "चुराता है"। अब मैं एचटीटीपीएस पर स्विच करता हूं और मेरी कुकी अभी भी आईडी 1 है। मैं लॉगिन करता हूँ हमलावर तब मेरे सत्र को लेने में सक्षम है क्योंकि वह मेरी कुकी जानता है ...

+0

अपनी टिप्पणी पुन: कारण SSLID एक ही है कि सत्र (, मैं सिर्फ क्लिक किया फ़ायरफ़ॉक्स में ताज़ा सब के बाद) ही है। आप इस सत्र का उपयोग अपने सत्र प्रबंधन में कर सकते हैं। एसएसएलआईडी कैसे बनाया गया है - यह सर्वलेट स्पेक द्वारा कवर नहीं है, इसलिए प्रत्येक विक्रेता अपने तंत्र का उपयोग कर सकता है। मुझे उम्मीद है कि आपको टॉमकैट स्रोतों की जांच करनी होगी। वैसे भी, आपको किसी भी विशिष्ट कार्यान्वयन पर भरोसा नहीं करना चाहिए - बस इसका उपयोग करें क्योंकि आप JSESSIONID का उपयोग करेंगे - एक अपारदर्शी मान के रूप में। –

उत्तर

11

यदि यह टॉमकैट का एक हालिया संस्करण है, तो आपको कोई समस्या नहीं हो सकती है। हालांकि, यह सत्र से जुड़े एसएसएल आईडी की जांच करने पर निर्भर करता है। इस तरह के

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(); 
} 

मैं तो एक उपयुक्त असुरक्षित यूआरएल फ़ायरफ़ॉक्स और लाइव HTTP हेडर एक्सटेंशन का उपयोग कर, सत्र कुकी प्राप्त करने के लिए लागू किया। यह जवाब भेजा जब मैं

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 

इसके बाद, मैं करने की कोशिश की अपेक्षा के अनुरूप, एक संरक्षित यूआरएल

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

पहुँच सकते हैं और, मैं

https://localhost:8443/EchoWeb/personal/protected 
पर पुनः निर्देशित किया गया

और प्रतिक्रिया थी

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

सूचना है कि कुकी/सत्र आईडी एक ही है, लेकिन हम अब एक नया SSLID है। अब, सत्र कुकी का उपयोग कर सर्वर को धोखा देने का प्रयास करें।विशेष रूप से

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() 

अब, तुम अजगर पता करने की जरूरत नहीं है, - मैं सिर्फ एक (भिन्न) संरक्षित संसाधन के लिए एक HTTP अनुरोध भेजने के लिए कोशिश कर रहा हूँ:

मैं एक अजगर स्क्रिप्ट, spoof.py की स्थापना कुकी में एक ही सत्र आईडी के साथ। यहाँ प्रतिक्रिया जब मैं अपने हंसोड़ स्क्रिप्ट दो बार भाग गया है: ऊपर प्रतिक्रिया में

 
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 

ध्यान दें कि सत्र डेटा जो पहले, असुरक्षित अनुरोध में स्थापित किया गया था (1254034761932 की एक टाइमस्टैम्प के साथ एक मूल्य), भर भेज दिया गया है , क्योंकि टोमकैट एक ही सत्र का उपयोग कर रहा है क्योंकि सत्र आईडी समान है। यह निश्चित रूप से सुरक्षित नहीं है। हालांकि, ध्यान दें कि SSL आईडी अलग हर बार थे और यदि आप उन का उपयोग अपने सत्र डेटा में प्रमुख करने के लिए (उदाहरण के लिए दिखाया गया है), तो आप सुरक्षित होना चाहिए। अगर मैं अपने फ़ायरफ़ॉक्स टैब ताज़ा करते हैं, यहाँ प्रतिक्रिया है:

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

सूचना है कि SSLID ही पहले फ़ायरफ़ॉक्स अनुरोध के लिए के रूप में है। इसलिए, सर्वर SSL आईडी मान का उपयोग करके सत्रों को अलग-अलग बता सकता है। सूचना विशेष रूप से है कि "सुरक्षित डेटा" फ़ायरफ़ॉक्स सत्र से बनाया गया प्रत्येक अनुरोध के लिए ही है, लेकिन अलग जाली से प्रत्येक सत्र और भी फ़ायरफ़ॉक्स सत्र से अलग करने के लिए।

+0

महान स्पष्टीकरण! लेकिन मेरे पास अभी भी एक सवाल है: यह कैसे काम करता है, कि फ़ायरफ़ॉक्स के साथ आपका अंतिम कॉल पुराने SSLID भेजता है। वह आईडी कैसे बनाई गई है? क्या यह सुविधा कहीं भी दस्तावेज है? – Marcel

2

मुझे लगता है कि यह डिजाइन द्वारा इस तरह काम करता है। आप सत्र पर अपने अभिगम नियंत्रण का आधार नहीं बना सकते हैं। आपको अन्य पैरामीटर का उपयोग करने की आवश्यकता है। आपको प्रमाणीकरण जोड़ने और भूमिका-आधारित नियंत्रण का उपयोग करने की आवश्यकता है।

टॉमकैट में, सुरक्षा है लेकिन बिल्कुल विपरीत है। यदि आपको सुरक्षित क्षेत्र में सत्र मिलता है, तो वह सत्र असुरक्षित क्षेत्र में स्थानांतरित नहीं किया जाता है। टोमकैट कुकी पर "सुरक्षित" ध्वज सेट करके इसे प्राप्त करता है ताकि कुकी HTTP कनेक्शन पर नहीं भेजी जा सके।

+0

मैं सत्र पर अभिगम नियंत्रण का आधार नहीं रखता हूं। उपर्युक्त web.xml पूरे web.xml का एक छोटा सा हिस्सा है। बेशक मेरे पास एक जेएएएस आधारित प्रमाणीकरण विधि लागू है। मैं अपने विवरण में थोड़ा और स्पष्ट होने की कोशिश करता हूं। – Marcel

2

मैं sessionId बदलने के लिए जब आप सत्र को प्रमाणित सुझाव देते हैं।
इस तरह पुराने सत्र आईडी बेकार हो जाता है और सत्र अपहरण असंभव है।
एक सर्वलेट कंटेनर में sessionId बदलने के लिए:

  • session.invalidate()
  • सत्र = req.getSession (सच)

    • एक अस्थायी संग्रह पर वर्तमान सत्र से सभी विशेषताओं की प्रतिलिपि
    • अस्थायी संग्रह

    SSLID बारे में स्थित विशेषताओं के साथ नए सत्र को भरने, कृपया ध्यान दें कि दोनों क्लाइंट और सर्वर किसी भी पर कनेक्शन बंद करने के लिए स्वतंत्र हैं पहर। जब एक नया एसएसएल हैंडशेक बंद हो जाएगा और एक नया एसएसआईडी उत्पन्न होगा। तो, आईएमओ एसएसएलआईडी सत्र (या ट्रैक करने में मदद) ट्रैक करने का एक विश्वसनीय तरीका नहीं है।

  • संबंधित मुद्दे