Skoncujte s anonymitou koncových uživatelů (2/2) - Proxy Authentication

Znalost identity koncového uživatele ve všech vrstvách systému je základní nutností při tvorbě bezpečných aplikací. Dnes si ukážeme jak Proxy Authentication umožňuje využít všechny bezpečnostní mechanismy Oracle i v případě, že aplikace sdílí stejné spojení postupně pro více koncových uživatelů, jak je obvyklé v dnešních webových aplikacích.
V minulém dílu jsme si ukázali, jaké problémy přináší dnes tak obvyklá anonymita koncových uživatelů při práci s databází - tedy stav, kdy se aplikace připojuje stále pod stejným uživatelským jménem a toto spojení střídavě používá pro obsloužení různých koncových uživatelů. Ukázali jsme si také první možné řešení tohoto problému - Client Identifier. Zatím co u Client Identifier bylo snahou vytvořit mechanismus umožňující předávat identitu koncového uživatele s minimální režií i za cenu že stále nelze využít všechny běžné mechanismy řízení přístupu na úrovni koncových uživatelů, v případě Proxy Authentication je naopak primární snahou nabídnout mechanismus, který bude umožňovat využít všechny bezpečnostní mechanismy Oracle i v prostředí sdílených spojení.

Nejprve si ukážeme použití Proxy Authentication v kódu aplikace - a použijeme stejný příklad jako v minulém díle. Opět jde o poměrně malou změnu v kódu aplikace - tři řádky před použitím spojení a jeden na konci.


void sqlWithProxyAuth (OracleDataSource ds, String endUserName) throws SQLException {
Connection conn=ds.getConnection();
 
java.util.Properties prop = new java.util.Properties();
prop.put(OracleConnection.PROXY_USER_NAME, endUserName);
((OracleConnection)conn).openProxySession(
OracleConnection.PROXYTYPE_USER_NAME, prop);
 
Statement stmt=conn.createStatement();
stmt.execute("DELETE FROM hr.employees WHERE employee_id=120");
ResultSet rs = stmt.executeQuery("SELECT count(*) FROM hr.employees");
rs.next();
System.out.println("Počet záznamů:" + rs.getLong(1));
rs.close();
stmt.close();
 
((OracleConnection)conn).close(OracleConnection.PROXY_SESSION);
 
conn.close();
}

Oproti Client Identifier ale naše práce ještě nekončí. Vedle technického účtu, přes který se aplikace připojuje do databáze, totiž musíme při použití Proxy Authentication vytvořit v databázi i účty pro jednotlivé koncové uživatele a povolit jim připojování přes technický účet. Databáze tuto informaci použije:


  • ke kontrole zda zadaný koncový uživatel opravdu v databázi existuje
  • volitelně i k autentizaci koncového uživatele jeho heslem či jinými prostředky
  • použití rolí (a tedy i práv) koncového uživatele pro dané spojení

Přihlašte se do databáze jako uživatel s právy DBA (např. system) a proveďte postupně tyto operace:


  1. Nejprve vytvořte role, na kterých budeme demonstrovat fungování přístupových práv.

    CREATE ROLE employees_viewer;
    CREATE ROLE jobs_viewer;
    CREATE ROLE test_role;
    GRANT select ON hr.employees TO employees_viewer;
    GRANT select ON hr.jobs TO jobs_viewer;
    GRANT select ON hr.departments TO test_role;

  2. Vytvořte technický účet, přes který se bude připojovat aplikace - účet APPSERV.

    CREATE USER appserv IDENTIFIED BY appserv_heslo;
    GRANT connect,test_role TO appserv;

  3. Nyní vytvořte obvyklým způsobem koncového uživatele a přidělte mu role.

    CREATE USER david IDENTIFIED BY davidovoheslo;
    GRANT connect, employees_viewer, jobs_viewer TO david;

  4. Nakonec povolte uživateli DAVID, aby se připojoval skrze aplikaci využívající technický účet APPSERV. Specifikujeme, že takto vytvořené spojení pak bude moci využívat všechna práva uživatele DAVID, s vyjímkou role JOBS_VIEWER.

    ALTER USER david
    GRANT CONNECT THROUGH appserv
    WITH ROLES ALL EXCEPT jobs_viewer;

Nyní již máme vše připravené a je na čase zjistit, jak se Proxy Authentication chová. Pro zkoušení níže uvedených ukázek můžete využít:


  1. SQL*Plus ve verzi 11g, které dovoluje v klauzuli connect uvést současně koncového i technického uživatele. Proxy spojení tedy vytvoříte takto:

    sqlplus appserv[david]/appserv_heslo

  2. Oracle SQL Developer 1.5 a novější - v dialogu pro vytvoření zadejte jméno a heslo techického účtu (v našem případě APPSERV). Pak zaškrtněte políčko Proxy Connection a do zobrazeného dialogu zadejte jméno koncového uživatele (v našem případě DAVID). Protože nevyžadujeme ověření koncového uživatele heslem, nevyplňujte jej.
  3. Použijte Java kód uvedený v první ukázce a upravte jej tak, aby spouštěl níže uvedené dotazy.

V první řadě zjistěte role, jejichž práva má aktuálním spojení k dispozici:


SELECT * FROM session_roles;

ROLE
CONNECT
EMPLOYEES_VIEWER

Všimněte si, že ve výpisu chybí role JOBS_VIEWER, kterou jsme proxy spojením zakázali klauzulí ALL ROLES EXCEPT. Chybí zde ale i role TEST_ROLE, která byla nagrantována technickému uživateli a ne koncovému uživateli.

Z výpisu je vidět, že při použití proxy autentizace má spojení k dispozici práva rolí grantovaných koncovému uživateli DAVID, nikoliv role grantované technickému účtu APPSERV. Aplikace tak bude mít v databázi různá práva podle toho, kdo s ní bude zrovna pracovat.

Výše uvedené tvrzení si můžeme ještě zkontrolovat tím, že se pokusíme postupně provést SELECT nad tabulkami HR.EMPLOYEES (přístupná roli EMPLOYEES_VIEWER), HR.JOBS (přístup roli PRODUCT_VIEWER) a HR.DEPARTMENTS (přístupná roli TEST_ROLE). Pouze dotaz do HR.EMPLOYEES bude úspěšný, ostatní skončí chybou „ORA-00942: table or view does not exist".
Je také zajímavé ukázat si, jak se proxy spojení projeví na hodnotách vracených různými funkcemi pro získání jména aktuálního uživatele. Pro srovnání uvádím výstup dotazu jak při použití Proxy Authentication, tak i výstup při použití Client Identifier a běžného privátního spojení vytvořeného uživatelem David:


SELECT user,
sys_context('USERENV','SESSION_USER') session_user,
sys_context('USERENV','PROXY_USER') proxy_user,
sys_context('USERENV','CURRENT_USER') current_user,
sys_context('USERENV','CLIENT_IDENTIFIER') client_identifier
FROM dual;


Metodausersession userproxy usercurrent userclient identifier
Proxy Authenticationdaviddavidappservdavid
Client Identifierappservappserv appservdavid
Privátní spojenídaviddavid david

Vidíte, že spojení využívající Proxy Authentication se opravdu i z hlediska různých vlastností spojení chová spíše jako by každý uživatel vytvářel své privátní spojení.
Dále se stejně jako v předchozím dílu podívejte do auditního logu - otevřete si druhé spojení, ve kterém se do databáze přihlašte jako uživatel s právy DBA:


SELECT timestamp, sessionid, os_username,
username, action_name,
client_id, proxy_sessionid
FROM dba_audit_trail
WHERE timestamp>sysdate-1
ORDER BY timestamp desc;

timestampSession idos usernameuser nameaction nameclient_idproxy sessionid
17:50690270AppdavidLOGON(null)690269
17:50690269AppappservLOGON(null)(null)

Vidíte, že přihlášení zde vygenerovalo dva záznamy - spodní se týká přihlášení technického uživatele a horní přihlášení koncového uživatele. Pole PROXY_SESSIONID u záznamu koncového uživatele přitom odkazuje na SESSIONID druhého záznamu.
Na první pohled se tedy zdá, že spojení využívající Proxy Authentication se chová prakticky shodně jako privátní spojení vytvořené přímo koncovým uživatelem - tedy režim, na který jsme zvyklí z client/server aplikací. Rozdíl je však ve výkonu. Nedochází totiž k opakovanému vytváření spojení mezi databázovým klientem a serverem, ani ke startování server procesu. Provedl jsem jednoduché srovnání různých možností přihlašování.
U každé metody jsem simuloval postup, kdy se postupně 1.000x spustí dávka sestávající ze tří jednoduchých SQL dotazů a jednoho UPDATE nad tabulkou HR.EMPLOYEES. Tuto dávku spouští pokaždé jiný z 5 koncových uživatelů. V případě privátního spojení bylo spojení navázáno pokaždé před spuštěním dávky a bylo ukončeno hned po jejím dokončení. V ostatních případech bylo všemi spuštěními sdíleno stejné databázové spojení, pouze se příslušným způsobem nastavovala identita aktuálního koncového uživatele.


MetodaČas
Sdílené spojení s anonymním uživatelem18.0 s
Sdílené spojení s Client Identifier18.6 s
Sdílené spojení s Proxy Authentication26.9 s
Privátní spojení na jedno použití187.5 s

Je zřejmé, že výsledek testu je hodně závislý na úloze, kterou budou spojení provádět. Čím náročnější dotazy bude aplikace v databázi provádět, tím zanedbatelnější bude vliv způsobu připojení na výkon aplikace.
Test ukazuje, že i když použití Proxy Authentication s sebou nese jistou režii, je pořád významně efektivnější, než opakované vytváření privátního spojení. Na druhou stranu Proxy Authentication dovoluje jako jediné u sdíleného spojení plně využít všech bezpečnostních mechanismů databáze. Můžeme tak efektivněji zabránit případným bezpečnostním útokům či alespoň minimalizovat jejich dopad. Důsledné řízení přístupu k datům na úrovni databáze může zabránit úniku dat či jejich pozměnění i v případech, kdy se vám do aplikace vloudí nějaká ta bezpečnostní díra, jako je třeba formulář náchylný k SQL Injection. Pomůže ale i v situacích, kdy se útočníkovi podaří obejít aplikaci úplně.

Comments:

Dobry den. Diky za vybornou serii clanku. Dotaz: Lze Proxy Authentication zkouset s XE edici Oracle DB? JDBC pripojeni k db s username ve stylu: appserv[david] funguje. Avsak pri vytvareni proxy session z kodu volanim OracleConnection.openProxySession(OracleConnection.PROXYTYPE_USER_NAME, prop) server vraci chybu: java.sql.SQLException: ORA-00439: feature not enabled: Enterprise User Security Jde v pripade "pouheho" pripojeni pres jdbc o neco jineho nez Proxy Authentication. Dok za info, JaPe

Posted by JaPe on červen 08, 2010 at 08:12 dop. CEST #

Do puvodního kódu se mi vloudil drobný překlep v řádku: ((OracleConnection)conn).openProxySession(OracleConnection.PROXYTYPE_USER_NAME, prop); Chyběla zde úvodní závorka - už je to v ukázce upraveno.

Posted by David Krch on červen 14, 2010 at 03:26 odp. CEST #

Na dotaz JaPe jsem reagoval mailem. Proxy Authentication lze použít i s XE. JaPe v mezičase sám zjistil, že daná chybová hláška se objevuje, pokud se pokusíte připojit pod neexistujícím uživatelem.

Posted by David Krch on červen 20, 2010 at 02:30 odp. CEST #

Dobry den. Pouzivame Oracle Standard Edition One 11.1.0.0.0 a dostavame presne taky isty problem ORA-00439: feature not enabled: Enterprise User Security. Ano, tato chyba nastava, len ak je zadany neexistujuci uzivatel. Da sa nieco nastavit v Databaze, alebo v samotnom JDBC volani, aby nastala spravna chyba? Podotykam ze chyba nenastava v Enterpise verzii. Takisto nenastava ak sa proxy uzivatel pouzije priamo v SQLPlus. Vopred srdecne dakujem za odpoved. Branislav Kocinec

Posted by Branislav Kocinec on březen 20, 2014 at 05:41 odp. CET #

Dobrý den. Bohužel se mi k vašemu problému nepodařilo získat žádné další informace. Pouze se mi jej podařilo zreprodukovat i na 11gR2 Express Edition. Pokud máte vy, nebo váš zákazník zaplacenou podporu, doporučuji řešit problém zadáním Service Requestu na http://support.oracle.com.

Posted by David Krch on březen 24, 2014 at 04:18 odp. CET #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Česky o všem co se točí kolem Oracle Database.

Autoři:

Patrik Plachý
Technology Sales Consultant

David Krch
Principal Consultant
Oracle Expert Services

Oracle Czech

Search

Archives
« duben 2014
PoÚtStČtSoNe
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    
       
Today