Zabezpečení databáze a dat

Z PostgreSQL
Verze z 19. 7. 2013, 09:17, kterou vytvořil Pavel (diskuse | příspěvky) (Založena nová stránka: ===Základní doporučení z hlediska bezpečnosti přístupu=== * Používejte více databázových (případně systémových) účtů * Aplikační databázový uživ…)

(rozdíl) ← Starší verze | zobrazit aktuální verzi (rozdíl) | Novější verze → (rozdíl)
Přejít na: navigace, hledání

Základní doporučení z hlediska bezpečnosti přístupu

  • Používejte více databázových (případně systémových) účtů
  • Aplikační databázový uživatel nikdy nesmí být vlastníkem databázových objektů (vlastníkem tabulek, funkcí, databází)
  • Je praktické používat pouze jeden vyhrazený účet, který slouží jako vlastník všech db objektů - tento účet (pokud možno) nikdy nepoužíváme z veřejně dostupné aplikace! Např. omezíme možnost přihlášení pouze z lokální sítě. Důležité: heslo k tomuto účtu není nikde uloženo (maximálně někde v zapečetěné obálce v trezoru).

Verifikace hesla bez možnosti čtení tabulky s uloženými hesly

Aplikační databázový uživatel musí mít přístup k tabulce obsahující seznam uživatelů a hashi hesel, aby mohl ověřit účet a heslo. To ale znamená významné bezpečnostní riziko, pokud by došlo ke kompromitování aplikačního databázového účtu. Pak je možné si stáhnout seznam uživatelů. Možným řešením je použití SECURITY DEFINER funkce - to je funkce, jejíž tělo je výkonáváno s právy vlastníka funkce (nikoliv s právy volajícího). Tato funkce umožní vykonání jasně definovaného bezpečného kódu s dočasně změněnou identitou. V případě kompromitace účtu může účastník volat tyto funkce, ale nemá přístup k tabulce uživatelů/hesel.

postgres=# CREATE ROLE eshop_owner NOLOGIN;
CREATE ROLE
postgres=# CREATE ROLE eshop_app LOGIN;
CREATE ROLE
postgres=# ALTER ROLE eshop_app PASSWORD 'bezpecnejsiHeslo';
ALTER ROLE

SET ROLE TO eshop_owner;
CREATE TABLE eshop_users(account text CHECK (account <> '') PRIMARY KEY, password text CHECK (password <> ''));

CREATE OR REPLACE FUNCTION public.new_account(account text, password text)
 RETURNS void
 LANGUAGE plpgsql
 SECURITY DEFINER
 SET search_path TO pg_catalog
AS $function$
BEGIN
  IF coalesce(trim(new_account.account), '') = '' THEN
    RAISE EXCEPTION 'cannot create account'
       USING DETAIL='Name is empty string.';
  ELSEIF coalesce(trim(new_account.password), '') = '' THEN
    RAISE EXCEPTION 'cannot create account "%"', new_account.account
       USING DETAIL='Password is empty string'; 
  END IF;

  INSERT INTO public.eshop_users(account,password)
    VALUES(trim(new_account.account), 
           md5(new_account.password || trim(new_account.account) || 'somerandomstr')); 

EXCEPTION 
  WHEN unique_violation THEN
    PERFORM pg_sleep(random());
    RAISE EXCEPTION 'cannot create account "%"', new_account.account
       USING DETAIL='User already exists';
  WHEN others THEN
    PERFORM pg_sleep(random());
    -- reraise exception
    RAISE;
END;
$function$;

CREATE OR REPLACE FUNCTION public.verify_password(account text, password text)
 RETURNS boolean
 LANGUAGE plpgsql
 SECURITY DEFINER
 SET search_path TO pg_catalog
AS $function$
BEGIN
  IF EXISTS(SELECT *
               FROM public.eshop_users e
              WHERE e.account = trim(verify_password.account)
                AND e.password=md5(verify_password.password || trim(verify_password.account) || 'somerandomstr'))
  THEN
    RETURN true;
  ELSE
    PERFORM pg_sleep(random());
    RETURN false;
  END IF;
END;
$function$;

postgres=> SET ROLE TO eshop_app;
SET
postgres=> SELECT * FROM eshop_users;
ERROR:  permission denied for relation eshop_users
postgres=> SELECT new_account('pavel','mojeheslo');
 new_account 
-------------
 
(1 row)

postgres=> SELECT new_account('pavel','mojeheslo');
ERROR:  cannot create account "pavel"
DETAIL:  User already exists

postgres=> SELECT verify_password('pavel','mojeheslo');
 verify_password 
-----------------
 t
(1 row)

postgres=> SELECT verify_password('pavel','mojehesloa');
 verify_password 
-----------------
 f
(1 row)

Na co si dát pozor

Bezpečné techniky zabezpečení přístupu k datům pomocí pohledů