Место Row Level Security в высоконагруженном проекте
Hardcore Edition
Александр Токарев
RuOUG
Agenda
1. Row Level Security
2. RLS approaches
3. Our case
4. Lessons learned
5. Q&A
RLS security myths
RLS
1. Enable row-level access control
2. Simplify application development
3. Centralize security management
Security requirements
We need new security now!
Initial requirements
1. Users should see only own data
One year after development started:
1. GDPR audit
2. SOX audit
3. 5 severe security violations = 20 new rules
Security requirements
1. Minimal application changes
2. Low impact to performance
3. Centralized security management
4. All applications should be affected
5. Implementation should be fast
=
Oracle Virtual Private Database
RLS in DBMS
RLS location
1. Application server
2. Database server
3. Mixture
Application server
1. Modify queries to DB
+ performance, agile
- hand-made
2. Filter fetched data
+ supported by frameworks
- extra app/db server traffic, complicated search, paging, etc
DB server
1. Security views
+ performance
- issues with DML
2. Stored procedures API
+ performance
- out of fashion
3. Embedded row level security
+ full of myths
- full of myths
Mixture
Client 1
Client 2
Client X
Application
server
RLS location
1. Application server
+ high level language
- access via application server only
2. Database server
+ performance, close to data
- too much myths
3. Mixture
+ very scalable
- complicated implementation
DBMS RLS myths
1. Bad performance
2. Complicated implementation
3. Easy to hack
4. No interaction with UI
5. Exists in old database engines only
6. Only for 2-tier applications
Our project architecture
Oracle
main
Oracle
DG
Application
server
Application
server
Load
balancer
Client
browser
10000 RPS
4000 users
InMemory
cluster
Application
server
GCC
Apache
Solr
CRM
20 Reports per second
100 users
60 Reports
per second
300 users
20 Reports per second
100 users
100 RPS
Access types
1. User observes own records only
2. Users observes records shared with him by others user
3. User observes records for given permitted customer list
.
.
.
20. User observes records for given permitted record type list
Security source
Customer
Security DB
Microsoft
Active Directory
Oracle
main
Oracle
DG
Application
server
Application
server
Load
balancer
Client
browser
InMemory
cluster
Application
server
GCC
Apache
Solr
CRM
300 roles per user300 000 permissions
mappings
VPD glossary
• Context – key-value pair storage
• Security object – object controlled by VPD
• Security predicate – SQL string appended to query
• Policy function – PL/SQL populating predicate
• Policy – metadata which glues all together
VPD internals
sql
VPD policy
checker
Security predicate
producer
Query
rewriter
Query plannerData
Context
Policy function
Predicate testing
“Created by username” policy
“Created by username” policy
“Created by username” policy
“Created by username” policy
“Created by username” policy
ACL policy
1. Based on AD groups only
2. AD groups store permission mappings
3. Mostly IN or EXISTS/NOT EXISTS predicates
division_type_code in (‘BRANCH’, ‘DEPO’, ‘ARCH’)
Not exists (
select 1
from restricted_user_measures m
where m.measure_id = customer.measure_id
)
“Created by username” policy 3 Tier
“Created by username” policy 3 Tier
“Created by username” policy 3 Tier
Invoke just after got connection
Application changes
AD user Tableau made login
The same in Java!
DBMS RLS myths
1. Bad performance
2. Complicated implementation
3. Easy to hack
4. No interaction with UI
5. Exists in old database engines only
6. Only for 2-tier applications
Development process failure
1. Developers see no data
2. DBAs see no data
3. Only started applications see data
Development process failure
Development process fix
Development process Prod
Development process Dev
External systems interaction pain
1. Customer security DB – DB links are prohibited
Solution: dedicated ETL job – 5 minute delay
2. Active Directory – no access from Oracle
Solution: pass all user roles to context from Java
Debug Policy fine
– Filter predicate in execution plan
– View v$vpd_policy
Debug failure Policy broken
Debug failure Policy broken
1. No information in execution plan
2. No information in v$vpd_policy
3. Queries fails with
Debug failure Policy broken
DBMS RLS myths
1. Bad performance
2. Complicated implementation
3. Easy to hack
4. No interaction with UI
5. Exists in old database engines only
6. Only for 2-tier applications
Performance degradation
1. Query plans hard parse – 3x more
2. Get connection from pool – 3x more
3. Query execution time – up to 2x more
4. Context switches – up to 2x more
Plan to fix
1. Get connect from pool
2. Securities predicates
3. Hard parse
4. Wild execution plans
5. Cache
6. Denormalization
Get connection pain
1. Java – get AD roles
2. Java – filter security roles
3. Java – send to Oracle as input parameter:
- AD user name
- AD roles list
4. Oracle – VPD predicates magic
80%
0.4 sec
Get connection pain
120-300 AD roles!
Connection pain solution
1. Do not pass AD roles from Java side
2. Connect to AD from Oracle DBMS
3. Use DBMS_LDAP package
0.4 seconds => 0.08 seconds!
Policy evaluation mitigation
sql
VPD policy
checker
Security predicate
producer
Query
rewriter
Query plannerData
Security predicate cache
sql
VPD policy
checker
Security predicate
producer
Query
rewriter
Query plannerData
Predicate
cache
Policy types
1. Dynamic
Predicate is produced each call
2. Static
Predicate produced once
3. Context-sensitive
Predicate produced if security context is changed
Policy types
1. Static
when predicate string is constant
ad_user = sys_context(‘security_ctx’, ‘ad_user’)
2. Context-sensitive
when predicate string is built from context
environment_code in (‘SANDBOX’, ‘PROD’, ‘HOME’)
Taken from context
Static policy
Context-sensitive policy
Hard parse resolution
Hard parse resolution
Hard parse resolution
Hard parse resolution
50% hard parse eliminated!
Bad query plans basic resolution
Bad ACL query plans resolution
Dreams
1. Use InMemory structures – plsql collections
2. Fast
3. No disk I/O
Reality
1. PL/SQL context switches – low performance
2. No options for cardinality estimate – bad plans
3. Very hard to debug
Bad ACL query plans resolution
Bad ACL query plan resolution
1. I/O is tiny
2. Proper plans/statistics via Dynamic Sampling
3. Indexing support
4. Small changes in policies
Bad ACL query plan resolution
300% performance profit!
Fixed ACL pain
DBA complains:
- UNDO size grow
- REDO volume grow
- Overloaded disks
Fixed ACL pain
Fixed ACL pain resolution
Less 30x times!
Fixed ACL pain resolution
DBAs are happy!
VPD and Result Cache
VPD and Result Cache
Call 1
Call 2
VPD and Result Cache
VPD and Result Cache
Call 1
Call 2
VPD and Result Cache
VPD and Result Cache
VPD and Result Cache
VPD and Result Cache
VPD and Result Cache
Nothing changes!
VPD and Result Cache
VPD and Result Cache
Try to not use result cache with VPD!
ACL inlining
2 ACL types:
1. By ID
1000-2000 IDs
2. By types
2-10 types
ACL inlining
2-10 records
ACL inlining
Take from context
ACL inlining issues
Not all values + wrong syntax
Someone cuts predicates!
ACL inlining issues
Policies more 4000 bytes
Still doesn’t work!
ACL inlining issues
Default – 256!
ACL inlining issues
ACL inlining
Pros
1. Extremely fast
2. No extra DB objects
Cons
1. More hard parse
2. Tricky to populate IN clause
50% performance profit!
Cursor invalidation
Cursor invalidation
Cursor invalidation
Known issue!
Our plan – do nothing!
Exactly our optimization approach 
Many rows
Securities right denormalization
ATokarev,VPetrov,MSovina
Securities predicates
LIKE = FULL scan mostly!
Denormalization not very efficient in Oracle!
1. Ingestion degradation up to 10%
2. Additional maintenance
3. Sudden deterioration
Cache
Per-username based caches:
1. VPD calls
2. AD groups values
3. ACL values*
*8 ACLs – no dedicated cache per ACL
InMemory PL/SQL
Caching parameters
N Code Current
value
Purpose
1 VPD_CACHE N Should be invoke vpd.connect if user hasn’t changed
2 ACL_CACHE N Do we need call Active Directory
3 AD_CACHE Y Cache access control list population
4 AD_EXPIRING 300 Lifetime in seconds
5 VPD_EXPIRING 600 Lifetime in seconds
6 ACL_EXPIRING 120 Lifetime in seconds
Was changed ~8 times in Production!
Caching conclusion
1. Agreed with business and Security Team
2. Data-driven:
– On/off
– Expiration time
Final performance metrics
1. Query plans hard parse – 10%
2. Get connection from pool – 5%
3. Query execution time – up to 20%
4. Context switches – eliminated
DBMS RLS myths
1. Bad performance
2. Complicated implementation
3. Easy to hack
4. No interaction with UI
5. Exists in old database engines only
6. Only for 2-tier applications
RLS side channel attacks
1. Security predicates/caches/context sniffing
Identify data by security filters content
2. Fake user name calls
Direct connect to DB via superuser as an application user
3. Hand-crafted queries
Tricky queries based on a particular DB issues
4. Dump analysis
- SGA
- Library cache
- Data files
Security predicate sniffing
Events
1. 10053 – Cost Based Optimizer decisions
2. 10730 – VPD predicates
3. 10060 – All Predicates
4. 43905 – Result Cache
Security predicate sniffing mitigation
1. Close an access to VPD-related views:
- V$VPD_POLICY
- %_POLICIES
- %_POLICY_ATTRIBUTES
- %_POLICY_CONTEXTS
- %_POLICY_GROUPS
2. Close an access to DB trace files
3. Use context – not direct values
4. Use session level temporary tables for cache
Fake user name attack
1. Connect to DB directly
2. Process as though application:
Fake user name mitigation
Fake user name mitigation
Fake user name mitigation
Fake user name mitigation
Fake user name risk
Next day
Login statement is stolen
Fake user name mitigation
Fake user mitigation
Next minute
Login is stolen
Fake user name mitigation
Hand-crafted queries
Hand-crafted queries
Iterative inference attack
Hand-crafted queries
1. result-cache PL/SQL functions
2. others tricks
Hand-crafted queries
VPD column level security hacking 1
VPD column level security hacking 1
VPD column level security hacking 1
VPD column level security hacking 1
NULL
VPD column level security hacking 1
VPD column level security hacking 1
VPD column level security hacking 1
VPD column level security hacking 1
VPD Iterative inference attack
Failed in 12.1!
Works in 11.4!
DBMS RLS myths
1. Bad performance
2. Complicated implementation
3. Easy to hack
4. No interaction with UI
5. Exists in old database engines only
6. Only for 2-tier applications
RLS in Oracle
About 70 policies from default Oracle installation!
RLS in others DB
RLS in Postgres
RLS in Postgress
RLS in Postgres ACL
RLS in Postgres ACL
RLS in Postgres ACL
Very efficient in Postgres!
Overall performance – 15% degradation
DBMS RLS myths
1. Bad performance
2. Complicated implementation
3. Easy to hack
4. No interaction with UI
5. Exists in old database engines only
6. Only for 2-tier applications
DBMS RLS pros
1. Works automagicaly
2. Tiny client code modification
3. Security rules are equal for all clients
4. No options to bypass common security hacks
5. Security management centralization
6. Works on Oracle Standby database
DBMS RLS cons
1. Works automagicaly
2. Sophisticated debug
3. Complicated interaction with external
systems
4. SQL knowledge required
5. Interaction with UI impossible
6. Copy-paste if there are many databases
DBMS RLS myths
1. Bad Unpredictable performance
2. Complicated implementation debug
3. Easy A lot of efforts to hack
4. No interaction with UI
5. Exists in old database engines only
6. Only for 2-tier applications
When use DBMS RLS
1. Fast tech debt resolution
2. Different applications use direct DB connection
3. Newly implemented applications
4. SOX, GDPR, ISO/IEC 27001/27002,
FedRAMP/FISMA, SOC, HIPAA и PCI DSS
compliance requirements
When not to use DBMS RLS
1. Applications uses application server only
2. Sophisticated microservices architecture
3. Very old applications
4. High-loaded OLTP applications
Lessons learned
1. Plan security in advance
2. Use data-driven caching
3. Denormalize data
4. Invent simple policies
5. Care about hackers
6. RLS in DBMS works fine
7. Even in Postgres 
THANK YOU
WE ARE HIRING!
Alexander Tokarev
Database expert
DataArt
atokarev@dataart.com
https://github.com/shtock
RuOUG

Row Level Security in databases advanced edition

Editor's Notes

  • #2 Всем привет. Меня зовут Александр и я занимаюсь в компании DataArt вопросами, связанными с производительностью баз данных и архитектурой приложений.
  • #3 Сегодня мы обсудим такую вещь, как смысл наличия безопасности на уровне строк, подходы к её реализации в целом и как решали мы данную задачу в одном из наших проектов. Я попытаюсь рассказать какие уроки из всего этого мы вынесли и с удовольствием отвечу на ваши вопросы. На самом деле это всё детали.
  • #4 Безопасность на уровне строк, да ровно как и все задачи, связанные с безопасностью, окутаны плеядой разнообразных мифов и именно их разрушению или подтверждению будет посвящён наш разговор. Ну и конечно же я надеюсь вы узнаете всех мифических персонажей, которые нам попадутся.
  • #5 Перед тем, как мы начнём рассматривать мифы давайте очень кратко вспомним, зачем же нужна безопасность на уровне строк и где её реализуют. В целом всё очевидно из названия. Rls нужна, чтобы фильтровать данные по строкам на основе идентификатора пользователя, его ролей или контекста выполнения Её наличие упрощает разработку приложения За счёт централизации логики безопасности Вопрос в зал у кого политики сложнее, чем показывать клиенту только свои данные
  • #6 Но самое страшное, что все требования к безопасности появились через год после начала разработки Объяснить какие – это важный момент по замечаниям Gdpr + sox
  • #7 Так как времени на реализацию Security было мало был, а список пожеланий был весьма большой и противоречивый, а ещё и разработчики среднего слоя настойчиво не хотели менять DAO, то единственным выходом была концентрация логики Security в базе данных через встроенную row level security, так как использование security view привело бы к изменению DAO.
  • #8 Фильтрация строк очевидно может быть реализована на Сервере приложений Сервере баз данных И всегда остаётся место для смешанных вариантов
  • #9 Собственно тут 2 основных подхода: Все запросы к серверу БД на уровне DAO содержат в себе все необходимые предикаты безопасности и Применение фильтрации к уже загруженным данным Достоинства и недостатки обоих методов весьма очевидны. Когда вручную создаются запросы очевидно их скорость весьма высока, можно делать что угодно, но ручное их написание может привести к ошибкам. Самые частые – в каком-то из классов DAO предикаты забываются. Я имею ввиду антотации Filter и where в Hibernate Для фильтрации тоже все понятно. Оно уже реализовано весьма богато во многих фреймворках, таких как Spring Security или Jango guardian, но приводит к росту трафика между серверами, усложняет и замедляет задачи поиска, пейджинга и прочего Тут идёт разговор о PredFilter и PostFilter в Spring Security или о Spring ACL
  • #10 Существует множество вариантов реализации безопасности на стороне сервера баз данных. Самый простой и очевидный это в представлениях, куда мы помещаем все наши security предикаты. Далее мы можем создать api из хранимых процедур И, наконец, использовать встроенные в базу данных средства row level security Опять таки, + и – ясны. Представления очень быстрые и гибкие, но становится тяжелее делать DAO, ибо прямые операции вставки и изменения данных уже не проходят или надо делать instead of триггеры, что совсем уж грустно Хранимые процедуры быстры, но уже не модны Что касается встроенной безопасности на уровне базы данных то тут полный простор для мифов как в части плюсов, так и в части минусов
  • #11 Тут можно придумывать множество комбинаций, но самым распространённым является шардирование по клиентам, но само собой бывают более сложные политики, чем разделение доступа по одному клиенту.
  • #12 Исходя из плюсов и минусов каждого варианта вытекают плюсы и минусы каждого решения
  • #13 Вопрос к аудитории про сложность security
  • #14 Лучше всего рассматривать мифы на примере конкретной архитектуры. Собственно рассмотрим архитектуру нашего приложения. Как вы видите типичная архитектура трёхзвенного enterprise-приложения за исключением того, что ряд серверов в AWS. Ключевая печаль в том, что по ряду причин CRM система, системы получения отчётности и система виртуализации данных ходят прямыми запросами в базу данных и поменять это невозможно, а требования безопасности должны быть едины для всех. Важно заметить, что хранимая логика в базе данных запрещена.
  • #15 Рассмотрим какие у нас есть вариации для row level security Всё начинается с простейшего Пользователь видит только свои записи, и то там не всё так просто, но я не могу раскрывать детали. Также другие пользователи могут шарить записи с другими пользователями, для некоторых типов объектов определён список пользователей, с которыми они могут работать, а для некоторых пользователей определены только определённые типы объектов. Сейчас в системе около 20-ти типов правил row level security.
  • #16 Всё бы было ничего, но проблема в том, что ещё и не вся информация для формирования предикатов безопасности лежит у нас в системе. Так, например, информация по разрешённым покупателям находится в отдельной БД, а маппинги между покупателями и нашими пользователями присваиваются через набор групп в Active Directory. Причём, что важно одна запись из ActiveDirectory может соответствовать набору записей из БД покупателей.
  • #17 Вопрос к аудитории про сложность security Нарисовать 3 этапа Определение что секурити Формирование предиката реврайт
  • #18 Чтобы объяснить как это работает проще показать, я расскажу какие политики у нас есть в проекте и попытаемся создать одну из них
  • #19 Итак, давайте создадим простейшую политику, практически аналогичную используемой у нас
  • #20 Юзер бд – тут создаём предикат
  • #21 Юзер бд – тут создаём предикат
  • #22 Юзер бд – тут создаём политику
  • #23 Тут простой селект и показ во что он превратился. Сам для себя глянуть в v$sqlplan + вьюху + залогиниться под другим юзером и др кол-во Обратить внимание, что всё пусто
  • #24 Тут простой селект и показ во что он превратился. Сам для себя глянуть в v$sqlplan + вьюху + залогиниться под другим юзером и др кол-во
  • #25 Тут простой селект и показ во что он превратился. Сам для себя глянуть в v$sqlplan + вьюху + залогиниться под другим юзером и др кол-во
  • #26 Тут простой селект и показ во что он превратился. Сам для себя глянуть в v$sqlplan + вьюху + залогиниться под другим юзером и др кол-во
  • #27 Мы не будем рассматривать сами функции, но если кратко, то ACL политики это политики по access control list, который формируется либо из набора групп AD либо на основе маппингов AD групп и других систем. Собственно IN или EXISTS выбираются на основе объёма списка для ограничений данных. Малый – IN. Большой – exists.
  • #28 Ключевая боль, что тут пользователь БД, а все приложения ходят под connection pool. Что же делать? В контексте USERENV есть один атрибут, который создан специально для таких целей и может быть единственный изменён извне. Т.е. мы берём session_user и заменяем его на
  • #29 Ключевая боль, что тут пользователь БД, а все приложения ходят под connection pool. Что же делать? В контексте USERENV есть один атрибут, который создан специально для таких целей и может быть единственный изменён извне. Т.е. мы берём session_user и заменяем его на
  • #30 Таким образом, каждое приложение при получении соединения из connection pool вызывает простую команду указывая имя именно application user, а не пользователя базы данных. Таким образом проблема 3-х звенных приложений прекрасно решается. Собственно у нас имя AD пользователя проходит через соответствующие http header, проваливается на jboss и на каждом получении коннекта мы вызываем установку идентификатора.
  • #31 Таким образом, каждое приложение при получении соединения из connection pool вызывает простую команду указывая имя именно application user, а не пользователя базы данных. Таким образом проблема 3-х звенных приложений прекрасно решается. Собственно у нас имя AD пользователя проходит через соответствующие http header, проваливается на jboss и на каждом получении коннекта мы вызываем установку идентификатора.
  • #32 Вопрос к аудитории про сложность security
  • #33 После того, как всё это завели начались проблемы Девелоперы не видят данные, dba не видят данные (это же не постгресс, где есть роль суперюзер, в которой обходятся все security вещи), только из приложения что-то видно. В общем, наступила полная медитация.
  • #34 Как мы помним нашу старую policy function в ней мы данные помещаем под защиту всегда
  • #35 По новому концепту мы внедряем на уровне continuous integration переменную, которая при деплое резолвится нужным образом
  • #36 Либо в 1 = 1 для продакшна и все данные под защитой всегда, т.е. если контекст не взведён, то данных и не увидят
  • #37 Либо для дева проверяется, установлен ли контекст и фильтруются, только если он есть, т.е. запущено приложение
  • #38 Как я уже сказал, одна из проблем, что данные для безопасности лежат в других системах. Часть в сторонней бд, в которую нельзя ходить напрямую, а часть в active directory. Соответственно для внешней бд etl разработчики сделали соответствующую процедуру загрузки, а для AD решили передавать список ролей из джавы прямо в контекст.
  • #39 Отлаживать можно через план выполнения, view со списком предикатов, но есть одна проблема. Это работает только тогда, когда в политике нет ошибок.
  • #40 Если мы внесём какую-либо опечатку в политику, то
  • #41 Мы не получим ни плана выполнения, ни информации во вью, а все запросы начнут отваливаться с ошибками
  • #42 как мы обнаружили, единственный выход это найти соответствующий трейс-файл, который оказывается в случае таких ошибок создаётся автоматически и разбираться в нём
  • #43 Вопрос к аудитории про сложность security
  • #44 Как и следовало ожидать, когда делаешь всё по мануалу, отваливается производительность Увеличилось количество генерации планов, время получения коннекта из пула, да и сами запросы изрядно просели по скорости
  • #45 Мы определили план действий по решению проблем
  • #46 Как устроено получение коннекта из пула Вначале ява получает список ролей, потом фильтрует и отправляет в оракл имя ad пользователя и список ролей. Далее работают уже знакомые нам процедуры по инициализации контекста. Обнаружилось, что 80% уходило именно на передачу параметра
  • #47 А так как у пользователя под 300 AD ролей в целом это походило на правду
  • #48 В итоге было принято внезапное, но работающее решение – получать AD роли прямо в базе данных и это помогло нам в 4 раза сократить время
  • #49  Вы помните как работает row level security? Так вот один из этих этапов вполне может быть объектом кэширования, хотя это всё находится в ядре. Причём этот этап вносит весьма высокий вклад в падение производительности.
  • #50 Этап формирования предикатов может быть частично исключён, а они переключены на кэш политик
  • #51 Есть 3 типа политик. Динамические, которые пересоздаются каждый раз, ститические, которые создаются разово и контекст-зависимые, которые инвалидируются, если контекст меняется Соответственно 2 и 3 типы помещаются в кэш
  • #52 Соответственно статика применяется, если строка предиката константа, хотя значения в контексте меняются. Динамические когда сами строки строятся из контекста
  • #53 В целом настройки для политик устанавливаются очень просто. Мы просто указываем, что политика должна быть static, как например для политики фильтрации по имени пользователя. Итого исключив ненужные создания предикатов мы получили прирост скорости около 10%.
  • #54 В целом настройки для политик устанавливаются очень просто. Мы просто указываем, что политика должна быть static, как например для политики фильтрации по имени пользователя. Итого исключив ненужные создания предикатов мы получили прирост скорости около 10%.
  • #55 Производительность улучшилась, но количество hard parse не уменьшалось и это видно по плану выполнения запроса. На каждое имя пользователя свой план или дополнительные затраты на технологию adaptive cursor sharing.
  • #56 Решение это проблемы очень простое – не надо собирать предикат через конкатенацию
  • #57 А надо использовать непосредственно значение из контекста
  • #58 Таким образом для любых значений у нас одинаковый план и часть hard parse ушла
  • #59 Как вы думаете вообще с чего надо начать боль с плохими планами? Правильно, надо добавить индексы.
  • #60 Не забыть упомянуть отдельно про боль с хардпарсами и inmemory
  • #61 Эта странная на первый взгляд конструкция позволяет выбирать данные из InMemory кэшей как из обычных таблиц
  • #62 Решение очень простое – убрать красоту и использовать session level temprorary table
  • #63 Что в оракле 12.2 уже в inmemory по дефолту
  • #64 Всё было бы хорошо, но как всегда начали плакаться наши DBA. Как вы думаете – о чём
  • #65 Примерно каждое формирование ACL выглядит так
  • #66 Как мы это решили? Правильно, темпорари андо
  • #67 Как мы это решили? Undo мигрировало во временное пространство. В общем то dba счастливы,
  • #68 Очень интересно VPD ведёт себя с result cache, который как вы помните по моим прошлым презентациям мы любим и умеем готовить. Итак, давайте вспомним, что у нас есть. Давайте отфильтруем данные по пользователю PERSO Как мы видим сформировался код результата
  • #69 Про sql что пашет и картинку с планом и разным юзером
  • #70 Выберем данные для пользователя Петров, по которому данных нет
  • #71 И о чудо – наблюдаем такую же картину как и при вызове без пользователя, т.е. резалт кэш как-то учитывает впд.
  • #72 Вернёмся теперь к начальному состоянию и посмотрим не происходит ли какой-либо хаос Всё по нулям – резалт кэш работает
  • #73 За счёт чего же это происходит Глянем в ядро Мы увидим два одинаковых запроса, но с разными кэш айди. Требуется рыть глубже!
  • #74 Оттрассируем сессию с событием дебага резалт кэша и увидим, что в формирование кэша входит отдельно впд предикат, что и даёт разные айди кэшей, поэтому всё замечательно и работает
  • #75 Посмотрим теперь на пл скул Создадим функцию резалт кэш, которая возвращает количество записей в нашей таблице
  • #76 Итак, угадайте сколько у нас будет записей Ничего не меняется
  • #77 Почему? А по документации!
  • #78 Несмотря на то, что он у меня всегда работает я бы не рисковал с RC и VPD А теперь предлагаю секцию ответов и вопросов, чтобы вы всё не забыли и перерыв на чай.
  • #79 Кэш прав
  • #80 Тут стрелками нарисовать, где2-10 запиисей
  • #81 Соответственно, эти значения мы не захардкоживаем понятно дело, а собираем на основе полей из security context или ad ролей. И, кстати, как я ранее говорил, это идеальный претендент на то, чтобы стать context depended кандидатом для кэширования
  • #82 Итого мы сделали наш ACL инлайн, но иногда стали выскакивать уже знакомые ошибки. Если посмотреть на предикаты, то они выглядели обрезано
  • #83 Мы посмотрели в мануал и решили включить long policy, хотя понимали, что у нас нету 4000 символов. Как и ожидалось это не помогло. Как вы думаете, в чём же причина?
  • #84 Ответ на этот вопрос кроется как по-настоящему выглядит функция для получения предиката. А выглядит она так Т.е. получаем мы данные из контекста, в котором по-умолчанию не указано сколько символов надо возвращать, а исходная длина – 256. В чём смысл этого я не знаю. Если кто знает – расскажите. Дима, тут ты можешь ответить первым
  • #85 Поэтому мы указываем 4000 и радуемся
  • #86 Но как вы думаете какая боль у этого решения?
  • #87 Следующая беда, которая нас постигла это инвалидация курсоров по причине роу левел секьюрити Запомните количество версий курсоров – нам оно ещё пригодится
  • #88 обратите внимание, что количество предикатов во вью впд полиси совпало с количеством курсоров
  • #89 В общем то, это известная ситуация, отражённая в соответствующей ноте, что впд политики не меняют sql id, хотя из-за предикатов sql разный, что мы уже подтвердили через вью впд полиси.
  • #90 Один из вариантов, которые мы так же решили попробовать это денормализовать права. Лучше всего этот случай подходил тогда, когда пользователи позволяют свои документы смотреть другим.
  • #91 Ключевой вопрос – как делать фильтрацию. Тут есть 2 варианта. Like и contains. Однако первый всегда приводит к фулскану, а второй требует создания полнотекстовых индексов, которые не лучшим образом реализованы в оракле.
  • #92 Кэш коннектов
  • #93 Кэш впд
  • #94 советы datadriven кэши кэши вкл выкл кэши с настройкой времени
  • #95 Упомянуть про три политики Где юзернейм Где in Где сложные джоины
  • #96 Вопрос к аудитории про сложность security
  • #97 Если честно, я не знаю ещё как мы это будем делать, на стороне БД или всё же на стороне сервера приложений, но мы точно знаем, что Oracle VPD это позволяет Sga – full sql, LC – static policies, DF – all data Ну что ж, давайте подводить выводы Пример открытой времянки таблицы
  • #98 Предикаты VPD могут быть найдены на основе следующих эвентов трассировки
  • #99 Вы же не хотите, чтобы пользователь увидел, какие таблицы у него фильтруются
  • #100 Если честно, я не знаю ещё как мы это будем делать, на стороне БД или всё же на стороне сервера приложений, но мы точно знаем, что Oracle VPD это позволяет Ну что ж, давайте подводить выводы
  • #101 Один и тот же хэщ – спросить в чём риск Хранение хэша Можно добыть хэш
  • #102 Один и тот же хэщ – спросить в чём риск Хранение хэша Можно добыть хэш
  • #103 Один и тот же хэщ – спросить в чём риск Хранение хэша Можно добыть хэш
  • #104 Один и тот же хэщ – спросить в чём риск Хранение хэша Можно добыть хэш И злоумышленник даже не понимает, что данных нет, так как мы не генерим исключение, а просто имитируем пустой логин
  • #105 Один и тот же хэщ – спросить в чём риск Хранение хэша Можно добыть хэш
  • #106 Если честно, я не знаю ещё как мы это будем делать, на стороне БД или всё же на стороне сервера приложений, но мы точно знаем, что Oracle VPD это позволяет Ну что ж, давайте подводить выводы
  • #107 Дата за вчера с украденным хэшем
  • #108 В данном варианте мы убеждаемся, что текущая дата сервера находится в диапазоне даты, пришедшей как входной параметр плюс время, в течении которого она может существовать. Таким образом, если злоумышленник похитил срочку с вызовом, у него есть только 1 секунда, чтобы ей воспользоваться.
  • #109 Если честно, я не знаю ещё как мы это будем делать, на стороне БД или всё же на стороне сервера приложений, но мы точно знаем, что Oracle VPD это позволяет Ну что ж, давайте подводить выводы
  • #110 Если честно, я не знаю ещё как мы это будем делать, на стороне БД или всё же на стороне сервера приложений, но мы точно знаем, что Oracle VPD это позволяет Ну что ж, давайте подводить выводы
  • #111 С ораклом такие штуки не проходят, потому что там другой механизм работы RLS, но я смог и тут кое-что проделать. Во-первых, можно использовать pl-sql с result cache как мы смотрели ранее или ещё более забавный способ. Я собрал статистику по таблице
  • #112 А потом декодировал минимальные и максимальные значения по одной из скрытых колонок и получил их возможный диапазон. Не так много, но в опытных руках этого может быть уже достаточно.
  • #113 Тем не менее у меня получилось взломать другую часть VPD, которая называется column data masking. Создадим другую политику Итак, создадим такую же как и политику безопасности политику скрывания. Если security предикат верен, то запись будет показываться, если нет – то не будет. В нашем случае мы будем видеть поля только тогда, когда залогиненный пользователь совпадает с создателем.
  • #114 Свяжем политику с таблицей и полями, которые должны находиться под защитой и указываем, что не удовлетворяющие контролю строки не должны исчезать.
  • #115 Свяжем политику с таблицей и полями, которые должны находиться под защитой и указываем, что не удовлетворяющие контролю строки не должны исчезать.
  • #117 Меняем пользователя на Персо и видим, что его имена показались, а остальное скрылось
  • #118 А теперь начнём взлом! Используем типовую технику, а именно через возврат данных, которые скрыты. Плохие новости, не правда ли? Как можно решить эту проблему? Посмотреть версию и
  • #119 А теперь начнём взлом! Используем типовую технику, а именно через возврат данных, которые скрыты. Плохие новости, не правда ли? Как можно решить эту проблему? Посмотреть версию и
  • #120 И перейти на другую, где и запустить наш скрипт. Да, сообщение конечно же, меня не радует, ибо мы долго и упорно стараемся скрыть факт наличия безопасности в приложении, а тут о нём нам явно говорят, но других вариантов я для себя не вижу.
  • #121 Давайте попробуем более сложную атаку, а именно уже известную Iterative inference attack
  • #122 Вопрос к аудитории про сложность security
  • #123 Кстати, хотел показать, что в самом дефолтном Оракле VPD используется, но политики завраплены, я, конечно же, смотрел их, но уже забыл о чём они. Их довольно много в OEBS, но у меня не было под рукой его инсталляции, чтобы вам показать.
  • #124 В вопросу о Row Level Security работает не только в MsSql, но и в современно Azure SQL Data Warehouse, само собой Постгрес и amazon insight. Наверняка, ещё и в других СУБД, но дальше я не рыл.
  • #125 Итак, давайте повторим в постгресе ряд политик. Например, политику по имени пользователя. Включаем факт работы RLS на таблице, потом создаём вполне очевидную таблицу Самое главное как оказалось включить режим игнорирования факта незаполнения контекста, иначе без него получалась ошибка, которая не позволяла имитировать тут ситуацию, что если контекст не заполнен, то данные показывать не надо.
  • #126 Установим в контекст имя пользователям ии проверим как всё работает. Всё прекрасно фильтруется и предикат безопасности наблюдается в плане выполнения
  • #127 Создадим нашу денормализованную таблицу в постгресе, только вместо типа varchar используем более родной для Postgres тип Массив и созданим по полю полнотекстовый индекс А далее создадим политику, которая проверяет вхождение в данный массив пользователя из контекста.
  • #128 Проверим работу РЛС с денормализованными данными – в целом всё великолепно
  • #129 Как мы видим, постгрес весьма разумно использует полнотекстовые индексы и как показал наш опыт они более стабильны в нём, однако в силу более слабого оптимизатора деградация производительности не менее 15%, а в некоторых случаях была и больше. Ну что ж, давайте подводить выводы
  • #130 Ну что же Давайте подводить выводы, которых понятно будет много
  • #132 Bad performance = unpredictable perforomance – mention pictures from PG, MS and Oracle and put picture Possible
  • #133 Итак, к чему же мы пришли с мифами? Плохая производительность трансформируется в непредсказуемую Сложная реализация сводится к непростой отладке Да, никакого взаимодействия с UI Что касается того, что рлс есть в старых СУБД, его легко взломать, да и то, что он применим только для 2-х звенных приложений это конечно же не верно
  • #134 Для быстрого закрытия техдолга В случае если к БД ходит напрямую множество приложений Недавно созданые приложения, в которых можно что-то подфиксить, если они начнут ломаться Требования соответствия различным законам
  • #135 Когда не стоит использовать безопасность в базах данных? Когда доступ гарантировано проходит только через сервер приложений В сложной микро сервисной архитектуре Для очень старых приложений, в которых добавление слоя фильтрации на стороне БД поломает приложение Высоконагруженные OLTP приложения, в которых добавление чего-либо неконтролируемого может сильно изменить время отклика
  • #136 Наши основные уроки таковы Думайте о безопасности заранее Используйте data-driven кэши Если есть возможность денормализовать права по безопасности, то это не помешает Упрощайте политики – тут проговорить, что если политика работает на таблице, на которой есть политика, то ничего не взлетит Не забывайте о взломе Главное, что row level security прекрасно работает в бд И даже в Postgres
  • #137 Всем спасибо за внимание, я готов ответить на ваши вопросы