top of page

Always Encrypted - SQL Server 2016 - II

  • Jukka Katajisto
  • Oct 23, 2016
  • 4 min read

SQL Serverin uusi Always Encrypted ominaisuus tarjoaa sovelluskehittäjälle helpon tavan salata haluttu tieto, niin tiedonsiirron kuin tallennuksen osalta. Käyttö on käytännössä näkymätöntä sovelluslogiikalle, mutta sen toiminnasta kannattaa tietää jotain ennen päälle kytkemistä.

Tässä blogi-kirjoituksessa käsittelen ominaisuuden käyttöä sovelluksen näkökulmasta. Jos lyhyt yleiskuvaus kiinnostaa aiheesta lue se edellisestä kirjoituksestani.

Lyhyesti

Ominaisuuden käyttöönotto sovelluksessa on periaatteessa hyvin yksinkertaista. Tarvitaan vain sertifikaatti, johon on pääsy sovelluksesta sekä taulu, jossa se on kytketty päälle. Sovelluksen käyttämään connectionstring informaatioon lisätään Column Encryption Setting=enabled;. Data provider huolehtii tämän jälkeen kaikkien salattavien sarakkeiden automaattisesta salauksesta sovelluspäässä ennen kuin data lähetetään SQL Serverille. Tämä suojaa salattavan datan tehokkaasti sekä tiedonsiirron, että tallennuksen osalta. Kaikki tämä tapahtuu ohjelmoijalle näkymättömästi, joten näin voidaan parantaa tietoturvaa hyvällä tuottavuudella.

Tällä hetkellä ominaisuutta tukevat data providerit:

  • .NET 4.6+

  • Microsoft JDBC Driver 6.0 (tai uudempi)

  • ODBC Driver 13.1 for SQL Server

Käyttö vaatii, että kaikki salattaviin sarakkeisiin liittyvät SQL-kyselyt ovat parametrisoituja tai, että käytetään stored procedureja. Asia on sinänsä vain hyvä, koska SQL-injektion hyökkäys roikkuu vuodesta toiseen OWASP top-10 listalla. Jos sovellus yrittää lähettää SQL-kyselyn sisällä salattavan arvon, nostaa järjestelmä virheen 'Operand type clash:..'.

Salauksen käyttö ei lisää SQL Serverin kuormaa muutoin kuin kasvaneena data määränä, koska kaikki datan salaamiseen ja purkamiseen liittyvät toiminnot tehdään sovelluksessa. Tämä taas kuormittaa sovelluspalvelinta tai työasemaa enemmän, joten suorituskykyä pitää testata ennen tuotantokäyttöä.

Tuetut tietotyypit

Ominaisuus ei tue kaikkia SQL Serverin tietotyyppejä. Jos sovelluksessa halutaan salata ei tuettuja tietotyyppejä, täytyy siihen rakentamaa oma ratkaisu. Oheisen linkin takaa löytyy lista tietotyypeistä, joita ei tueta. Näitä ovat: xml, timestamp/rowversion, image, ntext, text, sql_variant, hierarchyid, geography, geometry, alias, user defined-types, FILESTREAM sarakkeet jne.. Getting Started with Always Encrypted

Sovelluksen optimointi

Jos palautetaan mieleen mistä provider tietää tarvitaanko SQL-kyselyn mukana välitettäviä parametreja salata, niin se tapahtuu lähettämällä 'piilossa' yksi ylimääräinen SQL-kysely 'sys.sp_describe_parameter_encryption', joka palauttaa tuloksessa listan salattavista sarakkeista. Jos sovellus pääsääntöisesti käsittelee ei salattavaa dataa, on tämä turha ja raskas prosessi. Tällöin ominaisuutta ei kannata kytkeä päälle kaikkialle käyttämällä 'Column Encryption Setting=enabled' tietoa connectionstringissä, vaan kysely kohtaisesti.

Kyselykohtaisesti toimintaa voidaan kontrolloida välittämällä SqlCommandin konstruktorille parametri SqlCommandColumnEncryptionSetting.

Parametrin mahdolliset arvot ovat:

  • Disabled Poistaa ominaisuuden käytöstä kyselylle.

  • Enabled Kytkee ominaisuuden päälle kyselylle.

  • ResultSetOnly Tulos käsitellään, mutta ei kyselyn parametrejä.

  • UseConnectionSetting Käyttää yhteyden oletusasetuksia, jotka määritelty connectionstringissä.

.NET 4.6.2+ versiosta lähtien ominaisuus tukee kysely kohtaisesti metatietojen säilyttämistä välimuistissa, jolloin salauksen tarvitsemat metatiedot haetaan vain kerran palvelimelta. Tämä parantaa suorituskykyä huomattavasti varsinkin OLTP-tyyppisissä sovelluksissa. Oletuksena tiedot säilytetään välimuistissa 2 tuntia, mutta aikaa voidaan kontrolloida SqlConnectionin ColumnEncryptionKeyCacheTtl-attribuutilla. Lisäksi tallennus välimuistiin voidaan kytkeä pois päältä SqlConnectionin ColumnEncryptionQueryMetadataCacheEnabled-attribuutilla.

Tilan tarve

Sovelluksen suorituskyvyn kannalta on myös hyvä tiedostaa kasvanut tilantarve. Asia vaikuttaa niin tiedonsiirtoon kuin SQL Serverin käyttämään muistin määrään sekä data-, loki- ja backup-tiedostoihin. Koska kyseessä on vahva salaus vie salattu tieto vähintään 65 tavua tilaa per sarake. Käytetyn tilan voi laskea kaavalla: 1 + 32 + 16 + (FLOOR(DATALENGTH(cell_data)/16) + 1) * 16

Kaavasta nähdään, että esim. jokainen 4 tavun int arvo vie salattuna 65 tavua. Hyvin suurilla tietomäärillä tämä kannattaa huomioida ja miettiä mitä kannattaa salata.

Lisäksi koska kyseessä on salattu tieto, se ei pakkaannu hyvin. Tämä kannattaa huomioida, jos SQL Serverin tauluja on optimoitu käyttämällä rivi tai sivu pakkausta liittyen salattaviin sarakkeisiin. Jos vastaan tulee hyvin pakkautuvaa salattua sisältöä, niin kannattaa asiaa hiukan tutkia. Esim. Electronic Codebook (ECB) moodin käyttö generoi riskialttiin lopputuloksen suurempia aineistoja salattaessa.

SQL Server murrettu

Sovellus luottaa tiedon salauksen suhteen SQL Serverin välittämiin metatietoihin. Miten voidaan varmistaa, ettei sovellukselta voi kalastella salattavaa tietoa?

Käytännössä tämä tarkoittaa siis sitä, kun joku on saanut haltuun riittävät oikeudet sovelluksen tietokantaan, voi vihamielinen käyttäjä muuttaa taulun tietoja siten ettei sarakkeita tarvitse salata. Kun sovelluksessa ei ole mitään salauslogiikkaa ja data provider hoitaa salauksen taustalla, lähettää se sarakkeiden tiedot selväkielisenä SQL Serverille.

Sovelluskoodissa voidaan varmistaa, että salattavat sarakkeet lähetetään aina salattuina määrittelemällä parametrille ForceColumnEncryption = true;.

Jos salaus on kytketty pois päältä SQL Serveriltä, niin järjestelmä nostaa virheen tiedon lähettämisen sijaan:

Toinen mahdollinen hyökkäys tapa on ensin asentaa valesertifikaatti ja sen jälkeen muuttaa taulun salausmetatiedot käyttämään tätä hyökkääjän asentamaa sertifikaattia, jolloin sovellus salaisi datan tavalla jonka hyökkääjä voisi purkaa. Tämä voidaan estää listaamalla sovelluksella sallitut salaussertifikaatit ja näiden sijainti.

Jos nyt sovelluksessa määritelty sertifikaatti (polku + thumbprint) ei vastaa palvelimen palauttamia nostetaan virhe.

Entity Framework

Entity frameworkin tuotanto käytöstä Always Encryptedin kanssa ei ole vielä oma kohtaista kokemusta, mutta joitain ongelmakohtia ja niiden ratkaisuja on käsitelty CTP version kanssa seuraavassa blogi-kirjoituksessa: Using Always Encrypted with Entity Framework 6

Huomioitavaa on se, että salattavien attribuuttien pituudet pitää määritellä mallissa ja mallin tietotyyppi täytyy olla salaamaton muoto esim. nvarchar. Taulun luonti scripteihin täytyy sitten lisätä ALTER TABLE käskyllä sarakkeet ja niille SQL Serverin käyttämät salaukseen liittyvät metatiedot.

Salasanat

Itse en suosittelisi missään nimessä käyttämään ominaisuutta salasanojen suojaamiseen sen houkuttelevasta helppoudesta huolimatta, vaan ne täytyy edelleen salata niin ettei niitä pysty muuntamaan selkokielisiksi mitenkään. Tämä tapahtuu vahvalla hash-algoritmilla. Hyvä tapa on vielä suolata salasana ennen sotkemista, jolloin jokainen tietokantaan tallennettu salasana on eri riippumatta siitä onko käyttäjät käyttäneet samaa salasanaa. Lisäksi suolaus pitää tehdä oikein ja tarpeeksi pitkällä käyttäjäkohtaisella sotkulla, joka on myös hyvä tallentaa tietokantaan.

Hyvä artikkeli salasanojen suojauksesta löytyy:

Blogin seuraavassa osassa käsittelen vielä lyhyesti salausavaimien generointia ja elinkaarta.

Comments


Featured Posts
Recent Posts
Archive
Search By Tags
Follow Us
  • Facebook Basic Square
  • Twitter Basic Square
  • Google+ Basic Square
bottom of page