Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como posso proteger o nome de usuário e a senha do MySQL da descompilação?


Nunca codifique senhas em seu código. Isso foi mencionado recentemente no Top 25 Erros de Programação Mais Perigosos :

Codificar uma conta secreta e uma senha em seu software é extremamente conveniente - para engenheiros reversos qualificados. Se a senha for a mesma em todo o software, todos os clientes ficarão vulneráveis ​​quando essa senha inevitavelmente for conhecida. E porque é codificado, é uma dor enorme para consertar.

Você deve armazenar informações de configuração, incluindo senhas, em um arquivo separado que o aplicativo lê quando é iniciado. Essa é a única maneira real de evitar que a senha vaze como resultado da descompilação (nunca a compile no binário para começar).

Para obter mais informações sobre esse erro comum, leia o artigo CWE-259 . O artigo contém uma definição mais completa, exemplos e muitas outras informações sobre o problema.

Em Java, uma das maneiras mais fáceis de fazer isso é usar a classe Preferences. Ele foi projetado para armazenar todos os tipos de configurações do programa, algumas das quais podem incluir um nome de usuário e senha.
import java.util.prefs.Preferences;

public class DemoApplication {
  Preferences preferences = 
      Preferences.userNodeForPackage(DemoApplication.class);

  public void setCredentials(String username, String password) {
    preferences.put("db_username", username);
    preferences.put("db_password", password);
  }

  public String getUsername() {
    return preferences.get("db_username", null);
  }

  public String getPassword() {
    return preferences.get("db_password", null);
  }

  // your code here
}

No código acima, você pode chamar o setCredentials após mostrar uma caixa de diálogo solicitando o nome de usuário e a senha. Quando você precisar se conectar ao banco de dados, basta usar o getUsername e getPassword métodos para recuperar os valores armazenados. As credenciais de login não serão codificadas em seus binários, portanto, a descompilação não representará um risco de segurança.

Observação importante: Os arquivos de preferência são apenas arquivos XML de texto simples. Certifique-se de tomar as medidas apropriadas para impedir que usuários não autorizados visualizem os arquivos brutos (permissões do UNIX, permissões do Windows etc.). No Linux, pelo menos, isso não é um problema, porque chamar Preferences.userNodeForPackage criará o arquivo XML no diretório inicial do usuário atual, que não pode ser lido por outros usuários de qualquer maneira. No Windows, a situação pode ser diferente.

Observações mais importantes: Houve muita discussão nos comentários desta resposta e de outros sobre qual é a arquitetura correta para essa situação. A pergunta original realmente não menciona o contexto em que o aplicativo está sendo usado, então falarei sobre as duas situações em que posso pensar. O primeiro é o caso em que a pessoa que usa o programa já conhece (e está autorizada a conhecer) as credenciais do banco de dados. O segundo é o caso em que você, o desenvolvedor, está tentando manter as credenciais do banco de dados em segredo da pessoa que usa o programa.

Primeiro caso:o usuário está autorizado a conhecer as credenciais de login do banco de dados

Nesse caso, a solução que mencionei acima funcionará. A Preference Java class armazenará o nome de usuário e a senha em texto simples, mas o arquivo de preferências só poderá ser lido pelo usuário autorizado. O usuário pode simplesmente abrir o arquivo XML de preferências e ler as credenciais de login, mas isso não é um risco de segurança porque o usuário já conhecia as credenciais.

Segundo caso:tentando ocultar as credenciais de login do usuário

Este é o caso mais complicado:o usuário não deve saber as credenciais de login, mas ainda precisa acessar o banco de dados. Nesse caso, o usuário que executa o aplicativo tem acesso direto ao banco de dados, o que significa que o programa precisa conhecer as credenciais de login com antecedência. A solução que mencionei acima não é apropriada para este caso. Você pode armazenar as credenciais de login do banco de dados em um arquivo de preferências, mas o usuário poderá ler esse arquivo, pois ele será o proprietário. Na verdade, não há realmente nenhuma boa maneira de usar esse caso de maneira segura.

Caso correto:usando uma arquitetura multicamada

A maneira correta de fazer isso é ter uma camada intermediária, entre o servidor de banco de dados e o aplicativo cliente, que autentique usuários individuais e permita que um conjunto limitado de operações seja executado. Cada usuário teria suas próprias credenciais de login, mas não para o servidor de banco de dados. As credenciais permitiriam o acesso à camada intermediária (a camada de lógica de negócios) e seriam diferentes para cada usuário.

Cada usuário teria seu próprio nome de usuário e senha, que poderiam ser armazenados localmente em um arquivo de preferências sem nenhum risco de segurança. Isso é chamado de arquitetura de três camadas (as camadas sendo seu servidor de banco de dados, servidor de lógica de negócios e aplicativo cliente). É mais complexo, mas realmente é a maneira mais segura de fazer esse tipo de coisa.

A ordem básica das operações é:
  1. O cliente é autenticado com a camada de lógica de negócios usando o nome de usuário/senha pessoal do usuário. O nome de usuário e a senha são conhecidos pelo usuário e não estão relacionados às credenciais de login do banco de dados de forma alguma.
  2. Se a autenticação for bem-sucedida, o cliente fará uma solicitação à camada de lógica de negócios solicitando algumas informações do banco de dados. Por exemplo, um inventário de produtos. Observe que a solicitação do cliente não é uma consulta SQL; é uma chamada de procedimento remoto como getInventoryList .
  3. A camada de lógica de negócios se conecta ao banco de dados e recupera as informações solicitadas. A camada lógica de negócios é responsável por formar uma consulta SQL segura com base na solicitação do usuário. Quaisquer parâmetros para a consulta SQL devem ser higienizados para evitar ataques de injeção de SQL.
  4. A camada de lógica de negócios envia a lista de inventário de volta ao aplicativo cliente.
  5. O cliente exibe a lista de inventário para o usuário.

Observe que em todo o processo, o aplicativo cliente nunca se conecta diretamente ao banco de dados . A camada de lógica de negócios recebe uma solicitação de um usuário autenticado, processa a solicitação do cliente para uma lista de inventário e só então executa uma consulta SQL.