sql >> Databasteknik >  >> RDS >> Mysql

Hur kan jag skydda MySQL användarnamn och lösenord från dekompilering?

Hårdkoda aldrig lösenord i din kod. Detta togs upp nyligen i Top 25 mest farliga programmeringsmisstag :

Att hårdkoda ett hemligt konto och lösenord i din programvara är oerhört bekvämt - för skickliga, omvända ingenjörer. Om lösenordet är detsamma för all din programvara, blir varje kund sårbar när lösenordet oundvikligen blir känt. Och eftersom det är hårdkodat är det en enorm smärta att fixa.

Du bör lagra konfigurationsinformation, inklusive lösenord, i en separat fil som programmet läser när det startar. Det är det enda riktiga sättet att förhindra att lösenordet läcker som ett resultat av dekompilering (kompilera det aldrig till binären till att börja med).

För mer information om detta vanliga misstag kan du läsa CWE-259-artikeln . Artikeln innehåller en mer grundlig definition, exempel och mycket annan information om problemet.

I Java är ett av de enklaste sätten att göra detta att använda klassen Preferences. Den är utformad för att lagra alla möjliga programinställningar, av vilka några kan innehålla ett användarnamn och lösenord.

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
}

I koden ovan kan du anropa setCredentials efter att ha visat en dialogruta, fråga efter användarnamn och lösenord. När du behöver ansluta till databasen kan du bara använda getUsername och getPassword metoder för att hämta de lagrade värdena. Inloggningsuppgifterna kommer inte att hårdkodas i dina binärer, så dekompilering kommer inte att utgöra en säkerhetsrisk.

Viktig anmärkning: Inställningsfilerna är bara XML-filer med vanlig text. Se till att du vidtar lämpliga åtgärder för att förhindra obehöriga användare från att se råfilerna (UNIX-behörigheter, Windows-behörigheter, et cetera). Åtminstone i Linux är detta inget problem, eftersom att anropa Preferences.userNodeForPackage kommer att skapa XML-filen i den aktuella användarens hemkatalog, som ändå inte är läsbar av andra användare. I Windows kan situationen vara annorlunda.

Fler viktiga anmärkningar: Det har varit mycket diskussion i kommentarerna till detta svar och andra om vad den korrekta arkitekturen är för denna situation. Den ursprungliga frågan nämner inte riktigt i vilket sammanhang applikationen används, så jag kommer att prata om de två situationer jag kan tänka mig. Det första är fallet där personen som använder programmet redan känner till (och har behörighet att känna till) databasens referenser. Det andra är fallet där du, utvecklaren, försöker hålla databasuppgifterna hemliga för personen som använder programmet.

Första fallet:Användaren har behörighet att känna till databasens inloggningsuppgifter

I det här fallet kommer lösningen jag nämnde ovan att fungera. Java Preference class kommer att lagra användarnamnet och lösenordet i vanlig text, men inställningsfilen kommer endast att kunna läsas av den auktoriserade användaren. Användaren kan helt enkelt öppna inställnings-XML-filen och läsa inloggningsuppgifterna, men det är ingen säkerhetsrisk eftersom användaren kände till autentiseringsuppgifterna till att börja med.

Andra fallet:Försöker dölja inloggningsuppgifter för användaren

Detta är det mer komplicerade fallet:användaren ska inte känna till inloggningsuppgifterna men behöver fortfarande tillgång till databasen. I det här fallet har användaren som kör programmet direkt tillgång till databasen, vilket innebär att programmet måste känna till inloggningsuppgifterna i förväg. Lösningen jag nämnde ovan är inte lämplig för detta fall. Du kan lagra inloggningsuppgifterna för databasen i en inställningsfil, men användaren kommer att kunna läsa den filen, eftersom de kommer att vara ägaren. Det finns faktiskt inget bra sätt att använda detta fodral på ett säkert sätt.

Rätt fall:Använda en flerskiktsarkitektur

Det korrekta sättet att göra det är att ha ett mellanlager, mellan din databasserver och din klientapplikation, som autentiserar enskilda användare och tillåter att en begränsad uppsättning operationer kan utföras. Varje användare skulle ha sina egna inloggningsuppgifter, men inte för databasservern. Autentiseringsuppgifterna skulle ge åtkomst till mellanskiktet (affärslogiknivån) och skulle vara olika för varje användare.

Varje användare skulle ha sitt eget användarnamn och lösenord, som skulle kunna lagras lokalt i en inställningsfil utan någon säkerhetsrisk. Detta kallas en tre-lagsarkitektur (nivåerna är din databasserver, affärslogikserver och klientapplikation). Det är mer komplext, men det är verkligen det säkraste sättet att göra den här typen av saker.

Den grundläggande ordningen för operationer är:

  1. Klienten autentiserar med affärslogiknivå med användarens personliga användarnamn/lösenord. Användarnamnet och lösenordet är kända för användaren och är inte relaterade till databasens inloggningsuppgifter på något sätt.
  2. Om autentiseringen lyckas, gör klienten en begäran till affärslogiknivån och ber om viss information från databasen. Till exempel en inventering av produkter. Observera att klientens begäran inte är en SQL-fråga; det är ett fjärranrop som t.ex. getInventoryList .
  3. Affärslogiknivån ansluter till databasen och hämtar den begärda informationen. Affärslogiknivån ansvarar för att skapa en säker SQL-fråga baserat på användarens begäran. Alla parametrar till SQL-frågan bör saneras för att förhindra SQL-injektionsattacker.
  4. Affärslogiknivån skickar inventeringslistan tillbaka till klientapplikationen.
  5. Klienten visar inventeringslistan för användaren.

Observera att under hela processen ansluter klientapplikationen aldrig direkt till databasen . Affärslogiknivån tar emot en begäran från en autentiserad användare, bearbetar klientens begäran om en inventeringslista och kör först därefter en SQL-fråga.



  1. Välj SQL Server-databasstorlek

  2. Använda ett Alias ​​i en WHERE-sats

  3. Hur EXTRACTVALUE() fungerar i MariaDB

  4. De bästa varnings- och meddelandeverktygen för PostgreSQL