sql >> Databáze >  >> RDS >> Mysql

Jak mohu chránit uživatelské jméno a heslo MySQL před dekompilací?

Nikdy do svého kódu nezadávejte hesla napevno. Toto bylo nedávno uvedeno v 25 nejnebezpečnějších programovacích chyb :

Pevné kódování tajného účtu a hesla do vašeho softwaru je mimořádně pohodlné – pro zkušené zpětné inženýry. Pokud je heslo stejné pro celý váš software, pak se každý zákazník stane zranitelným, jakmile se toto heslo nevyhnutelně stane známým. A protože je napevno zakódovaný, je velmi těžké ho opravit.

Informace o konfiguraci, včetně hesel, byste měli ukládat do samostatného souboru, který aplikace čte při spuštění. To je jediný skutečný způsob, jak zabránit úniku hesla v důsledku dekompilace (nikdy je nezkompilujte do binárního kódu).

Další informace o této běžné chybě si můžete přečíst v článku CWE-259 . Článek obsahuje důkladnější definici, příklady a spoustu dalších informací o problému.

V Javě je jedním z nejjednodušších způsobů, jak toho dosáhnout, použití třídy Preferences. Je navržen pro ukládání všech druhů nastavení programu, z nichž některá mohou obsahovat uživatelské jméno a heslo.

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
}

Ve výše uvedeném kódu můžete zavolat setCredentials po zobrazení dialogového okna s dotazem na uživatelské jméno a heslo. Když se potřebujete připojit k databázi, stačí použít getUsername a getPassword metody pro načtení uložených hodnot. Přihlašovací údaje nebudou pevně zakódovány do vašich binárních souborů, takže dekompilace nebude představovat bezpečnostní riziko.

Důležitá poznámka: Soubory preferencí jsou pouze prosté textové soubory XML. Ujistěte se, že jste provedli vhodná opatření, abyste zabránili neoprávněným uživatelům v prohlížení nezpracovaných souborů (oprávnění UNIX, oprávnění Windows atd.). Alespoň v Linuxu to není problém, protože volání Preferences.userNodeForPackage vytvoří soubor XML v domovském adresáři aktuálního uživatele, který je stejně pro ostatní uživatele nečitelný. Ve Windows může být situace jiná.

Další důležité poznámky: V komentářích této odpovědi a dalších se hodně diskutovalo o tom, jaká je správná architektura pro tuto situaci. Původní otázka ve skutečnosti nezmiňuje kontext, ve kterém je aplikace používána, takže budu mluvit o dvou situacích, které mě napadají. První je případ, kdy osoba používající program již zná (a je oprávněna znát) přihlašovací údaje k databázi. Druhým je případ, kdy se vy, vývojář, snažíte utajit přihlašovací údaje k databázi před osobou používající program.

První případ:Uživatel je oprávněn znát přihlašovací údaje k databázi

V tomto případě bude fungovat řešení, které jsem uvedl výše. Preference Java class uloží uživatelské jméno a heslo jako prostý text, ale soubor předvoleb bude čitelný pouze pro oprávněného uživatele. Uživatel může jednoduše otevřít soubor XML s předvolbami a přečíst si přihlašovací údaje, ale to nepředstavuje bezpečnostní riziko, protože uživatel přihlašovací údaje na začátku znal.

Druhý případ:Pokus o skrytí přihlašovacích údajů před uživatelem

Toto je složitější případ:uživatel by neměl znát přihlašovací údaje, ale stále potřebuje přístup k databázi. V tomto případě má uživatel spouštějící aplikaci přímý přístup k databázi, což znamená, že program potřebuje znát přihlašovací údaje předem. Řešení, které jsem uvedl výše, není pro tento případ vhodné. Přihlašovací údaje k databázi můžete uložit do souboru předvoleb, ale uživatel bude moci tento soubor číst, protože bude vlastníkem. Ve skutečnosti neexistuje žádný dobrý způsob, jak toto pouzdro používat bezpečným způsobem.

Správný případ:Použití vícevrstvé architektury

Správný způsob, jak to udělat, je mít mezi databázovým serverem a klientskou aplikací střední vrstvu, která ověřuje jednotlivé uživatele a umožňuje provádět omezenou sadu operací. Každý uživatel by měl své vlastní přihlašovací údaje, ale ne pro databázový server. Přihlašovací údaje by umožňovaly přístup ke střední vrstvě (vrstva obchodní logiky) a pro každého uživatele by byly jiné.

Každý uživatel by měl své vlastní uživatelské jméno a heslo, které by bylo možné uložit lokálně do souboru předvoleb bez jakéhokoli bezpečnostního rizika. Říká se tomu třívrstvá architektura (úrovněmi jsou váš databázový server, server obchodní logiky a klientská aplikace). Je to složitější, ale je to skutečně nejbezpečnější způsob, jak něco takového udělat.

Základní pořadí operací je:

  1. Klient se ověřuje pomocí úrovně obchodní logiky pomocí osobního uživatelského jména/hesla uživatele. Uživatelské jméno a heslo jsou uživateli známy a nijak nesouvisí s přihlašovacími údaji k databázi.
  2. Pokud je ověření úspěšné, klient odešle požadavek na úroveň obchodní logiky a požádá o některé informace z databáze. Například inventář produktů. Všimněte si, že požadavek klienta není SQL dotaz; je to vzdálené volání procedury, jako je getInventoryList .
  3. Vrstva obchodní logiky se připojí k databázi a načte požadované informace. Vrstva obchodní logiky má na starosti vytvoření zabezpečeného SQL dotazu na základě požadavku uživatele. Všechny parametry dotazu SQL by měly být dezinfikovány, aby se zabránilo útokům SQL injection.
  4. Vrstva obchodní logiky odešle seznam inventáře zpět do klientské aplikace.
  5. Klient zobrazí uživateli seznam inventáře.

Všimněte si, že v celém procesu klientská aplikace se nikdy nepřipojí přímo k databázi . Vrstva obchodní logiky přijme požadavek od ověřeného uživatele, zpracuje klientský požadavek na inventář a teprve poté provede SQL dotaz.



  1. Nelze zkrátit tabulku, protože na ni odkazuje omezení FOREIGN KEY - SQL Server / Výukový program TSQL, část 70

  2. Jak funguje pg_sleep_for() v PostgreSQL

  3. Převeďte název měsíce na číslo měsíce v SQL Server

  4. Role DBA v NoSQL