Nếu đó là phiên bản Tomcat gần đây, bạn có thể không gặp sự cố. Tuy nhiên, điều này phụ thuộc vào việc bạn kiểm tra ID SSL được kết hợp với phiên. Đây là có sẵn sử dụng mã như
String sslId = (String) req.getAttribute("javax.servlet.request.ssl_session");
(Lưu ý rằng chìa khóa thuộc tính có thể thay đổi trong tương lai để javax.servlet.request.ssl_session
_id
- như một phần của spec Servlet 3.0).
tôi thiết lập một servlet với doGet
phương pháp sau đây:
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();
}
sau đó tôi gọi một URL không được bảo vệ thích hợp sử dụng Firefox và phần mở rộng Live HTTP Headers, để có được những cookie phiên. Đây là câu trả lời được gửi khi tôi chuyển đến
http://localhost:8080/EchoWeb/unprotected
(web.xml của tôi, giống như bạn, chỉ bảo vệ/user/* và/cá nhân/*):
URI: /EchoWeb/unprotected
SID: 9ACCD06B69CA365EFD8C10816ADD8D71
SSLID: null
Info: unprotected: 1254034761932
Secret: null
Date: 27/09/09 07:59
Tiếp theo, tôi đã cố gắng để truy cập vào một URL được bảo vệ
http://localhost:8080/EchoWeb/personal/protected
và, như mong đợi, tôi đã chuyển đến
https://localhost:8443/EchoWeb/personal/protected
và phản ứng là
URI: /EchoWeb/personal/protected
SID: 9ACCD06B69CA365EFD8C10816ADD8D71
SSLID: 4abf0d67549489648e7a3cd9292b671ddb9dd844b9dba682ab3f381b462d1ad1
Info: unprotected: 1254034761932
Secret: protected: 1254034791333
Date: 27/09/09 07:59
ý rằng ID cookie/session là như nhau, nhưng bây giờ chúng tôi có một SSLID mới. Bây giờ, chúng ta hãy cố gắng giả mạo máy chủ bằng cách sử dụng cookie phiên.
tôi thiết lập một kịch bản Python, spoof.py
:
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()
Bây giờ, bạn không cần phải biết Python, đặc biệt - Tôi chỉ cố gắng để gửi một yêu cầu HTTP tới một tài nguyên (khác nhau) được bảo vệ với cùng một ID phiên trong Cookie. Dưới đây là câu trả lời khi tôi chạy kịch bản giả mạo của tôi hai lần:
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
Lưu ý trong các câu trả lời ở trên rằng các dữ liệu phiên (một giá trị với một dấu thời gian của 1254034761932
) được đặt trong yêu cầu đầu tiên, không được bảo vệ, đã được gửi đi khắp , bởi vì Tomcat đang sử dụng cùng một phiên vì ID phiên là như nhau. Đây là khóa học không an toàn. Tuy nhiên, lưu ý rằng các ID SSL khác nhau mỗi lần và nếu bạn sử dụng các mã này để nhập dữ liệu phiên của bạn (ví dụ như được hiển thị), bạn nên an toàn. Nếu tôi làm mới tab Firefox của tôi, đây là phản ứng:
URI: /EchoWeb/personal/protected
SID: 9ACCD06B69CA365EFD8C10816ADD8D71
SSLID: 4abf0d67549489648e7a3cd9292b671ddb9dd844b9dba682ab3f381b462d1ad1
Info: unprotected: 1254034761932
Secret: protected: 1254034791333
Date: 27/09/09 08:05
Chú ý rằng SSLID là cùng như đối với các yêu cầu Firefox trước đó. Vì vậy, máy chủ có thể phân biệt các phiên bằng cách sử dụng giá trị SSL ID. Lưu ý đặc biệt là "dữ liệu được bảo vệ" giống nhau cho mỗi yêu cầu được thực hiện từ phiên Firefox, nhưng khác nhau cho mỗi phiên giả mạo và cũng khác với phiên Firefox.
Hãy bình luận của bạn: Lý do SSLID giống nhau là phiên là như nhau (tôi chỉ cần nhấp vào làm mới trong Firefox, sau khi tất cả). Bạn có thể sử dụng thực tế này trong quản lý phiên của bạn. Về cách SSLID được xây dựng - nó không được bao hàm bởi đặc tả servlet để mỗi nhà cung cấp có thể sử dụng các cơ chế riêng của họ. Bạn sẽ phải kiểm tra các nguồn Tomcat, tôi mong đợi. Dù sao, bạn không nên dựa vào bất kỳ triển khai cụ thể nào - chỉ cần sử dụng nó như bạn sẽ sử dụng JSESSIONID - như một giá trị mờ đục. –