Background
Whenever a user crosses an authentication boundary, the user's session ID
should be regenerated. This concept applies to a user logging into an
application, logging out, or when a user reauthenticates due to a risk-based
authentication process. The regeneration of session IDs is an important
practice that helps eliminate session fixation vulnerabilities and may limit
the impact of session theft vulnerabilities prior to authentication.
For more information on Session Fixation vulnerabilities and Session ID
regeneration practices, please see the OWASP pages below:
http://www.owasp.org/index.php/Session_Fixation
http://www.owasp.org/index.php/Session_Management#Regeneration_of_Session_Tokens
Session ID
Regeneration in Traditional Java Web Applications
In a J2EE application, the user's JSESSIONID
cookie should be regenerated and the previous session should be removed or
deleted from the server. Example code below shows how this might be
accomplished in a traditional Java web application.
public class ExampleLoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if( //authentication was successful ) {
request.getSession().invalidate();
HttpSession session = request.getSession(true);
session.setAttribute("AUTHENTICATED", new Boolean(true));
response.sendRedirect("PageRequiringAuthentication.jsp");
//Additional Code Would Normally Follow
Session ID Regeneration in Struts 2 Applications
In Struts 2 applications, developers typically don't directly interact with the
HttpServletRequest, HTTPServletResponse, or HttpSession objects. With
consideration of these factors, the solution discussed above for a traditional
Java web application may not be appropriate for Struts 2.
I did a little research and through trial an error I came up with a Struts 2
specific solution for regenerating JSESSIONIDs. This solution utilizes the
SessionAware interface. Please excuse the unrealistic authentication code...
package nickcoblentzblog.actions.sessions;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.dispatcher.SessionMap;
public class Login extends ActionSupport implements SessionAware {
private String userid;
private String password;
private Map session;
public String execute() {
if(userid.equals("admin") && password.equals("admin")) {
/* Session ID Regeneration: Try #4 */
((SessionMap)this.session).invalidate();
this.session = ActionContext.getContext().getSession();
/* End Try #4 */
session.put("AUTHENTICATED", new Boolean(true));
return SUCCESS;
}
else
return ERROR;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void setSession(Map session) {
this.session = session;
}
}
To test this code, I followed the following procedure.
1. Cleared all browser cookies
2. Visited the Login JSP page
3. Used the Web Developer Toolbar to view my initial JSESSIONID
4. Logged into the application successfully
5. Used the Web Developer Toolbar to view my final JSESSIONID
The initial JSESSIONID value was:
AA4996C5E24BB8221BB27B23EA599F34
The final JSESSIONID value was:
325ED18851B93EBA542D2AE7926E7F8E
Based on these tests this solution appears to work successfully.
In case anyone is curious, here are a couple other ideas I toyed with:
/* Try # 1:
this.request.getSession().invalidate();
this.request.getSession(true);
*/
/* Try #2:
HTTPUtilities esapiHTTPUtilities = ESAPI.httpUtilities();
esapiHTTPUtilities.setCurrentHTTP(request, response);
try {
esapiHTTPUtilities.changeSessionIdentifier();
}
catch(Exception e) {
e.printStackTrace();
}
*/
/* Try #3:
((SessionMap)ActionContext.getContext().getSession()).invalidate();
*/
Posted by Nick Coblentz
[Ph4nt0m Security Team]
Email: ax...@ph4nt0m.org
=== V3ry G00d, V3ry Str0ng ===
=== Ultim4te H4cking ===
=== XPLOITZ ! ===
=== #_# ===
#If you brave,there is nothing you cannot achieve.#
/* Session ID Regeneration: Try #4 */
((SessionMap)this.session).invalidate();
//把当前的SESSION干掉,也就是说,之后会自动生成个新的session
this.session = ActionContext.getContext().getSession();
/* End Try #4 */
session.put("AUTHENTICATED", new Boolean(true));
//给新的session赋予通过验证的权利
这是一个针对Session Fixation攻击的防范
现在 Session Fixation 攻击基本都快绝迹了,估计很多人都忘记了。
因为现在一般应用都会在登录后重新生成一个session或者附加一些东西,而改变原来的session。
一些框架和一些应用里本身就自己带了这个东西,所以程序员可能都不需要再关注了。比如tomcat。
Session fixation攻击是这样的:
你事先获取一个session,这时候你是没登录的,然后你把这个link或啥的拷给别人,别人登录进去了,这时候这个session是认证过的,而你事先是知道这个sessionID的,所以你就可以直接用这个sessionID登录进他的帐户了
由于现在很少见到这种不改变session的玩意了,所以很难再搞起这种攻击了。
这里作者是重新写了下在struts 2 框架里面怎么重新生成session,有意思的是,在ESAPI里也有函数可以直接调用。
[Ph4nt0m Security Team]
Email: ax...@ph4nt0m.org
=== V3ry G00d, V3ry Str0ng ===
=== Ultim4te H4cking ===
=== XPLOITZ ! ===
=== #_# ===
#If you brave,there is nothing you cannot achieve.#
发件人: ph4nt0m@googlegroups.com
[mailto:ph4nt0m@googlegroups.com]
代表
xgc
kxlzx
发送时间: 2008年9月5日
15:41
收件人: ph4nt0m@googlegroups.com
主题: [Ph4nt0m]
Re: [zz]JSESSIONID Regeneration in Struts 2