Управление уязвимостями отвечает на вопрос, что происходит с находкой после того, как её нашли. Аудит, сканер или проверка кода дают список, а процесс превращает список в закрытые дыры: у каждой находки есть запись, приоритет, ответственный, срок и проверка, что исправление работает. Без процесса отчёт об аудите лежит в почте, а через полгода те же ошибки находят снова.

Процесс не требует дорогих систем: для команды из нескольких разработчиков хватает таблицы или трекера задач и недельной договорённости. Как проводится сама проверка, описано на страницах «Аудит безопасности веб-приложения» и «Secure code review», как встроить автоматические проверки в сборку — на странице «Внедрение DevSecOps». Здесь о том, что делать с их результатами.

Коротко. Шесть шагов: найти, записать, оценить, назначить, исправить, проверить. Приоритет задают три вещи: насколько опасна ошибка, достижима ли она и что лежит за ней. Закрытой считается только находка, на которую есть тест или повторная проверка. Принятый риск оформляется письмом с владельцем и датой пересмотра.

Шесть шагов: от находки до закрытия

Весь процесс помещается в шесть шагов. Если какой-то пропущен, находки накапливаются или закрываются «на словах».

ШагЧто происходитЧто на выходеКто отвечает
1. НайтиАудит, ревью кода, проверка в сборке, сообщение пользователя или сторонней организацииСырая находка с описанием местаИсточник находки
2. ЗаписатьНаходка заносится в реестр, дубли склеиваются, ложные срабатывания помечаются с причинойЗапись с номером и статусомОтветственный за безопасность в команде
3. ОценитьОпределяется серьёзность, достижимость и ценность данных, которые лежат за ошибкойПриоритетТот, кто знает приложение: техлид и ответственный за безопасность
4. НазначитьСтавится владелец и срок по приоритету, создаётся задачаЗадача в трекере со срокомРуководитель разработки
5. ИсправитьПравка кода, обновление зависимости или смена настройки; если сразу нельзя, временная мераИзменение, прошедшее обычное ревьюВладелец задачи
6. ПроверитьПовторная проверка тем же способом, которым нашли, и тест на регрессиюСтатус «закрыто» с подтверждениемНе исполнитель, а второй человек или автоматика

Шаги 2 и 6 пропускают чаще всего. Без записи находка живёт в чьей-то голове, без проверки закрытие означает «разработчик сказал, что исправил».

Откуда берутся находки и сколько в них шума

Источников несколько, и у каждого свой характер. Один даёт мало находок, но точных, другой много, и половина из них не требует действий.

ИсточникЧто даётШумКто разбирает
Аудит или ревью кода человекомОшибки логики и прав, которые автоматика не видитМало: каждая находка с воспроизведениемАвтор отчёта вместе с вашим разработчиком
Статический анализ кода в сборкеОпасные конструкции: сборка запросов строкой, слабая криптография, секреты в кодеЗаметный: часть срабатываний относится к недостижимому кодуРазработчик в рамках ревью изменения
Проверка зависимостейИзвестные уязвимости в используемых библиотекахВысокий: уязвимая функция может не вызываться у васОтветственный за безопасность, раз в неделю
Динамическая проверка стендаПроблемы настройки и заголовков, видимые снаружиСредний: нужен разбор на стендеОтветственный за безопасность
Сообщение пользователя или исследователяНаходки, которые вы пропустилиРазный; требуют быстрой реакцииРуководитель разработки, тот же день
ИнцидентПодтверждённая эксплуатация ошибкиНет, это фактРуководитель с участием владельца системы
Опросник клиентаВопросы, на которые нечем ответитьМало, но это сигнал о слепых зонахОтветственный за безопасность

Разницу между статическим анализом, динамической проверкой и анализом зависимостей подробно описывает статья «SAST, DAST, SCA: в чём разница», а настройку в вашей сборке — страница про анализ кода и зависимостей. Для процесса важно одно: все источники сходятся в один реестр, иначе приоритеты сравнивать не с чем.

Реестр: что записывать по каждой находке

Реестр — это таблица или проект в трекере задач. Он нужен не контролёру, а вам: через три месяца по нему видно, что открыто, что закрыто и почему. Минимальный набор полей:

  • Номер и краткое название. «Доступ к чужим заказам по номеру в адресе», а не «IDOR».
  • Место. Адрес, файл и функция либо библиотека и версия.
  • Как воспроизвести. Шаги, по которым разработчик увидит проблему сам. Находка без воспроизведения плохо проверяется при закрытии.
  • Источник и дата. Кто нашёл и когда. По дате считается возраст находки.
  • Серьёзность, достижимость, ценность данных. Три отдельные отметки, а не одна общая.
  • Владелец и срок. Фамилия человека, а не название команды.
  • Статус. Новая, подтверждена, в работе, исправлена, проверена, закрыта, ложная, принят риск.
  • Ссылка на исправление и на проверку. Изменение в репозитории и тест либо запись о повторной проверке.

Не копируйте в реестр секреты и данные клиентов, найденные при проверке: достаточно описания места. Сам реестр содержит сведения об уязвимостях, поэтому доступ к нему узкий.

Как расставлять приоритеты: три вопроса вместо одной оценки

Единая оценка серьёзности из сканера или из каталога уязвимостей описывает ошибку в вакууме. Для вас важнее три вопроса, и ответы на них меняют порядок работ.

  1. Насколько опасна сама ошибка? Чтение чужих данных, выполнение чужого кода и обход входа опаснее, чем отсутствие заголовка.
  2. Достижима ли она? Виден ли уязвимый адрес снаружи, нужна ли учётная запись, вызывается ли уязвимая функция библиотеки в вашем коде.
  3. Что лежит за ней? Персональные данные, деньги, учётные записи администраторов или справочник городов.

Ниже условные примеры, показывающие, как одни и те же вопросы дают разный порядок.

Условная находкаОпасностьДостижимостьЧто за нейРешение
Клиент открывает заказы другого клиента, меняя номер в адресеВысокая: чтение чужих данныхЛюбой вошедший пользовательКонтакты и суммы заказовПервая очередь, исправить сразу
Библиотека с уязвимостью, функция не вызываетсяВысокая по описаниюНизкая: код не используетсяНе применимоОбновить в плановом порядке, не срочно
Ключ доступа к базе найден в истории репозиторияВысокаяЗависит от доступа к репозиториюВся базаЗаменить ключ в тот же день; историю чистить потом
Администратор входит без второго фактораСредняяТолько из внутренней сетиПрава на все данныеВ ближайший релиз, с временной мерой на сети
Не хватает одного защитного заголовкаНизкаяТребует другой уязвимостиПубличные страницыПо плану, вместе с другими настройками

Видно, что высокая серьёзность по описанию не значит срочность, а средняя может оказаться срочной. Принимать такие решения лучше вдвоём: тот, кто знает приложение, и тот, кто знает ошибки.

Сроки и владельцы: как не превратить реестр в кладбище

Срок задаётся классом приоритета, а не настроением недели. Ниже шкала в качестве отправной точки; значения подстройте под ваш ритм релизов и запишите в регламент. Сроки считаются от подтверждения находки.

КлассРеакцияСрок исправленияЕсли не успеваем
Критический: эксплуатация идёт или тривиальна, под угрозой данные клиентовВ тот же деньВ течение нескольких дней, вне обычного релизаВременная мера немедленно: закрыть функцию, отключить доступ, сменить ключи
ВысокийВ течение рабочего дняБлижайший релиз, обычно в пределах недели-двухВременная мера и письменное решение руководителя
СреднийВ течение неделиБлижайшие один-два релизаПеренос с новой датой и указанием причины
НизкийПри разборе очередиПо плану, вместе с другими работамиЗакрыть как «принят риск» или удалить из реестра с пояснением

Три правила делают шкалу рабочей:

  • У срока есть владелец-человек. Задача, у которой записано «команда разработки», не имеет исполнителя.
  • Просрочка видна. На недельном разборе первым делом смотрят то, что вышло за срок, а не новые находки.
  • Нельзя молча сдвинуть срок. Перенос оформляется записью: новая дата и причина. Три переноса подряд означают, что нужно либо выделить время, либо пересмотреть класс.

Когда находка считается закрытой, и как принимать риск письменно

«Исправлено» и «закрыто» — разные статусы. Закрыто то, что проверено вторым человеком или автоматикой.

  1. Исправление прошло обычное ревью и попало в релиз, который работает у пользователей, а не только в ветке.
  2. Для логической ошибки добавлен тест, который падает на старом коде: тогда ошибка не вернётся незаметно.
  3. Тем же способом, которым находку нашли, проверено, что она больше не воспроизводится: тот же прогон, тот же запрос, повторное срабатывание сканера.
  4. Временные меры, поставленные на время исправления, сняты или записаны как постоянные.

Исключения: принятие риска

Иногда исправлять нецелесообразно: ошибка в устаревшем модуле, который выведут из эксплуатации, или исправление дороже возможного ущерба. Это допустимо, если решение оформлено, а не забыто:

  • Кто принял. Руководитель, у которого есть право отвечать за последствия, а не автор кода.
  • Почему. Одна-две фразы с описанием, что именно остаётся открытым.
  • Чем компенсируем. Ограничение доступа по сети, усиленный журнал, оповещение о попытках.
  • Когда пересмотрим. Дата в календаре. Исключение без даты превращается в бессрочное.

Метрики и ритм: что смотреть, чтобы процесс не умер

Хватает четырёх показателей, их можно считать вручную из реестра. Они показывают состояние процесса, а не количество найденных ошибок: рост числа находок после включения проверок означает, что вы стали видеть больше, а не что стало хуже.

  • Возраст открытых находок. Самая старая критическая и самая старая высокая. Это главный показатель: он показывает, где процесс застрял.
  • Просроченные. Сколько находок вышло за срок и у кого. Растущий список говорит, что не хватает времени, а не людей.
  • Повторные. Сколько находок возвращается после закрытия. Они показывают, что закрывали симптом, а не причину, и что нет тестов.
  • Время реакции на критические. От сообщения до первой меры.

Ритм простой. Раз в неделю короткий разбор: просроченное, новое, решения по приоритетам. Раз в квартал полный просмотр реестра: исключения с наступившей датой, находки без движения, ложные срабатывания. После крупного релиза или смены подрядчика добавляется внеочередной разбор. Для небольшой команды это полчаса в неделю, а не отдельная должность. Если проверки в сборке только внедряются, ориентиром служит статья «DevSecOps: с чего начать небольшой команде».

Признаки того, что процесс не работает

Процесс ломается тихо. По этим признакам понятно, что пора что-то менять:

ПризнакЧто за нимЧто делаем
Отчёт аудита лежит в почте, реестра нетНаходки не получили владельцевЗаводим реестр и переносим находки с приоритетами и сроками
Все находки названы срочнымиПриоритеты не различаются, срочным нельзя заниматьсяВводим три вопроса и классы; критических остаётся единицы
Закрывает тот же, кто исправлялНет независимой проверкиЗакрывает второй человек или повторный прогон
Сканер выдаёт сотни срабатываний, никто не смотритШум победил сигналОтключаем правила, не применимые к вам, разбираем остальное по приоритетам
Сроки переносят без записиСрок ничего не значитЛюбой перенос с причиной и датой, три переноса пересматривают класс
Исключения без даты пересмотраРиск принят навсегда без решения об этомВсем исключениям ставим дату и владельца
Исправили, а через релиз то же самоеНет теста на регрессиюДобавляем тест к каждому исправлению логической ошибки

Что делаем мы и с чего начать

Начинаем с обследования: 200 000 ₽ за один-два процесса и 2–3 недели, 350 000 ₽ и 3–4 недели, если приложений несколько. Если нужны находки, проводим аудит безопасности или ревью кода: отчёт содержит воспроизведение, серьёзность и порядок исправления, то есть записи, готовые для реестра. Мы помогаем завести реестр, согласовать классы и сроки, настроить проверки в сборке и разобрать первые срабатывания. Исправление найденного оценивается отдельно, от 150 000 ₽, и заказывать его у нас не обязательно. Стоимость обследования вычитается из первого этапа, если продолжаете с нами.

Мы не берём на себя круглосуточное дежурство и реакцию на инциденты в течение часа, не поставляем системы мониторинга безопасности, не проводим пентест боевых систем и аттестацию, лицензии ФСТЭК у нас нет. Исходный код и реестр остаются у вас с первого дня. Цены и сроки — на странице «Тарифы». Как проходит проверка кода — на странице «Secure code review», как встроить безопасность в весь цикл разработки — на странице «Безопасная разработка веб-приложений».

Частые вопросы

Чем управление уязвимостями отличается от аудита?

Аудит — разовая проверка, которая даёт список находок. Управление уязвимостями — постоянный процесс, который доводит находки до закрытия: запись, приоритет, владелец, срок, проверка. Аудит можно заказать один раз, процесс живёт в вашей команде.

Нужна ли для этого специальная система?

Для небольшой команды нет. Хватает таблицы или проекта в трекере задач с полями из статьи и недельного разбора. Специализированные системы нужны, когда находок много и источников больше пяти, но заводить процесс стоит с таблицы.

Как выбрать приоритет, если сканер ставит всем высокую серьёзность?

Задать три вопроса: насколько опасна ошибка, достижима ли она у вас и что лежит за ней. Оценка сканера описывает ошибку в вакууме. Уязвимая функция библиотеки, которая не вызывается в вашем коде, срочной не бывает, а ошибка прав с доступом к клиентам срочна даже при средней оценке.

Какие сроки исправления разумны?

Критические исправляют в течение нескольких дней, вне обычного релиза, с временной мерой в тот же день. Высокие уходят в ближайший релиз, средние в ближайшие один-два релиза, низкие по плану. Это отправная точка, значения подстраивают под ритм релизов и записывают в регламент.

Что делать, если исправить нельзя или слишком дорого?

Принять риск письменно: кто принял, почему, чем компенсируем и когда пересмотрим. Решение принимает руководитель, а не автор кода, и у исключения всегда есть дата пересмотра. Без неё исключение превращается в бессрочное.

Как понять, что находка действительно закрыта?

Если исправление проверено вторым человеком или автоматикой тем же способом, которым находку нашли, и есть тест, который падает на старом коде. Слова разработчика «исправил» закрытием не считаются.

Сколько времени это занимает у команды?

Для небольшой команды около получаса в неделю на разбор и время на сами исправления. Дольше всего занимает запуск: завести реестр, согласовать классы и сроки, разобрать накопившиеся находки.

Сколько стоит помощь с запуском процесса?

Обследование стоит 200 000 ₽ за 2–3 недели (350 000 ₽ за 3–4 недели при нескольких приложениях) и вычитается из первого этапа, если продолжаете с нами. Аудит безопасности или ревью кода оцениваются по той же шкале. Исправление найденного — от 150 000 ₽, сопровождение — 20 000, 60 000 или 120 000 ₽ в месяц.