Spring Security + Session Hijack
06/02/2013 03:45
0
Fala pessoal,

Estou desenvolvendo um app com grails 2.1.1 + spring security plugin 1.2.7.3 con a seguinte configuração:

grails.plugins.springsecurity.useSessionFixationPrevention = true

grails.plugins.springsecurity.securityConfigType = "Annotation"
grails.plugins.springsecurity.controllerAnnotations.staticRules = [
'/images/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
'/css/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
'/js/**': ['IS_AUTHENTICATED_ANONYMOUSLY']
]
grails.plugins.springsecurity.logout.afterLogoutUrl = '/'

// Clean cache
grails.cache.clearAtStartup = true

Segue também um simples exemplo de um controller/action do meu app:
@Secured(["hasRole('ROLE_USER') and isAuthenticated()"])
def teste(){}

Eu estava tentando "crackear" a segurança da action acessando-a diretamente sem estar loggado. O plugin então me apresenta uma view dizendo que não tenho autoridade para acessar aquela página... funcionou 100%

Então, quando estava testando algumas funcionalidades do meu sistema, percebi que o grails gerou um jsessionid (o que é bem incomum) e achei muito estranho. Copiei a url num notepad e efetuei loggoff do sistema e limpei o cache do meu browser. Depois eu voltei nessa action, porem fornecendo essa jsessionid... e ele entrou!

http://localhost:8080/teste/teste/teste;jsessionid=364AC2CAA5503EDE13F36FDB863FAE81

Mesmo quando eu tiro o "and isAuthenticated()" da notação, fazendo justamente de acordo com a documentação do plugin:
http://grails-plugins.github.com/grails-spring-security-core/docs/manual/guide/single.html#5.1%20Defining%20Secured%20Annotations
continua não funcionando nesse caso.

Alguem tem uma idéia do porque? Como resolver esse problema?
Tags: spring security plugin, jsessionid, hijack


0
tenta colocar a variável:
grails.plugins.springsecurity.useSessionFixationPrevention = true

fonte:
Doc springsecurity

Detalhe exploit
06/02/2013 11:25


0
Se não me engano, essa é uma alternativa pra quando o usuário não aceita cookies, dae meio que deixam por default
06/02/2013 11:25


0
Eu já estou usando grails.plugins.springsecurity.useSessionFixationPrevention, mesmo assim o erro continua, segue config:

// Spring Security Core plugin:
grails.plugins.springsecurity.userLookup.userDomainClassName = 'br.com.udoctor.seguranca.Usuario'
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'br.com.udoctor.seguranca.UsuarioRegra'
grails.plugins.springsecurity.authority.className = 'br.com.udoctor.seguranca.Regra'
grails.plugins.springsecurity.userLookup.usernamePropertyName = 'email'
grails.plugins.springsecurity.userLookup.passwordPropertyName = 'senha'

grails.plugins.springsecurity.password.algorithm = 'bcrypt'
grails.plugins.springsecurity.password.bcrypt.logrounds = 15

grails.plugins.springsecurity.useSessionFixationPrevention = true

grails.plugins.springsecurity.securityConfigType = "Annotation"
grails.plugins.springsecurity.controllerAnnotations.staticRules = [
'/images/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
'/css/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
'/js/**': ['IS_AUTHENTICATED_ANONYMOUSLY']
]
grails.plugins.springsecurity.logout.afterLogoutUrl = '/'

Abri um JIRA para esse problema:

http://jira.grails.org/browse/GPSPRINGSECURITYCORE-209#comment-74060

06/02/2013 13:03


0
Vou reinstalar o plugin e verificar se esse erro esta ocorrendo tambem nas novas versões do plugin.

Atualmente estou usando a 1.2.7.3

Isso é um erro gravissimo.
06/02/2013 13:04


0
que estranho, era pra estar desabilitado isso....

por acaso tem essa variável?
grails.views.enable.jsessionid=true

no Config.groovy
06/02/2013 16:08


0
O pior é que não está Mussato.

Segue config:

// locations to search for config files that get merged into the main config;
// config files can be ConfigSlurper scripts, Java properties files, or classes
// in the classpath in ConfigSlurper format

// grails.config.locations = [ "classpath:${appName}-config.properties",
// "classpath:${appName}-config.groovy",
// "file:${userHome}/.grails/${appName}-config.properties",
// "file:${userHome}/.grails/${appName}-config.groovy"]

// if (System.properties["${appName}.config.location"]) {
// grails.config.locations << "file:" + System.properties["${appName}.config.location"]
// }

grails.project.groupId = appName // change this to alter the default package name and Maven publishing destination
grails.mime.file.extensions = true // enables the parsing of file extensions from URLs into the request format
grails.mime.use.accept.header = false
grails.mime.types = [
all: '*/*',
atom: 'application/atom+xml',
css: 'text/css',
csv: 'text/csv',
form: 'application/x-www-form-urlencoded',
html: ['text/html','application/xhtml+xml'],
js: 'text/javascript',
json: ['application/json', 'text/json'],
multipartForm: 'multipart/form-data',
rss: 'application/rss+xml',
text: 'text/plain',
xml: ['text/xml', 'application/xml']
]

// URL Mapping Cache Max Size, defaults to 5000
//grails.urlmapping.cache.maxsize = 1000

// What URL patterns should be processed by the resources plugin
grails.resources.adhoc.patterns = ['/images/*', '/css/*', '/js/*', '/plugins/*']

// The default codec used to encode data with ${}
grails.views.default.codec = "none" // none, html, base64
grails.views.gsp.encoding = "UTF-8"
grails.converters.encoding = "UTF-8"
// enable Sitemesh preprocessing of GSP pages
grails.views.gsp.sitemesh.preprocess = true
// scaffolding templates configuration
grails.scaffolding.templates.domainSuffix = 'Instance'

// Set to false to use the new Grails 1.2 JSONBuilder in the render method
grails.json.legacy.builder = false
// enabled native2ascii conversion of i18n properties files
grails.enable.native2ascii = true
// packages to include in Spring bean scanning
grails.spring.bean.packages = []
// whether to disable processing of multi part requests
grails.web.disable.multipart=false

// request parameters to mask when logging exceptions
grails.exceptionresolver.params.exclude = ['senha']

// configure auto-caching of queries by default (if false you can cache individual queries with 'cache: true')
grails.hibernate.cache.queries = false

environments {
development {
grails.logging.jul.usebridge = true
}
production {
grails.logging.jul.usebridge = false
// TODO: grails.serverURL = "http://www.changeme.com"
}
}

// log4j configuration
log4j = {
// Example of changing the log pattern for the default console appender:
//
//appenders {
// console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n')
//}

error 'org.codehaus.groovy.grails.web.servlet', // controllers
'org.codehaus.groovy.grails.web.pages', // GSP
'org.codehaus.groovy.grails.web.sitemesh', // layouts
'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping
'org.codehaus.groovy.grails.web.mapping', // URL mapping
'org.codehaus.groovy.grails.commons', // core / classloading
'org.codehaus.groovy.grails.plugins', // plugins
'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration
'org.springframework',
'org.hibernate',
'net.sf.ehcache.hibernate'
}

// Mail plugin
grails {
mail {
host = "smtp.gmail.com"
port = 465
username = "daniel.marchena.parreira@gmail.com"
password = "Dmp99841276"
props = ["mail.smtp.auth":"true",
"mail.smtp.socketFactory.port":"465",
"mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
"mail.smtp.socketFactory.fallback":"false"]
}
}

// Spring Security Core plugin:
grails.plugins.springsecurity.userLookup.userDomainClassName = 'br.com.udoctor.seguranca.Usuario'
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'br.com.udoctor.seguranca.UsuarioRegra'
grails.plugins.springsecurity.authority.className = 'br.com.udoctor.seguranca.Regra'
grails.plugins.springsecurity.userLookup.usernamePropertyName = 'email'
grails.plugins.springsecurity.userLookup.passwordPropertyName = 'senha'

grails.plugins.springsecurity.password.algorithm = 'bcrypt'
grails.plugins.springsecurity.password.bcrypt.logrounds = 15

grails.plugins.springsecurity.useSessionFixationPrevention = true

grails.plugins.springsecurity.securityConfigType = "Annotation"
grails.plugins.springsecurity.controllerAnnotations.staticRules = [
'/images/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
'/css/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
'/js/**': ['IS_AUTHENTICATED_ANONYMOUSLY']
]
grails.plugins.springsecurity.logout.afterLogoutUrl = '/'
06/02/2013 17:28


0
Como prova de que isso realmente é um bug grave, criei um novo projeto do zero com Grails 2.1.1 + Spring Security Core Plugin 1.2.7.3 usando o s2-create para gerar os domínios.

http://www.4shared.com/zip/EZJugaWp/demonstracao.html

Acesse o controller user, action list com a seguinte url:

http://localhost:8080/teste/user/list;
ou
http://localhost:8080/teste/user/list;jsessionid=000

E você esta dentro de um controller que supostamente é 'IS_AUTHENTICATED_REMEMBERED', ou seja:
requires the user to be authenticated through a remember-me cookie or an explicit login.

Você deveria estar loggado para entrar nessa action.

07/02/2013 01:54


0
Testei com Grails 2.2.0 + Spring Security Core Plugin 1.2.7.3 e o erro persiste.

07/02/2013 02:49


0
Eu testei numa aplicação que eu tenho, e fui kikado pra pagina de login

abre um bug no jira deles... mas acredito que seja alguma coisa configurada errado
07/02/2013 12:14


0
meu teste foi o seguinte:

pelo firefox, loguei no site
abri os cookies, peguei a variável jsessionId

fui no chrome e peguei o hash (sem deslogar pra não invalidar a sessão)
abri a mesma url só que passando o jsessionId via get (?jsessionid=hash e ;jsessionid=hash)

fui redirecionado pra pagina de login
07/02/2013 12:19


0
Ele trata o "?", o problema esta com o ";".

Por curiosidade Mussatto, faz o download desse projeto exemplo e testa na sua máquina.

Esse projeto esta cru, zerado, eu instalei a ggts e criei um novo projeto grails 2.1.1.

A unica coisa que fiz foi adicionar o spring security como uma dependência do tipo compile e depois dei um generate-all para fazer o scaffolding dos dominios.

Por isso estou suspeitando que não trata-se de configuração, mas de um bug.

Eu já abri um JIRA para esse erro: http://jira.grails.org/browse/GPSPRINGSECURITYCORE-209#comment-74060
07/02/2013 13:38


0
Eu testei as duas maneiras (nunca tinha passado parametro com o ";" aliás)

Acho que a diferença é que não usei o scaffold

faz upload do seu projeto pro github.....

precisa fazer conta no 4shared pra baixar
07/02/2013 15:07


0
Mussatto, eu ainda não subi o projeto no git, vou fazer isso hoje, mas gostaria de perguntar qual versão do grails você esta utilizando e qual a versão do spring security. Talvez isso seja problema do release.

Se possível, compartilhe as configurações que você fez no arquivo Config para o plugin tambem.

08/02/2013 10:43


1
to usando o grails 2.2.0 e spring security core 1.2.7.3

das configs a unica coisa q adicionei foi:

grails.plugins.springsecurity.userLookup.userDomainClassName = 'security.User'
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'security.UserRole'
grails.plugins.springsecurity.authority.className = 'security.Role'
08/02/2013 13:15


0
Daniel,

Sugiro que você altere a senha do seu email pois ao postar seu arquivo de configuração ela está exposta(a menos que seja uma senha fake).

Já havia visto essa limitação do Spring Security.

E aí, conseguiu resolver ?

13/02/2013 15:31


0
Nathan, obrigado pelo lembrete, esse não é meu e-mail oficial, mas já troquei a senha.

Sobre o bug, resolvi parcialmente, a solução foi utilizar:

grails.plugins.springsecurity.securityConfigType = "InterceptUrlMap"

grails.plugins.springsecurity.interceptUrlMap = [

/**
* Pesquisa Controller mappings
*/

'/*': ['IS_AUTHENTICATED_ANONYMOUSLY']

etc...
etc...
etc...
]


E modificar a classe abstrata AbstractFilterInvocationDefinition.java:

	protected String lowercaseAndStripQuerystring(final String url) {

String fixed = url;

if (getUrlMatcher().requiresLowerCaseUrl()) {
fixed = fixed.toLowerCase();
}

if (_stripQueryStringFromUrls) {
int firstQuestionMarkIndex = fixed.indexOf("?");
if (firstQuestionMarkIndex != -1) {
fixed = fixed.substring(0, firstQuestionMarkIndex);
}

int jsessionid = fixed.indexOf(";");
if (jsessionid != -1){
fixed = fixed.substring(0, jsessionid);
}

}

return fixed;
}


Estou utilizando o Grails versão 2.1.3 + Spring Security Core 1.2.7.3 + Java 7

Eu estava utilizando a notação @Secured e essa solução não funciona nesse caso.

13/02/2013 17:46



Ainda não faz parte da comunidade???

Para se registrar, clique aqui.


Aprenda Groovy e Grails com a Formação itexto!

Newsletter Semana Groovy

Assinar

Envie seu link!


Livro de Grails


/dev/All

Os melhores blogs de TI (e em português) em um único lugar!

 
Creative Commons
RSS Grails Brasil é mantido por itexto Consultoria.
Em caso de problemas contacte Henrique Lobo Weissmann (Kico) por e-mail: kico@itexto.com.br
Todo o conteúdo presente neste site adota o Creative Commons como licença padrão.
Ver: 4.14.0
itexto