Segurança web em Java: Evitando SQL Injection, força bruta e outros ataques | Alura Cursos Online
Primeiras aulas do curso Segurança web em Java: Evitando SQL Injection, força bruta e outros ataques
Olá pessoal, tudo bem? Daremos uma breve introdução sobre o que veremos nesse curso de Segurança Web em Java utilizando o Spring MVC.
Durante o curso, simularemos o cenário onde fomos contratados pela empresa Alura Shows. Eles desenvolveram um sistema, e o nosso objetivo é encontrar possíveis vulnerabilidades.
A medida em que vamos encontrando os problemas, a nossa tarefa é ir corrigindo o projeto que os diretores da Alura Shows passaram para a gente, tornando a aplicação mais segura.
Na primeira parte, teremos um formulário onde os usuários se cadastrarão:
Porém, alguns usuários mal intencionados, tentarão enviar no formulário de login alguns códigos SQL, com o objetivo de se autenticar como se fosse um outro usuário. Faremos essas inserções de código, de forma automatizada, por meio de uma outra máquina que será um Kali Linux. No Kali Linux, teremos uma série de ferramentas que nos ajudarão a testar essas vulnerabilidades.
Inicialmente, as senhas dos usuários cadastrados na aplicação, serão armazenadas em texto puro. Encontraremos uma forma de armazenar a senha dos usuários utilizando o código Hash. Veremos como será todo esse processo de autenticação utilizando o código Hash.
Um de nossos usuários, tentará por meio de um programa, forçar várias senhas de forma automatizada. O objetivo é descobrir qual foi a senha usada por outro usuário ao se cadastrar.
Utilizaremos o botão de reCAPTCHA do Google, para ajudar a verificar que o login está sendo feito por um usuário humano. A ideia é que nós verifiquemos o clique no botão de reCAPTCHA, envie a informação para o Google, que responderá se o clique do botão foi aceito.
Para seguir de um forma mais tranquila com o curso, é recomendável que você tenha um pouco de conhecimento com o Spring.
Esse é o conteúdo que veremos na primeira parte do curso. Vamos começar?
SQL Injection - Inserindo códigos SQL
Nós fomos contratados pela Alura Shows, com os objetivos de realizarmos teste na aplicação que eles desenvolveram utilizando Spring MVC. O intuito é encontrar possíveis vulnerabilidades de segurança que podem existir, e caso a gente encontre alguma, a nossa tarefa será corrigi-la e torná-la mais segura.
No primeiro dia de reunião com os diretores da Alura Shows, nos foi passado os arquivos do projeto para começarmos a gerar os testes.
Com o projeto no Eclipse, para iniciarmos os testes, é necessário acessarmos a aplicação. Podemos arrastar com o mouse o projeto do Package Explorer, e soltá-lo no servidor configurado na aba "Servers". Agora basta pressionarmos o *Start the Server para que a aplicação inicie.
Após o Tomcat ser inicializado, acessaremos no navegador o endereço localhost:8080/alura-shows/. Seremos redirecionados para a página inicial da aplicação, que tem informações dos próximos eventos.
O objetivo da aplicação, é que os usuários interajam com o sistema para visualizar as datas dos próximos shows, comprar ingressos e assim por diante. Mas para isso, em algum momento o usuário terá que fazer um cadastro.
Para se cadastrar, o usuário tem que ir em "Usuário > Registrar":
Cadastraremos o primeiro usuário que se chama Alex. Colocaremos as seguintes informações no formulário de cadastro:
E-mail: `alex@gmail.com`
Imagem perfil: alex.jpg
Ao clicarmos em Registrar, as informações do usuário Alex serão armazenadas no banco de dados, em seguida seremos redirecionados para uma página que mostrará as informações do usuário. Após isso podemos clicar em "Logout".
A Alura Shows está ficando cada vez mais famosa, e outros usuário também querem se cadastrar no sistema. Cadastraremos outro usuário que se chama Fernando. Colocaremos as seguintes informações no formulário de cadastro:
E-mail: `fernando@gmail.com`
Imagem perfil: fernando.jpg
Temos os usuários Alex e Fernando cadastrados. Em algum momento, esses usuários terão que fazer uma autenticação no sistema. Vamos testar a autenticação.
Clicaremos em "Logout" para sair do perfil do Fernando. Em Login, no campo E-mail colocaremos `alex@gmail.come no campo **Senha** colocaremos123`. Como as informações estão corretas, é esperado que a autenticação seja aceita.
A autenticação funcionou! Mas, se em vez de usarmos a senha como 123 e colocarmos 0123456789, o que aconteceria? Receberemos a mensagem de Usuário não encontrado
Isso mostra que a validação da etapa de login está sendo feita, não permitindo que usuários com informações erradas acessem a aplicação.
Mas será que os desenvolvedores se preocuparam com os caracteres passados no formulário? Por exemplo, se colocarmos no campo E-mail `alex@gmail.come em **Senha** o caractere'` (aspas simples), o que aconteceria?
Recebemos uma Exception do sistema. A mensagem de erro emitida pela Exception é:
Você tem um erro na sua sintaxe SQL. Olhe o manual correspondente à sua versão do MySQL
Isso significa que os desenvolvedores da Alura Shows não estão fazendo a verificação de caracteres. Isso pode se tornar uma grande vulnerabilidade da aplicação.
Veremos o que podemos fazer em relação a essa injeção de código SQL.
SQL Injection - Forjando autenticação
Colocamos no campo da senha um caractere especial, que é a aspas simples. Com isso, tivemos um erro de sintaxe no SQL informando qual o tipo de banco que estamos usando. Tentaremos entender o porque essa Exception ocorreu.
Começaremos verificando para onde o formulário de login está enviando essas informações. Na página de login, clicaremos com o botão direito do mouse e selecionaremos "Inspecionar".
O formulário está enviando os dados para o endereço /alura-shows/login. Isso significa que temos um Controller na aplicação, com um método que está respondendo para o endereço /login.
No Eclipse dentro do pacote "controller" temos a classe UsuarioController, nela encontramos o método login(). O método recebe um Usuario usuario, onde é passado como argumento na chamada dao.procuraUsuario(usuario) para fazer a validação.
public String login(@ModelAttribute("usuario") Usuario usuario,
RedirectAttributes redirect, Model model, HttpSession session) {
Usuario usuarioRetornado = dao.procuraUsuario(usuario);
model.addAttribute("usuario", usuarioRetornado);
redirect.addFlashAttribute("mensagem", "Usuário não encontrado");
return "redirect:/usuario";
session.setAttribute("usuario", usuarioRetornado);
return "usuarioLogado";
Acessaremos então a classe UsuarioDaoImpl para analisar o método procuraUsuario(). No método, temos a query SQL, onde concatenamos os valores de e-mail e senha vindas do objeto usuario.
public Usuario procuraUsuario(Usuario usuario) {
String query = "SELECT * FROM Usuario WHERE email=" + "'"
+ usuario.getEmail() + "'" + " and senha=" + "'"
+ usuario.getSenha() + "';";
Para analisar o comando SQL, colocaremos em um única linha e removeremos todas as concatenações do Java. A query está sendo enviada ao banco de dados da seguinte forma:
SELECT * FROM Usuario WHERE email='usuario.getEmail()' and senha='usuario.getSenha()';
Quando o usuário envia seus dados para efetuar a autenticação no formulário de login, eles são recebidos e colocados na query que será enviada para o banco de dados. Os comandos Java serão subsistidos pelos valores e a query ficará da seguinte maneira:
SELECT * FROM Usuario WHERE email='alex@gmail.com' and senha=''';
Repare que as aspas simples usadas nos valores possuem abertura e fechamento, da mesma forma que fazemos com Strings em Java. Ao inserir uma aspas simples a mais no campo de senha, foi identificado que está faltando o seu fechamento e provocando o erro de sintaxe. Como as aspas delimitam valores do tipo String, é possível injetar códigos na query.
Por exemplo, o usuário Alex possui um pouco de conhecimento em programação e conhece o usuário Fernando. O Alex tem tem a intenção de efetuar o login com a conta do Fernando, por isso ele colocou no campo E-mail fernando@gmail.com e no campo Senha x. A query será enviada da seguinte forma:
SELECT * FROM Usuario WHERE email='fernando@gmail.com' and senha='x';
Essa query fará uma expressão booleana, analisando os valores passados de e-mail e senha com a dos usuários cadastrados. Quando o banco checar a conta do Fernando, será retornado true para o e-mail e false para a senha. Dessa forma o acesso será recusado, justamente porque os dois parâmetros precisam ser verdadeiros.
O que o Alex precisaria fazer para acessar a conta do Fernando, era transformar a o segundo parâmetro em verdadeiro. Colocando no campo Senha o valor x' or 'a' = 'a, a expressão ficará:
SELECT * FROM Usuario WHERE email='fernando@gmail.com' and senha='x' or 'a' = 'a';
Dessa forma, estamos dizendo que x ou 'a'='a' precisam ser verdadeiros. O x retornará false mas 'a'='a' sempre retornará true. Em expressões booleanas que utilizam operador OR (OU), apenas um valor precisa ser verdadeiro para que toda a expressão se torne verdadeira.
Com os dois parâmetros retornando verdadeiro, a autenticação será válida permitindo que o Alex entre na aplicação com a conta do Fernando. Em uma situação real, isso poderia trazer prejuízos ao usuário que teve a conta invadida.
Veremos outros detalhes que essa injeção de código SQL pode trazer de problemas para nós.
Sobre o curso Segurança web em Java: Evitando SQL Injection, força bruta e outros ataques
O curso Segurança web em Java: Evitando SQL Injection, força bruta e outros ataques possui 127 minutos de vídeos, em um total de 53 atividades. Gostou? Conheça nossos outros cursos de Java em Programação, ou leia nossos artigos de Programação.