8 lines
15 KiB
JSON
8 lines
15 KiB
JSON
{
|
||
"index": 145,
|
||
"slug": "editorial-2023-12-field-security-audit",
|
||
"title": "Аудит веб-проекта: как превратить список рисков в безопасный порядок исправлений",
|
||
"excerpt": "Высокий score не говорит, что менять первым. Разбираем security-triage через evidence, границы системы, владельца, обратимый шаг и проверяемый критерий результата.",
|
||
"contentHtml": "<p>После аудита команда часто получает длинный список пунктов. В одном есть версия зависимости. В другом — вопрос к авторизации. В третьем неясно, кто выдаёт загруженный файл. Заголовки звучат одинаково тревожно, но доказательства различаются. Если первым исправить самый громкий пункт, можно потратить релиз на косметическую правку и оставить публичный путь без владельца. Поспешное изменение может сломать рабочий сценарий. Цена ошибки — простой пользователей, потеря данных или новый обход защиты.</p>\n<p>Безопасный triage начинается не со score. Он отвечает на четыре вопроса: что наблюдается, какая граница затронута, кто подтверждает контракт и какой следующий шаг можно отменить. Severity помогает описывать риск. Она не назначает владельца, не даёт разрешение на проверку и не доказывает наличие уязвимости.</p>\n<h2>Тезис: порядок исправлений строит evidence</h2>\n<p>Разделите карточку риска на пять частей: evidence, exposure, owner, reversibility и decision. Evidence связывает утверждение с источником. Exposure показывает путь от внешнего входа к данным или действию. Owner подтверждает границу и принимает изменение. Reversibility описывает возврат. Decision объясняет, почему пункт идёт сейчас.</p>\n<p>Запись «проверить границу авторизации API» — вопрос. Запись «любой пользователь читает чужой заказ» — утверждение, которому нужны воспроизводимый сценарий, разрешённая среда и зафиксированный результат. Пока этих условий нет, карточка имеет статус evidence gap. Нельзя поднимать её до подтверждённой уязвимости только потому, что она выглядит правдоподобно.</p>\n<h2>Как score вводит в заблуждение</h2>\n<p>CVSS описывает характеристики уязвимости и помогает сравнивать техническую тяжесть. Но score не видит карту продукта. Он не знает, какой путь критичен для бизнеса, согласован ли тест, принадлежит ли endpoint вашей команде и что произойдёт после изменения. Поэтому высокий Base score может ждать уточнения, а менее громкий пункт с неизвестной публичной границей — получить первый безопасный gate.</p>\n<p>Порядок должен быть объясним одним предложением: «Сначала подтверждаем владельца и ожидаемый отказ на публичной границе доступа, затем согласуем контракт identity-провайдера, после этого меняем выдачу файла с готовым rollback». Если такую фразу нельзя составить, список смешивает проверку фактов, согласование scope и разработку.</p>\n<table><thead><tr><th scope=\"col\">Симптом</th><th scope=\"col\">Причина</th><th scope=\"col\">Проверка</th><th scope=\"col\">Действие</th></tr></thead><tbody><tr><td>Самый высокий score всегда первый</td><td>Severity подменяет контекст</td><td>Запросить claim, источник и ограничение</td><td>Обосновать порядок evidence и exposure</td></tr><tr><td>Есть домен, но нет границы</td><td>Актив и third-party путь смешаны</td><td>Нарисовать один пользовательский маршрут</td><td>Убрать неподтверждённый участок</td></tr><tr><td>«Добавим проверку доступа» без теста</td><td>Решение опередило критерий</td><td>Назвать ожидаемый allow и deny</td><td>Написать validation до кода</td></tr><tr><td>Rollback означает «откатить»</td><td>Не названы версия и ответственный</td><td>Проверить обратное действие</td><td>Назначить owner и stop condition</td></tr><tr><td>security.txt считают разрешением</td><td>Disclosure смешали с authorization</td><td>Проверить объект, метод и время</td><td>Без согласования ограничиться инвентаризацией</td></tr></tbody></table>\n<figure><img src=\"/assets/editorial/2023/security-audit-2023-remediation-route.svg\" alt=\"Схема безопасного triage: evidence gap, граница третьей стороны и выдача файла проходят через владельца, scope, validation и rollback до изменения\" /><figcaption>Маршрут показывает порядок вопросов. Он не оценивает реальный риск, не находит уязвимость и не запускает remediation.</figcaption></figure>\n<h2>Минимальная запись, которая выдерживает проверку</h2>\n<p>Карточка не обязана быть большой. Поле <code>claim</code> описывает факт или вопрос, а не решение. <code>source</code> указывает журнал, запрос, конфигурацию, владельца или документ. <code>status</code> различает hypothesis, observed и confirmed. В <code>limit</code> записывают то, чего проверка не показывает.</p>\n<pre><code>const card = {\n id: 'SEC-042',\n claim: 'роль reader получает чужой заказ',\n scope: 'orders-api / GET /orders/:id',\n owner: 'orders-team',\n status: 'hypothesis',\n source: 'reproduction-2026-08-02-01',\n expected: { allow: 'свой заказ', deny: 'чужой заказ: 403' },\n limit: 'тестовая среда; production не проверялся',\n next: 'согласовать сценарий с владельцем API',\n rollback: 'изменений в системе нет'\n};\n\nif (card.status === 'hypothesis') {\n console.log('Не называть карточку подтверждённой уязвимостью');\n}</code></pre>\n<p>Пример учебный. Он не отправляет запросы, не получает токены и не доказывает поведение API. Его задача — показать форму записи. В настоящем отчёте идентификатор источника должен вести к разрешённому материалу. Не вставляйте пароль, токен, персональные данные или полный ответ, если для вывода достаточно хеша, фрагмента и защищённой ссылки.</p>\n<h2>Проверяемый маршрут от гипотезы к изменению</h2>\n<ol><li><strong>Опишите симптом.</strong> Запишите сценарий, время и наблюдаемый результат. Не называйте сигнал критической уязвимостью заранее.</li><li><strong>Назовите границу.</strong> Укажите приложение, endpoint, роль, данные и переход к внешней зависимости. Домен не является картой продукта.</li><li><strong>Проверьте разрешение.</strong> Зафиксируйте объект, среду, окно времени, допустимый метод, запретные действия, контакт и условие остановки. Документ disclosure не заменяет эту запись.</li><li><strong>Разделите allow и deny.</strong> Для авторизации назовите разрешённый результат и отказ. Для файла опишите приём, серверное имя, хранение и проверку доступа при выдаче.</li><li><strong>Назначьте владельца.</strong> Он подтверждает контракт и принимает решение.</li><li><strong>Выберите обратимый gate.</strong> Сначала добавьте чтение, тест, флаг или review контракта. Не меняйте необратимую схему, пока не закрыты evidence и rollback.</li><li><strong>Сформулируйте критерий.</strong> Назовите наблюдаемый результат, источник результата и момент проверки.</li><li><strong>Обновите карточку.</strong> Измените status, source, limit и rationale. Если evidence не подтвердился, верните hypothesis или закройте false positive с объяснением.</li></ol>\n<h2>Отрицательный путь важнее красивого отчёта</h2>\n<p>Если scope не подтверждён, активная проверка останавливается. Не стоит проверять путь на домене, который может принадлежать подрядчику. Если владелец неизвестен, назначьте вопрос и сохраните evidence gap. Если тест требует необратимой миграции, сначала проведите отдельный review изменения. Если после фикса нет безопасного способа проверить отказ, решение не готово.</p>\n<p>Та же логика работает для upload delivery. Нельзя считать файл защищённым только потому, что форма требует входа. Нужно проверить границу выдачи, серверное имя, место хранения, содержимое и авторизацию на чтении. Нельзя считать файл уязвимым только из-за расширения в URL. Нужны наблюдаемый сценарий и согласованный метод.</p>\n<h2>Ограничения метода</h2>\n<p>Матрица triage не заменяет penetration test, threat model, code review или incident response. Она не вычисляет business impact и не обещает срок исправления. OWASP ASVS задаёт проверяемые требования, но не знает архитектуру проекта. CVSS помогает описать тяжесть, но не выбирает владельца и не создаёт разрешение. RFC 9116 описывает канал раскрытия, а не право тестировать домен.</p>\n<p>Источники могут обновляться. Поэтому в отчёте фиксируйте версию стандарта и идентификатор требования. Не пишите «проверено по OWASP» без названия документа, версии, scope и метода. Не выдавайте учебный объект, синтетическую запись или локальный тест за production evidence.</p>\n<h2>Критерий готовности</h2>\n<p>Карточка готова к исправлению, когда другой инженер без устного контекста может ответить на пять вопросов: какой факт или вопрос проверяется; какая граница входит в scope; кто разрешил и принимает решение; какой результат подтвердит или опровергнет гипотезу; как вернуть изменение и кто это сделает. У карточки есть источник, версия метода, ограничение и дата следующей проверки.</p>\n<p>Если хотя бы одного ответа нет, готов не fix, а следующий gate. Это проверяемый результат аудита. Он снижает риск ошибочной правки и сохраняет отрицательный путь: команда знает, когда остановиться.</p>\n<h2>Проверяемые источники</h2><ul><li><a href=\"https://owasp.org/www-project-application-security-verification-standard/\" target=\"_blank\" rel=\"noopener\">OWASP Application Security Verification Standard</a> — актуальная стабильная версия ASVS 5.0.0 и правила ссылок на версионированные требования.</li><li><a href=\"https://www.first.org/cvss/v4.0/\" target=\"_blank\" rel=\"noopener\">FIRST: Common Vulnerability Scoring System v4.0</a> — официальная спецификация метрик CVSS.</li><li><a href=\"https://www.rfc-editor.org/rfc/rfc9116.html\" target=\"_blank\" rel=\"noopener\">RFC 9116: A File Format to Aid in Security Vulnerability Disclosure</a> — формат security.txt, область действия и отсутствие implied permission for testing.</li></ul>"
|
||
}
|