Segurança da sua aplicação e os frameworks: o ataque ao GitHub
Quanto é necessário conhecer as suas ferramentas para garantia a segurança de sua aplicação?
Egor Homakov fez barulho durante o fim de semana. O russo realizou um commit no branch master do repositório do Rails, passando parâmetros a mais no formulário de registro de chaves públicas do Github, algo conhecido como injeção por parâmetros, dado o recurso de mass assignement do Rails. Homakov fez o ataque de forma muito simples, uma vez que ele inferiu que existia um modelo na aplicação chamado PublicKey
e que o mesmo possuía relacionamento com a classe User
. Com isso, ele adicionou um campo novo no formulário, para indicar quem é o dono de tal chave pública. Isso foi feito através de um input type="hidden" value="USER_ID" name="public_key[user_id]"
.
![Formulário de cadastro de chave pública no Github](assets/seguranca-de-sua-aplicacao-e-os-frameworks-ataque-ao-github/cadastro_sshkey_github-300x185.png "cadastro_sshkey_github")
Bastou submeter o formulário com o novo campo e o valor adequado, para que o usuário possuísse a chave pública que estava sendo cadastrada.
![Ataque ao Github](assets/seguranca-de-sua-aplicacao-e-os-frameworks-ataque-ao-github/github_hack.jpg "github_hack")
A resposta do GitHub, assim como a atitude de suspender o usuário, foi duramente criticada por alguns desenvolvedores, sendo revertida poucas horas depois.
Mas não é só o Rails que possui essa, digamos, facilidade-vulnerabilidade. O Spring já tinha uma issue registrada para isso e o Sergio Lopes já alertou sobre esse problema de injeção de parâmetros no modelo.
A solução no Rails é simples, mas pode ser facilmente esquecida e ignorada. Basta declararmos que não queremos que um determinado atributo seja populado pelo request, como numa lista negra:
attr\_protected :user\_id
Apesar dessa forma funcionar, você pode simplesmente esquecer de marcar como protected um atributo novo, adicionado ao modelo. A forma ideal seria declarar todos os atributos que podem ser massivamente modificados, uma white list, caso o atributo não esteja marcado dessa forma, ele não será atualizado:
attr\_accessible :name
Uma outra questão: de quem fica a responsabilidade nesse caso? O framework deveria permitir apenas white lists para popular objetos via request? Ou o desenvolvedor deveria sempre ficar atento a esses casos? De qualquer maneira, é mais um alerta de que sempre precisamos dominar o framework que utilizaremos.