简体   繁体   English

CSRF 代币生成问题

[英]CSRF token generation issue

To prevent CSRF below were the steps i have followed:为了防止以下 CSRF,我遵循了以下步骤:

1 . 1 . First time when request comes(to loginfilter) session is null, create a session add token(randome number) to this new session by using setAttribute() and redirect to login.jsp screen using dispatcher.forward .第一次当请求到来时(到 loginfilter)会话为空,使用 setAttribute() 创建一个会话添加令牌(随机数)到这个新会话并使用dispatcher.forward重定向到 login.jsp 屏幕。

2 . 2 . in login.jsp screen use getAttribute() store the token in the hidden filed.在 login.jsp 屏幕中使用 getAttribute() 将令牌存储在隐藏字段中。

3 . 3 . on submit of login.jsp first request will come to loginfilter, here compare the token from the request with the token in the session, if matches then proceed with executing the action class.在提交 login.jsp 时,第一个请求将来到 loginfilter,这里将请求中的令牌与会话中的令牌进行比较,如果匹配则继续执行操作类。 otherwise generate the new token for the same session and redirect to the login.jsp using sendRedirect()否则为同一会话生成新令牌并使用sendRedirect()重定向到 login.jsp

when i ran the security tool on this application, i message saying "Missing one time token parameter".当我在这个应用程序上运行安全工具时,我的消息说“缺少一次性令牌参数”。

Please help me.请帮我。


1.filter.java 1.filter.java

if (session == null) {
    chain.doFilter(request, response);
    return;
}
else {
    // validate the CSRF
    String sToken = httprequest.getSession().getAttribute("CSRF_TOKEN")
            .toString();
    String pToken = httprequest.getParameter("CSRF_TOKEN");
    System.out.println("Tokens - " + sToken + pToken);
    if (sToken.equals(pToken)) {
        chain.doFilter(request, response);
    }
    else {
        CommonUtils.updateSessionToken(session);
        /*
         * RequestDispatcher rd =
         * request.getRequestDispatcher("/login.jsp");
         * rd.forward(request, response);
         */
        httpresponse.sendRedirect("/login.jsp");
    }
}

2.login.jsp 2.登录.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%
    Object token = request.getSession().getAttribute("CSRF_TOKEN");
    String tokenStr = "";
    if (token != null) {
        tokenStr = (String) token;
    }

    System.out.println("+tokenStr " + tokenStr);
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>CSRFGuard Test Application</title>
</head>
<body>
    Welcome to the OWASP CSRFGuard Test Application! Where would you like
    to go?
    <br />
    <form action="/CSRF/helloServlet" method="post">
        <input type="text" name="username" /> <br /> <input type="text"
            value="<%=tokenStr%>" name="CSRF_TOKEN" /> <input type="submit"
            value="login">
    </form>
</body>
</html>

3.web.xml 3.web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>CSRF</display-name>
    <servlet>
        <description>
        </description>
        <display-name>Hell0oServelt</display-name>
        <servlet-name>HelloServelt</servlet-name>
        <servlet-class>com.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServelt</servlet-name>
        <url-pattern>/helloServlet</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>login.jsp</welcome-file>
    </welcome-file-list>

        <listener>
        <listener-class>com.CsrfGuardHttpSessionListener</listener-class>
    </listener>
  <filter>
    <filter-name>LoggedInFilter</filter-name>
    <filter-class>com.LoggedInFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>LoggedInFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

</web-app>

4.CsrfGuardHttpSessionListener 4.CsrfGuardHttpSessionListener


public class CsrfGuardHttpSessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent event) {
        HttpSession session = event.getSession();
        System.out.println("New session id - "+session.getId());
        String tokenId = generateRandomId();
    session.setAttribute("CSRF_TOKEN", tokenId);
    System.out.println("newtoken -"+tokenId);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent event) {
        /** nothing to do  **/
    }

}

5.HelloServlet 5.HelloServlet


public class HelloServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public HelloServlet() {
        super();
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Welcome ...!");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        doPost(req, resp);
    }
}

On redirect the browser is simply instructed to make a new request to login.jsp.在重定向时,浏览器只是被指示向 login.jsp 发出一个新请求。 This login page would not have the token set in hidden field unless you are using some framework which can help you with that.此登录页面不会在隐藏字段中设置令牌,除非您使用一些可以帮助您解决此问题的框架。 So instead use request dispatcher forward.所以改为使用请求调度程序转发。 Also you mentioned that you ran a security tool.您还提到您运行了一个安全工具。 If it is a tool which mimics requests then make sure to include the token in the replay second request or it will not be recognized.如果它是一个模仿请求的工具,那么请确保在重播第二个请求中包含令牌,否则将无法识别。

EDIT (After code was posted): I did not get the reasoning of using a listener.编辑(发布代码后):我没有得到使用侦听器的理由。 What you wanted to achieve is that whenever a session is created you automatically associate a token with it.您想要实现的是,无论何时创建会话,您都会自动将令牌与其关联。 This you can do in your filter class as well.您也可以在过滤器类中执行此操作。 Please note that the httpRequest.getSession checks for the session and if not present it creates as well.请注意,httpRequest.getSession 检查会话,如果不存在,它也会创建。 There are other variants of this method which take boolean parameter.此方法还有其他变体采用布尔参数。 Also you need to understand that when you do chain.doFilter(request, response) it means that the request processing to proceed further in the chain.您还需要了解,当您执行 chain.doFilter(request, response) 时,这意味着请求处理将在链中进一步进行。

You can take help from other popular CSRF filter implementations like here , here .您可以从其他流行的 CSRF 过滤器实现中获取帮助,例如此处此处 Also you can take a look at sample posted here您也可以查看此处发布的示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM