CSRF令牌生成问题

问题描述 投票:0回答:1

为了防止CSRF,我遵循的步骤如下:

1.当请求到达(对于loginfilter)会话为空时,首先使用setAttribute()为此新会话创建会话添加令牌(randome编号),并使用dispatcher.forward重定向到login.jsp屏幕。

2.在login.jsp屏幕中使用getAttribute()将令牌存储在隐藏字段中。

3.在提交login.jsp时,第一个请求将来到loginfilter,这里将来自请求的令牌与会话中的令牌进行比较,如果匹配则继续执行动作类。否则为同一会话生成新令牌并使用sendRedirect()重定向到login.jsp

当我在这个应用程序上运行安全工具时,我的消息说“缺少一次令牌参数”。

请帮我。


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

<!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>

z.veb.hml

<?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


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


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

java struts-1
1个回答
0
投票

在重定向时,只需指示浏览器向login.jsp发出新请求。此登录页面不会在隐藏字段中设置令牌,除非您使用的某些框架可以帮助您。所以改为使用请求调度程序。你还提到你运行了一个安全工具。如果它是模仿请求的工具,那么请确保在重播第二个请求中包含令牌,否则将无法识别。

编辑(代码发布后):我没有得到使用监听器的原因。您想要实现的是,无论何时创建会话,您都会自动将令牌与其关联。您也可以在过滤器类中执行此操作。请注意,httpRequest.getSession会检查会话,如果不存在,它也会创建。此方法的其他变体采用布尔参数。此外,您需要了解当您执行chain.doFilter(请求,响应)时,它意味着请求处理在链中继续进行。

您可以从其他流行的CSRF过滤器实现中获取帮助,例如herehere。你也可以看看发布的here样本

© www.soinside.com 2019 - 2024. All rights reserved.