Aqui ficam mais uma pequena demo que não cheguei a apresentar na sessão do TechDays. Embora inicialmente tivesse planeado apresentá-la logo no início da sessão, ainda bem que não o fiz, dado que é realmente.... básica :) e tinha ficado sem tempo para material mais importante.
Não tive hipótese de fazer a locução :), sendo assim deixo algumas notas para acompanhar. O vídeo da demo está aqui.
Este tipo de ataque é usualmente tido como um dos mais fáceis e mais antigos (embora infelizmente ainda se encontre aqui e ali). Consiste basicamente em detectar e alterar os campos hidden de um determinado formulário. Ok, mas desde quando é que alterar campos hidden pode ser considerado um problema de segurança? Pode, se o programador não considerou essa hipótese, partindo do princípio que 1º-os valores não pode ser vistos, e 2º-os valores não podem ser alterados. E obviamente estas duas suposições não poderiam ser mais erradas (e nem precisam do fiddler, o notepad serve perfeitamente tal como está na demo).
O campo hidden é uma coisa curiosa para alguém que pretenda atacar a nossa aplicação, que pensa imediatamente: "olé! se este valor aqui está é porque o programador haverá de fazer algo com ele, e se está hidden é porque o programador achou melhor não o apresentar, talvez não fosse suposto modificá-lo..... que é precisamente a primeira coisa que vou fazer! :) ".
Um exemplo curioso que me lembro de ler, de um cenário real. Após um ataque via sql injection, que permitia fazer o bypass do login (como viram na sessão), a aplicação xxx permitia que o atacante fosse à página de alteração de dados (a mesma que permitia alterar a password...). A genial source dessa página mostrava então algo do género (pasme-se):
....
...
Ponto 1-além do bypass da sessão (que pelo menos não permitia saber a password), o atacante sabe agora a password do utilizador!!! Será que este utilizador é uma daquelas pessoas que usam sempre a mesma password em todos os sites??? (estão a ver o problema...)
Ponto 2-O hidden userid sugere imediatamente que a página vai pegar no valor e usá-lo num sql do tipo "update .... where userid=valordocampohidden" . E se eu alterar este id para qualquer userid que não o meu? Será que funciona? Pior, e se este userid permitisse um novo ataque de sql injection, onde eu pudesse colocar "1 or 1=1" (conseguem imaginar o efeito deste where no update?) . E na verdade, neste cenário específico, ambas as suposições eram verdadeiras.
Como é que podemos ultrapassar estes ataques? Existem 2 padrões muito utilizados:
1-mantemos os dados do lado do servidor onde o utilizador não tem acesso directo (userid em sessão por exemplo, definido após login, embora esta técnica não seja mto usada em asp.net dado que temos o padrão seguinte)
2-se enviamos algum campo para o utilizador (leia-se browser cliente) que depois usamos, devemos assiná-lo de alguma forma, garantindo assim que podemos verificar que foi criado por nós e não foi adulterado. É isto que acontece com as cookies de autenticação do asp.net e também com o viewstate. Tentem manipular as cookies ou o viewstate e verão que o asp.net automaticamente gera uma excepção (e na versão 2.0 estes eventos ficam devidamente identificados no event log, com username respectivo caso exista) .
Resumindo, tanto quanto possível evitem os campos hidden dado que estes não oferecem *nenhuma* garantia. Se precisarem de um comportamento semelhante ao hidden podem usar um valor no viewstate, que fica automaticamente validado contra alterações do lado do cliente. Dito isto, já não é muito comum termos esta necessidade em asp.net.... provavelmente esta demo é desnecessária.
Uma nuance que pode ser importante, no caso específico da demo, é que ainda que se possa garantir através de viewstate\validação que o preço foi o definido pelo servidor, o que acontece se o postback for feito 2 meses após o get inicial da página? O preço era o correcto na altura mas pode ser totalmente incorrecto agora. Nestes casos, o melhor, é mesmo abdicar da pequena optimização de performance e repetir todo o processo de cálculo/lookup de preço na hora em que o processo é finalizado.
Acham que valeu a pena trazer este cenário? Digam coisas. :)
RQ