ESAPI是開源組織owasp,開放的安全開發框架,但百度、google搜索相關的技術文章很少,今天小嚐試了一下,分享一下心得。
會話攻擊,簡單理解就是盜用竊取用戶的cookie,僞裝成用戶,向服務器端發送請求,竊取用戶私密信息。
具體如何防止會話攻擊,很簡單,參照《Web應用安全威脅與防治--基於OWASP TOP 10 與ESAPI》書中介紹的方法,一旦用戶登錄成功後,馬上validate用戶的會話,具體步驟如下:
- 用戶輸入用戶名和密碼
- 系統對用戶進行驗證通過
- 已有的會話信息如果仍然需要,則轉移到一個臨時變量中去
- invalidate當前會話
- 創建一個新會話
- 把臨時變量中保存的會話信息恢復到新創建的會話中去
- 用戶使用這個新的會話登錄到系統中並進行操作
貼出實例
構造一個簡單登錄頁面
<body>
<form action="loginServlet" method="post">
用戶名:<input type="text" name="username" /><br/>
密碼:<input type="password" name="password"/><br/>
<input type="submit" value="登錄"/>
</form>
</body>
驗證成功的頁面
<body>
歡迎${sessionScope.username }登錄
</body>
然後是一個LoginServlet,其中DefaultHTTPUtilities是ESAPI中org.owasp.esapi.reference.DefaultHTTPUtilities類,該類的changeSessionIdentifier(request),就是實現上述功能。
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
DefaultHTTPUtilities dhUtil = new DefaultHTTPUtilities();
try {
HttpSession session = dhUtil.changeSessionIdentifier(request);
session.setAttribute("username", username);
session.setAttribute("password", password);
request.getRequestDispatcher("/index.jsp").forward(request, response);
} catch (AuthenticationException e) {
e.printStackTrace();
}
}
貼出changeSessionIdentifier(request)方法源碼
public HttpSession changeSessionIdentifier(HttpServletRequest request) throws AuthenticationException {
// get the current session
HttpSession oldSession = request.getSession();
// make a copy of the session content
Map<String,Object> temp = new ConcurrentHashMap<String,Object>();
Enumeration e = oldSession.getAttributeNames();
while (e != null && e.hasMoreElements()) {
String name = (String) e.nextElement();
Object value = oldSession.getAttribute(name);
temp.put(name, value);
}
// kill the old session and create a new one
oldSession.invalidate();
HttpSession newSession = request.getSession();
User user = ESAPI.authenticator().getCurrentUser();
user.addSession( newSession );
user.removeSession( oldSession );
// copy back the session content
for (Map.Entry<String, Object> stringObjectEntry : temp.entrySet())
{
newSession.setAttribute(stringObjectEntry.getKey(), stringObjectEntry.getValue());
}
return newSession;
}
這段代碼應該很好理解。