Por que a pré-compilação pode impedir a injeção de SQL? Uma olhada e você entenderá. Explicação detalhada do princípio de pré-compilação

"Página inicial do autor": Shibie Sanri wyx
"Sobre o autor": CSDN top100, especialista em blog Alibaba Cloud, especialista em compartilhamento de nuvem Huawei, criador de alta qualidade na área de segurança de rede
"Coluna recomendada": Amigos interessados ​​em segurança de rede podem siga a coluna "Segurança de rede do iniciante ao mestre"

Primeiro, vamos entender brevemente o processo de injeção de SQL.

Por exemplo, uma função de consulta consulta o nome de usuário e a senha com base no ID inserido pelo usuário.

Insira a descrição da imagem aqui

A instrução SQL em segundo plano é assim

select *from user where id='1'

Se enviarmos a carga útil nos parâmetros

 https://127.0.0.1/Less-1/?id=-1' union select 1, 2, user()-- a

O SQL de fundo será dividido assim (nota importante aqui: a estrutura da sintaxe do SQL foi alterada)

select *from user where id='-1' union select 1, 2, user()-- a'

Ajude-nos a encontrar a conta do administrador do banco de dados que causou a injeção de SQL.

Insira a descrição da imagem aqui


A partir do processo de injeção, podemos descobrir que o núcleo da injeção SQL é que os parâmetros inseridos pelo usuário alteram a estrutura sintática do SQL.

A pré-compilação pode impedir que a estrutura da sintaxe seja alterada. Antes de falar sobre pré-compilação, devemos primeiro entender o processo de execução do SQL.


1. Processo de execução SQL

Tomando o MySQL como exemplo, quando o banco de dados executa uma instrução SQL, ele precisa passar por 7 etapas:

  1. Análise lexical: decomponha a instrução SQL em tokens (palavras-chave, identificadores, operadores) e, em seguida, classifique e analise os tokens para gerar estruturas de dados correspondentes.
  2. Análise de sintaxe: Verifique se a sintaxe está correta de acordo com as regras de detecção de sintaxe SQL e forme uma árvore sintática.
  3. Análise semântica: percorra a árvore sintática, determine informações como tabelas e colunas e verifique a exatidão da semântica.
  4. Processamento de otimização: Use o otimizador para processar e otimizar instruções SQL, como planos de execução, índices, etc.
  5. Plano de execução: Use o gerador de plano de execução para gerar o plano de execução da instrução SQL, como como acessar dados, como usar índices, etc.
  6. Execução do mecanismo: envia o plano de execução ao mecanismo de banco de dados correspondente para processamento. O plano de execução é traduzido em instruções de operação subjacentes para realizar varredura de dados, pesquisa de índice, classificação, agrupamento e outras operações.
  7. Dados de retorno: Retorna resultados de execução ao cliente, como conjuntos de resultados de consulta ou resultados de operação.

Aqui, entendemos aproximadamente o processo de execução em duas etapas, a saber: primeiro compilar a estrutura da sintaxe SQL ( 1~3步) e, em seguida, executar a instrução SQL ( 4~7步).

Em circunstâncias normais, os parâmetros inseridos pelo usuário participarão diretamente na compilação da sintaxe SQL, enquanto a pré-compilação primeiro constrói uma árvore sintática, determina a estrutura da sintaxe SQL e depois une os parâmetros do usuário.

2. Princípio da pré-compilação

O objetivo original da pré-compilação é melhorar a capacidade de reutilização do código, pois existem muitos SQLs que possuem apenas valores de parâmetros diferentes (exatamente o mesmo SQL será consultado no cache), como:

select * from user where id='1'
select * from user where id='2'

As árvores de sintaxe desses SQLs são as mesmas, mas precisam ser compiladas repetidamente todas as vezes, o que é uma perda de tempo.

A pré-compilação pode modelar a instrução SQL e substituir a posição do valor por um espaço reservado.Desta forma, o banco de dados compilará a estrutura de sintaxe SQL antecipadamente e depois passará o valor para execução quando for realmente chamado, eliminando a necessidade de repetir construir uma árvore de sintaxe.

select * from user where id={占位符}

A julgar pela captura de pacotes, a instrução SQL é primeiro pré-compilada (instrução Prepare) e os valores dos parâmetros são primeiro substituídos por espaços reservados. Ao executar (Execute Statement), passe os parâmetros.

Insira a descrição da imagem aqui

Os parâmetros passados ​​pelo usuário não participam da construção da árvore sintática, portanto a estrutura sintática do SQL não pode ser alterada, evitando assim a injeção.

Extensões:

O PDO (PHP Data Object) do PHP é uma interface unificada para operar vários bancos de dados e fornece dois mecanismos de pré-compilação: pré-compilação local e pré-compilação simulada.
A pré-compilação local refere-se à pré-compilação do próprio banco de dados, que também é o método de pré-compilação que mencionamos aqui.
A pré-compilação simulada é usada para bancos de dados que não suportam pré-compilação.Essencialmente, a entrada do usuário é traduzida no nível inferior e, em seguida, a instrução SQL é emendada e, em seguida, a instrução SQL completa é enviada ao banco de dados para execução.
Os parâmetros traduzidos serão tratados apenas como strings e não podem participar da compilação SQL (antes do PHP 5.3.6, a tradução do conjunto de caracteres de byte único era usada e existia a injeção de byte único). A configuração correta do conjunto de caracteres também pode impedir a injeção de SQL.


3. Pré-compilar para evitar injeção de SQL

Tomemos como exemplo MyBatis (estrutura de camada de persistência semiautomática). #{id}Ao passar parâmetros neste formato, o SQL será primeiro passado para o banco de dados para pré-compilação. Quando chamados, os espaços reservados serão substituídos por parâmetros e depois executados.

<select id="getUser" resultType="Blog" parameterType=int>
         SELECT *
         FROM user
		 WHERE id=#{
    
    id}
</select>

No entanto, alguns SQL requerem o uso de nomes de tabelas e colunas dinâmicas. Nesse caso, a pré-compilação não pode ser usada e precisa ser substituída. Dessa forma, os parâmetros #{id}participarão ${id}diretamente da compilação SQL e não poderão impedir a injeção de SQL. Neste momento , os parâmetros deverão ser filtrados manualmente.

Dica: A pré-compilação da estrutura MyBatis é a classe PreparedStatement em JDBC e seu objeto contém instruções SQL compiladas.

Usando a função de pré-compilação do MySQL em PHP:

1) Defina a instrução SQL pré-compilada e os parâmetros são representados por espaços reservados?

$sql = "SELECT * FROM user WHERE id= ? ";

2) Crie objetos de pré-processamento

$mysqli_stmt = $mysqli->prepare($sql);

3) Vincular parâmetros

$mysqli_stmt->bind_param('i', $id);

4) Vincule o conjunto de resultados

$mysqli_stmt->bind_result($username);

5) Execução

$mysqli_stmt->execute();

4. Limitações da pré-compilação

O mecanismo de pré-compilação consiste em compilar primeiro e depois passar o valor.Os parâmetros passados ​​pelo usuário não podem alterar a estrutura da sintaxe SQL, o que resolve fundamentalmente o problema de injeção de SQL.

Mas nem todos os parâmetros podem usar pré-compilação, como o cenário de nomes de tabelas dinâmicas e nomes de colunas. Porque durante a análise semântica, a árvore de sintaxe será analisada para verificar se o nome da tabela e o nome da coluna existem, portanto, o nome da tabela e o nome da coluna não podem ser substituído por espaços reservados. Não há como usar a pré-compilação.

Da mesma forma, ASC/DESC em cenários de classificação também requer transferência dinâmica de parâmetros e a pré-compilação não pode ser usada.

Acho que você gosta

Origin blog.csdn.net/wangyuxiang946/article/details/132356363
Recomendado
Clasificación