ZKOSS-会话令牌固定-

时间:2019-02-12 15:44:29

标签: zk

希望有人有一个主意。我需要什么:

在尝试进行身份验证时检查是否设置了特定的会话属性:

Sessions.getCurrent().getAttribute(...);

通过这样做,将创建一个新会话。如果未设置该属性,那么将检查身份验证,并且需要将其保存到新会话中。必须是新会话才能检索新会话ID,否则该应用程序很容易受到会话令牌固定攻击。

现在我不能使会话无效,获取一个新会话,然后设置身份验证,因为

Sessions.getCurrent().invalidate();
Sessions.getCurrent(true).setAttribute(...);

在最后一个请求完成之前不会破坏该会话,因此这里的getCurrent()将给我“旧的”会话,该会话在该时间点仍然有效。

我的想法是随后在URL中发送带有必要属性的转发,以将它们以其他方法保存到会话中,在该方法中我可以访问新会话。但是,我得到了一个IllegalStateException:

  

java.lang.IllegalStateException:在处理用户请求时使用sendRedirect代替

关于如何解决这种情况的任何想法?

提前谢谢! MJ。

1 个答案:

答案 0 :(得分:0)

不是安全专家,因此请您自己(和您的安全团队)检查以下代码是否满足您的特定要求。它只是试图演示如何使用本机会话和请求对象来有条件地使会话无效,设置/检查属性并在需要时转发请求。

对于这种情况,我建议使用较低的抽象水平,并直接使用本机HttpSession和HttpServletRequest对象,例如在servlet过滤器中。

这可以在请求处理的较早阶段捕获潜在的操纵尝试(并使您独立于所使用的框架工作)。

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { ATMsService } from './atms.service';

interface atm {
    target_address: string,
    postalcode: string,
    municipality: string,
    location: string,
    location_type: string,
    availability: string,
    availability_details: string,
    coordinates_lat: string,
    coordinates_lon: string
}

@Component({
  selector: 'app-page',
  templateUrl: './page.component.html',
  styleUrls: ['./page.component.css']
})
export class PageComponent implements OnInit {

  page: number;  
  atms: atm[] = [];

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    private service: ATMsService
    ) {}

  ngOnInit() {
    this.service.getAll().then((data) => {
      this.atms = data;
    })

    this.route.params.subscribe(parameters => {
      this.page = parameters.page;
    })
  }

}

然后在您的web.xml中配置过滤器

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class CheckCertainAttributeFilter implements Filter {

    public static final String CERTAIN_SESSION_ATTRIBUTE = "certain-session-attribute";
    public static final String MY_EXPECTED_VALUE = "my-expected-value";

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
            FilterChain chain) throws IOException, ServletException {
        final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        final HttpSession session = httpServletRequest.getSession();

        //session present, check for certain session attribute value
        if (session != null) { 
            final String certainSessionAttributeValue = 
                    (String) session.getAttribute(CERTAIN_SESSION_ATTRIBUTE);
            if (!MY_EXPECTED_VALUE.equals(certainSessionAttributeValue)) {
                session.invalidate();
                HttpSession newSession = ((HttpServletRequest) request).getSession(true);
                newSession.setAttribute(CERTAIN_SESSION_ATTRIBUTE, MY_EXPECTED_VALUE);
                request.getRequestDispatcher("/login.zul").forward(request, response);
            }
        }
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException { }

    @Override
    public void destroy() { }
}

此后,除非会话属性中存在期望值,否则每个请求都将转发到login.zul页面。