ROW CHECK и безопасность
Работал я в одном стартапе на Кложе. Код прошел через десятки разработчиков и представлял лоскутное одеяло: разные подходы и библиотеки. Каждый разработчик городил что-то сбоку, а не исправлял текущее положение дел. Была своя ORM с километрами кода и склейкой SQL-строк. Много там всего было, и в том числе база данных.
Эта база прямо сейчас стоит в памяти. Она тоже прошла через серию разработчиков,
каждый из которых знал, как делать правильно. Одни ребята забивали на
нормализацию; другие решили, что добавлять колонки утомительно и сделали поле
info с типом jsonb, в которое валили все подряд. Были материализованные вьюхи,
обновлять которые было затратно, и которые без конца обновлялись из-за косяков в
очереди сообщений. Ни одна запись физически не удалялась, а помечалась флагом
is_deleted = true
. Много багов было связано с тем, что данные выбирались без
этой проверки.
Но это не все. Основатель фирмы считал себя специалистом по безопасности и
придумал вот что. В Постгресе есть штука под названием ROW CHECK
: проверка
доступа на уровне записи. Если некая функция my_check(row)
возвращает null
или false
, то клиент словно не видит этой записи. Это медленно, но работало.
Почему директор так сделал? Он хранил в одной таблице данные разных клиентов и
опасался, что из-за ошибки в коде один клиент увидит данные другого. Поэтому
каждая таблица хранила избыточные айдишки, и в рамках каждого запроса
выставлялась переменная current_owner
. Функция ROW CHECK
проверяла, что ее
значение совпадает с айдишками записи.
Воздвигнув этот бастион, директор спокойно сидел под рутовой учеткой, для которой проверки были отключены. На моей памяти было два крупных инцидента, когда он путал окна и выполнял на проде то, что хотел выполнить на тесте. Терялись данные, пропадали целые таблицы.
К счастью, наши часовые зоны сильно отличались, поэтому на починку базы бросали другого человека. По понедельникам он рассказывал, как просиживал выходные за восстановлением бекапов, импортов CSV и отладкой. Были и другие, не столь фатальные случаи, связанные с активностью директора на проде.
Забавно, но наибольший урон базе нанес именно директор, а не хакеры или кривой код. Хакерам, видимо, стартап был не интересен, хотя в самописной ORM были дыры для инъекций. Код, хоть и был не супер, не страдал тем, что читал чужие данные. Свои удаленные – да, но не чужие.
Можно сказать одно: все запреты проверяются на прочность теми, кто их создает. У меня доступ на прод был только для чтения. В другом стартапе права на запись были, но под той учеткой я не ходил. В конце концов, был страх, что за подобный инцидент уводят. А у директора страха не было, вот и результат.
В более широком ключе: запрет хорошо работает только тогда, пока его соблюдают те, кто принимал. Не важно, о чем идет речь: о детях, собаках или машинах. Если говорящая голова топит за очередной запрет, но не готова применить его к своим детям, собакам или машинам, сказанное не имеет смысла.
Нашли ошибку? Выделите мышкой и нажмите Ctrl/⌘+Enter