Segurança no Vraptor3

Criei um interceptor para ser usado no Vraptor3 que adiciona uma camada extra para aplicações web. Obvio que algumas funcionalidades como session-fixation já são evitadas pelo próprio container (como no Glassfish), porém como não achei uma referência de que todos containers implementam, resolvi escrever essa classe.

Compartilho aqui ela com vocês.

Antes de ver o SecurityUserSessionHolder é necessário entender que tenho uma classe chamada UserSession que é um POJO simples que contém apenas um cache das informações do usuário, que depois do mesmo fazer autenticação via JAAS essa classe é inicializada com os seus dados, exemplo, endereço de IP e navegador.

[code]@Component
@SessionScoped
public class UserSession
implements Serializable {

private final String remoteAddr;
private final String userAgent;

}[/code]

Primeiro eu valido se o usuário está acessando via HTTPS, e recuso quaisquer acessos via HTTP.

// only allow http over ssl if (!request.getScheme().equals("https")) { logger.error("disconnected {}, non ssl request", session.getId()); disconnect(); }

Quando o usuário faz o login eu guardo o endereço de IP dele. A cada request eu verifico se o IP do usuário é o mesmo do login, e desconecto o usuário caso o IP for diferente.

// avoid session hijacking. deny if current ip is not equals then session ip. if (!request.getRemoteAddr().equals(userSession.getRemoteAddr())) { final Object[] params = { session.getId(), request.getRemoteAddr(), userSession.getRemoteAddr() }; logger.error("disconnected {} by session hijack: request IP {}, session IP {}", params); disconnect(); }

Aqui eu comparo se o user-agent (navegador) da requisição atual é o mesmo que eu guardei no login. Se o navegador não for o mesmo, desconecta.

// compare the user-agent on each request with the session value. // if the user-agent changes it's possible stealing session if (!request.getHeader("user-agent").equals(userSession.getUserAgent())) { final Object[] params = { session.getId(), request.getHeader("user-agent"), userSession.getUserAgent() }; logger.error("disconnected {} by user-agent: request UA {}, session UA: {}", params); disconnect(); }

Tanto a verificação do IP quando do navegador evitam o session-hijack.

Evito que o próprio cliente defina qual será o jsessionid. Isso pode acontecer nos casos de session-fixation. Não tenho certeza se todos os appservers implementam proteção contra esse tipo de ataque.

// not accept session identifiers from GET / POST variables // I belive the appserver doesn't accept this if (request.isRequestedSessionIdFromURL()) { logger.error("disconnected {} by requested session from URL", session.getId()); disconnect(); }

E por último verifico se o referer enviado pelo navegador é o mesmo do que seu último acesso. A cada acesso do usuário eu guardo na sessão dele os dados das duas últimas páginas acessadas. Caso o referer vindo do request não for igual a pelo menos um deles, desconecta o usuário.

[code]// destroy session if referrer is suspicious
// TODO IE has a bug: when document is reloaded referer always be null
final String referer = request.getHeader(“referer”);
final List sessionReferer = (List) session.getAttribute(“sessionReferer”);
final String url = request.getRequestURL().toString();

if (sessionReferer != null && !sessionReferer.contains(referer)) {
final Object[] params = { session.getId(), sessionReferer, referer };
logger.error(“disconnected {} by referer: history {}, referer {}”, params);
disconnect();
}[/code]

Porém esse último item tem um porém: e sempre culpa do maldito IE. No IE se você clica em um link que seja igual ao link da página anterior o referer vem como null, sendo assim o usuário acaba por ser desconectado. Ainda não pensei como resolver isso, até porque nem mesmo tenho IE na minha máquian :smiley:

A classe completa segue no meu GIST: http://gist.github.com/407927

Isso ai cara muito bommm…

assim que nen vc, sou um entusiasta do VRaptor 3 apesar de nao postar tanto sobre o assunto, mas leio a maioria dos posts no guj sobre…

continuemos assim que o produto vai longe

abs

[quote=garcia-jj]…

if (!request.getScheme().equals("https")) { . .[/quote]Só 1 duvidinha: esse ‘request’ é o request da API Servlet do Java??!
Mas, parabens p/ contribuição (principalmente neste aspecto 1/2 chatinho: segurança)!! Esta thread vai p/ meu Favoritos (de Java, é claro =P)!!

Derlon, é sim HttpServletRequest. A classe completa você encontra no meu gist em http://gist.github.com/407927.

Sakei! :wink:
Muito interessante a implementação usando Interceptor. Blz pura!!