trešdiena, 2012. gada 21. marts

SQL Server parametrs: "cross db ownership chaining"

Rakstā par SQL Server konfigurācijas parametru "cross db ownership chaining" un SQL Server datu bāzes parametru "DB_CHAINING". Par to, kādos apstākļos tas ir bīstams un kur slēpjas bīstamība.

Kāds ir risks?
Risks ir tāds, ka kāds dzīvojas pa svešu datu bāzi kā pa savējo- lasa/dzēš datus, sauc procedūras utt.
Labā ziņa ir tāda, ka šis parametrs pēc noklusējuma ir izslēgts.

Vai ir jāsatraucas?
Lai pārbaudītu potenciālo draudu drošībai, jāizpilda vaicājums:
exec sp_configure 'cross db ownership chaining'
Ja kolonnā "run_value" vērtība ir "0", var gulēt (gandrīz) mierīgi, bet ja vērtība ir "1",  tad rodas papildus jautājumi:
  • Vai visas datu bāzes uz SQL Server instances ir viena izstrādātāja ziņā?
  • Ja kādam ir tiesības veidot objektu jebkurā no datu bāzēm, viņam automātiski uztici tiesības arī uz pārējām datu bāzēm (tagad un gaišajā nākotnē)?
  • Vai ir iespējams, ka kāda no datu bāzēm uz šīs SQL Server instance nākotnē būs cita izstrādātāja ziņā?
Ja uz visiem jautājumiem atbildēji apstiprinoši, tad viss ir kārtībā, lai arī sirdsapziņa ir nedaudz aptraipīta. Tomēr, ja uz kaut vienu jautājumu atbildēji "Nē", tad ir salīdzinoši augsts risks, ka dati nav tik droši, kā vēlētos.

Lai arī raksts ir vairāk par servera parametru, der pārbaudīt arī vai šis parametrs nav uzstādīts datu bāzes līmenī. Ja ir- tad datu bāzes, kurās ir uzstādīts attiecīgais parametrs ir savstarpēji pakļautas šim pašam draudam. Lai tās atrastu:
select is_db_chaining_on, name
From sys.databases
where is_db_chaining_on = 1 and database_id > 6
Draudu būtība (Uhh, kāds virsraksts).
Ja ieslēgts parametrs "cross db ownership chaining", tad lietotāja tiesības NETIEK pārbaudītas otrā datu bāzē, ja lietotājs izpilda vaicājumu uz objektu (piem., skatu), kas izmanto tās pašas shēmas nosaukuma objektus citās datu bāzēs. Šī daļa ir "fīča".

Agrāk šis bij visai sakarīgs variants, kā nodrošināt piekļuvi citām datu bāzēm vienlaicīgi nenodrošinot tiešu pieeju citas datu bāzes objektiem. Tomēr tagad (sākot ar SQL 2005) ir pieejamas labākas alternatīvas (Datu drošība divu datu bāzu gadījumā 3. un sevišķi 4. variants).

Drauds ir tas, ka ja ir Kāds ar tiesībām veidot objektus vienā datu bāzē- db1, un šis Kāds ir "parasts" lietotājs citā datu bāzē db2 (piemēram, ir atļauta "Guest" lietotāja loma db2), tad šis Kāds var piekļūt jebkuram objektam db2.

Piemēram, zinot, ka db2 ir tabula "SomeShema.SomeTable", Kāds savā datu bāzē db1 izveido shēmu "SomeShema" un skatu "SomeShema.SomeView", kas atlasa datus no "db2.SomeShema.SomeTable" un urei- Kāds dara ar datiem no svešas datu bāzes ko vēlas.

Draudu mazināšana
Ir vairākas iespējas, kā samazināt šos draudus.
1. Atslēgt šo servera parametru un pieslēgt to tikai tām datu bāzēm, kam tas nepieciešams (par sp_dbooption un DB_CHAINING):
exec  sp_configure 'cross db ownership chaining', 0;
reconfigure;
Exec sp_dboption 'db1', 'DB_CHAINING', 'ON';
Exec sp_dboption 'db2', 'DB_CHAINING', 'ON';
2. Mainīt veidu, kā lietotājs piekļūst citām datu bāzēm- emuārā aprakstīti iespējamie varianti: Datu drošība divu datu bāzu gadījumā.

Piemērs
Skripts sastāv no trijām daļām un tam, kas to izpilda, jābūt ar sysadmin tiesībām.
Katrai daļai ir paskaidrojums. 2. daļā var vairāk papētīt kodu un laist pa solim, nevis visu uzreiz.
 /*
    1. DAĻA: Sakārtojam vidi testiem
*/
Create Database db1;
Create Database db2;
Create Login dbTestUser with password = 'sliktaparole';
Go
-- db1 datu bāzē ir lietoatājs, kam tiesības veidot objektus,
-- bet kuram nebūtu jābūt nekādām tiesībām uz db2 datu bāzi
use db1;
create user dbTestUser from login dbTestUser;
exec sp_addrolemember 'db_owner', 'dbTestUser';
Go
-- db2 datu bāzē būs tabula ar datiem, kurai mums nav tiesības piekļūt
use db2;
Create Table dbo.db2_TestTable
(
    col1 nvarchar(50)
);
Insert Into dbo.db2_TestTable Values('dati no db2');
-- lietotājam dbTest1 jābūt tiesībām piekļūt db2 (jebkādām).
-- tās var būt caur "Guest" lietotāju, vai arī ja lietotājs ir
-- pielikts datu bāzei lai varētu piekļūt kaut visniecīgākajai lietai.
-- Ilustsrācijai- db2 es atļaušu "Guest" lietotāju:
Grant Connect To Guest;
Go
-- UZMANĪBU: šo pēc testa atliec kā bija..
exec sp_configure 'cross db ownership chaining',  1;
reconfigure;

/*
    2. DAĻA: Eksperimentējam
   
    Normālā situācijā mēs pieņemam, ka dbTestUser neredzēs nekādus datus no db2_TestTable.
    Tomēr, ir izpildījušies divas lietas: ir uzstādīts slitais parametrs
    un dbTestUser ir piekļuve db2.   
   
    Turpinājumā ļaunais dbTestUser piekļūs tam, kam nedrīkst!   
*/
use db1;
Execute as Login = 'dbTestUser'
Select SUSER_SNAME()
-- pa tiešo tiesību nebūs. Nākamā rinda izmetīs kļūdu
Select * From db2.dbo.db2_TestTable
Go
-- mēģinām piemānīt visus un piekļūt datiem savādāk:
Create Proc dbo.db2_DoesNotChechRights
As
    Select * From db2.dbo.db2_TestTable
Go
-- ŠIS IR DRAUDS:
Exec dbo.db2_DoesNotChechRights
revert

/*
    3. DAĻA: Satīram visu!
*/
Use master;
drop database db1;
drop database db2;
drop login dbTestUser;
-- UZMANĪBU: pieņemu, ka pirms testa parametra vērtība bija 0
exec  sp_configure 'cross db ownership chaining', 0
reconfigure

Nav komentāru:

Ierakstīt komentāru