AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 36078
Accepted
Nathan Long
Nathan Long
Asked: 2013-03-07 06:48:18 +0800 CST2013-03-07 06:48:18 +0800 CST 2013-03-07 06:48:18 +0800 CST

Posso configurar o typecasting do MySQL para considerar 0 != 'foo'?

  • 772

Este artigo aponta o seguinte problema de segurança com o MySQL:

USERS
id | email            | password_reset_token
1  | [email protected]  | QTlXww)uV!Hdg3U6aGwKV2FPvAqzVgPx
2  | [email protected]  | CZor5t7WbX#LTeqiG3v@6f3@z#)BfK*n

Aqui temos bons tokens aleatórios que um usuário deve provar que possui para redefinir sua conta. Mas o usuário consegue enviar um token de redefinição de 0, então executamos esta consulta:

SELECT * FROM `users` WHERE `email` = '[email protected]' AND `password_reset_token` = 0

O MySQL converte o token VARCHARem um INTpara fazer a comparação . Ele considera a VARCHARque não começa com um número igual a 0. Portanto, um invasor pode corresponder a qualquer string não numérica e assumir o controle da conta .

Mesmo que o token de reinicialização inicie alguns números, a situação não é muito melhor. O MySQL ignora todos os caracteres, exceto os números iniciais, ao fazer essa comparação, portanto, considera 12blahblah3blah4igual a 12, o que torna a adivinhação exponencialmente mais fácil.

Posso configurar o MySQL para não fazer esse tipo de typecasting? Se, por exemplo, fosse lançado INTem VARCHARvez de vice-versa, esse ataque não funcionaria.

Observação

Se a consulta for executada com '0'em vez de 0, isso não funcionará. O artigo discute essa vulnerabilidade em termos da aceitação de XML do Ruby on Rails, onde uma type=integerpropriedade convenceu o Rails a enviar um inteiro real na consulta.

Esse bug foi corrigido no Rails; agora ele converte todos os parâmetros de solicitação em strings, portanto, nunca criaria uma consulta com um número inteiro. Mas ainda acho que o MySQL deve ser configurável para evitar isso.

mysql security
  • 2 2 respostas
  • 704 Views

2 respostas

  • Voted
  1. Best Answer
    Michael - sqlbot
    2013-03-07T11:27:40+08:002013-03-07T11:27:40+08:00

    O problema, porém, é que você está fornecendo um valor numérico, sem aspas, então o MySQL tenta converter o outro lado da comparação como um DOUBLE, para compará-lo com o argumento numérico que você forneceu ... o que deixa você com um 0 isso é equivalente a 0.

    mysql> select 'foo' = 0;
    +-----------+
    | 'foo' = 0 |
    +-----------+
    |         1 |
    +-----------+
    1 row in set, 1 warning (0.00 sec)
    
    mysql> show warnings;
    +---------+------+-----------------------------------------+
    | Level   | Code | Message                                 |
    +---------+------+-----------------------------------------+
    | Warning | 1292 | Truncated incorrect DOUBLE value: 'foo' |
    +---------+------+-----------------------------------------+
    1 row in set (0.00 sec)
    

    Se você fornecer o 0 em um contexto de string, isso será avaliado como falso.

    mysql> select 'foo' = '0';
    +-------------+
    | 'foo' = '0' |
    +-------------+
    |           0 |
    +-------------+
    1 row in set (0.00 sec)
    

    Portanto, uma opção que você poderia usar para evitar esse comportamento seria converter seu valor de entrada como um CHAR... o que, na maioria das vezes, já é ... mas, se não, será avaliado conforme o esperado.

    mysql> select 'foo' = cast(0 as char);
    +-------------------------+
    | 'foo' = cast(0 as char) |
    +-------------------------+
    |                       0 |
    +-------------------------+
    1 row in set (0.00 sec)
    

    update , para responder mais completamente à pergunta:

    Posso configurar o MySQL para não fazer esse tipo de typecasting?

    Não, não parece haver nenhuma maneira de evitar isso por meio de configuração - apenas por meio de um elenco explícito de sua string de aparência numérica potencial - para uma string, que você disse que não pode ser realizada desde que você está usando um ORM. O local mais provável, se existisse algo assim, seria SQL Server Mode , e nenhuma dessas opções modifica esse comportamento quando se trata de comparações.

    Há um pouco de discussão sobre conversões implícitas como esta no Bug #63112 :

    SELECIONE laranja > banana;

    Isso é verdadeiro ou falso? Bem ... na maioria das vezes uma banana é mais longa que uma laranja. Portanto, se o comprimento for o critério, a afirmação acima é falsa. Mas, na maioria das vezes, uma laranja é mais pesada que uma banana, portanto, se o peso for o critério, a afirmação acima é verdadeira.

    Ao comparar diferentes tipos (laranja versus banana, string versus inteiro), alguns 'critérios' ou 'regra' deverão ser usados. Quando o MySQL compara diferentes tipos de dados, eles são [ambos] convertidos para DOUBLE internamente antes da comparação. O inteiro "1" converte para o duplo "1" - a string 'a' ou 'UUID()' converte para o duplo "0". [...]

    Observe que o escopo deste relatório de bug não é estritamente limitado a conversão implícita em contexto externo, e a menção UUID()aqui é um pouco distrativa, pois UUID()pode retornar strings começando com dígitos e converter para outros números ... mas acho que serve para confirmar que não existe alternativa, pois nada é apresentado além de "não use tipos diferentes para comparação se quiser evitar um elenco", que já sabemos. Isto continua:

    Para evitar a conversão para DOUBLEgarantir internamente que os valores comparados sejam do mesmo tipo de dados. No seu caso, as idcolunas são strings e o valor com o qual você compara também deve ser strings (não 1, mas '1' - não 2, mas '2' etc.) ou use cast()/ convert()em sua declaração [...]

    Em relação à sua sugestão de que, se a conversão implícita for feita, o número deve se tornar uma string em vez da string se tornar um número ... Posso ver seu ponto, até certo ponto, para comparações de igualdade estrita ... mas há muitos outros operadores além =e usando essa lógica, surge toda uma nova série de problemas...

    mysql> SELECT CAST(100 AS CHAR) < '2';
    +-------------------------+
    | CAST(100 AS CHAR) < '2' |
    +-------------------------+
    |                       1 |
    +-------------------------+
    1 row in set (0.00 sec)
    

    Correto! A string '100' é "menor que" a string '2' em sentido alfabético... da mesma forma que a string 'AXX' é "menor que" a string 'B'. Portanto, essa alternativa certamente tem suas desvantagens.

    Existe, no entanto, uma terceira alternativa, que parece ser a lógica mais precisa (embora eu aceite uma objeção construtiva): Se uma string que começa com um caractere não-dígito é convertida para a DOUBLE(ou qualquer outro tipo numérico, nesse caso ), parece que o resultado mais correto dessa conversão seria NULL .

    Infelizmente, esta não é a abordagem do MySQL. Parece que isso pode ser corrigido na fonte, possivelmente sql/field.cconde o '0' retornado por my_strntod () parece ser simplesmente retornado ao chamador após lançar o aviso se ocorreu um erro, mas tentando tal hack tão profundo na fonte está além da minha especialidade.

    • 11
  2. atxdba
    2013-03-07T08:38:09+08:002013-03-07T08:38:09+08:00

    Primeiro, se sua consulta final estava sendo gerada dessa forma, parece implicar em pegar a entrada direta do usuário e colá-la em um modelo de consulta, o que em si é o problema da injeção de SQL. Além disso, mesmo se você estivesse fazendo isso, o modelo de consulta precisaria estar entre aspas para que as solicitações legítimas de entradas charish fossem sintaticamente válidas.

    Qualquer que seja a linguagem que seu aplicativo esteja usando, ruby ​​ou não, procure como eles fazem consultas parametrizadas e instruções preparadas. A API cuidará de todo o escape adequado para você.

    • 2

relate perguntas

  • Existem ferramentas de benchmarking do MySQL? [fechado]

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

  • Quando é o momento certo para usar o MariaDB em vez do MySQL e por quê?

  • Como um grupo pode rastrear alterações no esquema do banco de dados?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Conceder acesso a todas as tabelas para um usuário

    • 5 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve