Files

8 lines
18 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"index": 146,
"slug": "editorial-2023-12-mechanism-security-audit",
"title": "Аудит веб-проекта: как превратить наблюдение в проверяемый вывод",
"excerpt": "Практический аудит начинается не со сканера, а с границ системы, разрешённых действий и цепочки доказательств. Разбираем, как отделить факт от гипотезы и выбрать безопасный следующий шаг.",
"contentHtml": "<p>После аудита в документе появляется строка: «найдена уязвимость на границе авторизации». Но рядом нет точного актива, версии среды, описания наблюдения и подтверждения, что проверка была разрешена. Через день команда уже спорит не о факте, а о формулировке. Одни требуют срочного исправления, другие не могут повторить проверку. Цена ошибки — неверный приоритет и риск изменить рабочий путь без понимания причины. Если вывод окажется ложным, команда потратит время на защиту несуществующей проблемы. Если он окажется верным, слабая запись задержит исправление.</p>\n<p><strong>Тезис.</strong> Аудит строится из четырёх раздельных объектов: scope называет участок системы, authorization ограничивает допустимые действия, evidence связывает утверждение с наблюдением, а decision назначает владельца и следующий шаг. Ни один объект не заменяет другой. Публичный URL не описывает всю систему. Ссылка на стандарт не даёт право на тест. Скриншот не доказывает воспроизводимость. Score не превращается сам в план исправления.</p>\n<h2>Сначала зафиксируйте наблюдаемую границу</h2>\n<p>Начните с одного пользовательского сценария: вход, смена адреса, оплата или загрузка документа. Опишите путь от действия пользователя до изменения состояния. Для каждого перехода запишите asset ID, границу, владельца, класс данных и вопрос проверки. Формулировка «проверить API» слишком широкая. Формулировка «подтвердить, кто принимает решение о доступе между браузером и API» уже задаёт предмет.</p>\n<p>Карта активов не утверждает, что защита работает или не работает. Она показывает, где команда ожидает контракт и кто может его объяснить. Это важное отрицательное свойство карты. Если для identity provider нет владельца, запись не должна превращаться в «низкий риск». Её статус — пробел в evidence и запрос на подтверждение.</p>\n<div class=\"table-scroll\"><table><caption>Четыре слоя записи аудита</caption><thead><tr><th scope=\"col\">Слой</th><th scope=\"col\">Вопрос</th><th scope=\"col\">Минимальная запись</th><th scope=\"col\">Чего она не доказывает</th></tr></thead><tbody><tr><td>Scope</td><td>Какой участок обсуждаем?</td><td>asset ID, boundary, owner</td><td>Что участок уже проверен</td></tr><tr><td>Authorization</td><td>Что разрешено делать?</td><td>метод, среда, окно, stop condition</td><td>Что проверка дала положительный результат</td></tr><tr><td>Evidence</td><td>Что именно наблюдалось?</td><td>источник, время, версия, ограничение</td><td>Что вывод переносится на всю систему</td></tr><tr><td>Decision</td><td>Кто и что делает дальше?</td><td>owner, reversible step, criterion</td><td>Что исправление уже выполнено</td></tr></tbody></table></div>\n<figure><img src=\"/assets/editorial/2023/security-audit-2023-evidence-matrix.svg\" alt=\"Матрица учебных карточек scope, owner, permission и remediation gate; evidence отделено от разрешения и finding\" loading=\"lazy\" /><figcaption>Схема показывает форму связи между карточками. Это не карта реальной сети, не результат сканирования и не подтверждение безопасности продукта.</figcaption></figure>\n<h2>Как наблюдение становится проверяемым выводом</h2>\n<p>Evidence начинается с узкого утверждения. Например: «в согласованной тестовой среде запрос без нужной роли получил ответ 200 на маршруте X». Такая запись ещё не объясняет причину и не говорит, что production уязвим. Она фиксирует наблюдение, условия и границу вывода. Чтобы перейти от наблюдения к finding, нужен повторяемый метод, сопоставимый результат и право выполнить именно это действие.</p>\n<p>У карточки evidence должны быть простые поля. <code>scopeId</code> связывает материал с активом. <code>observation</code> описывает факт, а не интерпретацию. <code>source</code> указывает лог, запрос, тестовый отчёт или подтверждение владельца. <code>status</code> различает гипотезу, наблюдение и внешне подтверждённый результат. <code>limit</code> показывает, чего материал не покрывает. <code>nextAction</code> задаёт обратимый шаг. Если одного поля нет, вывод нужно сузить.</p>\n<p>Учебный пример ниже использует только фиксированные значения в памяти. Имена, идентификаторы и статусы вымышлены. Пример не открывает URL, не читает исходный код, логи или секреты, не запускает сканер и не имитирует право на тест. Он показывает контракт записи и отрицательную ветку. Для живого объекта сначала получите отдельное разрешение и зафиксируйте его в scope.</p>\n<pre><code>const card = {\n scopeId: 'synthetic-asset-web-api',\n observation: 'synthetic-role-check-needs-owner-confirmation',\n source: 'synthetic-record-only',\n status: 'synthetic-not-externally-verified',\n limit: 'no-real-system-no-production-claim',\n nextAction: 'synthetic-owner-review-before-change'\n};\n\nconst accepted =\n card.status === 'synthetic-not-externally-verified' &&\n card.limit.includes('no-real-system');\n\n// accepted === true означает только корректную форму учебной записи.\n// status = 'confirmed' здесь должно быть отклонено.</code></pre>\n<p>Здесь результат <code>true</code> не означает, что найден контрольный дефект или подтверждена безопасность. Он означает только, что запись сохранила ограничение модели. Если заменить статус на <code>confirmed</code>, пример обязан остановиться: у него нет внешнего источника, разрешённой среды и воспроизводимого теста. Это отрицательный путь, а не декоративная оговорка. Он не даёт учебному коду сказать больше, чем он действительно знает.</p>\n<h2>Разрешение не следует из доступности ресурса</h2>\n<p>Веб-страница может быть доступна из интернета, но это не делает любое действие с ней допустимым. Перед активной проверкой нужны объект, среда, период, метод, ограничения нагрузки, запрещённые действия, контакт и условие остановки. Отдельно определите, как хранить и удалять полученные материалы. Если владелец не подтвердил границу, оставайтесь в режиме инвентаризации и обсуждения контракта.</p>\n<p>Файл <code>security.txt</code> помогает найти канал раскрытия, но не расширяет scope и не создаёт подразумеваемое разрешение на тест. Так же работают публичная документация, ссылка на программу поиска ошибок и доступность административной формы: это сведения о контакте или интерфейсе, а не согласование конкретного действия. Запишите их как источники контекста, не как поле authorization.</p>\n<p>Для безопасного read-only шага можно запросить стандартный файл раскрытия у своего или явно разрешённого домена:</p><pre><code>TARGET='https://example.org'\ncurl --fail --silent --show-error --location \\\n --max-time 10 \"$TARGET/.well-known/security.txt\" \\\n | sed -n '1,40p'</code></pre><p>Команда делает только GET и печатает первые 40 строк. Код 404 означает, что файл не найден по этому адресу или сервер вернул иной ответ; это не доказательство уязвимости и не повод расширять проверку. Наличие <code>security.txt</code> помогает найти контакт, но не превращается в разрешение на сканирование.</p><h2>Симптом → причина → проверка → действие</h2>\n<div class=\"table-scroll\"><table><caption>Диагностическая таблица для первой проверки</caption><thead><tr><th scope=\"col\">Симптом</th><th scope=\"col\">Причина</th><th scope=\"col\">Проверка</th><th scope=\"col\">Действие</th></tr></thead><tbody><tr><td>В отчёте есть finding, но нет asset ID</td><td>Домен выдали за scope</td><td>Построить путь сценария и назвать boundary</td><td>Перевести вывод в hypothesis до заполнения карты</td></tr><tr><td>Есть скриншот, но нет метода и версии</td><td>Материал отделили от условий наблюдения</td><td>Проверить источник, время, среду и повтор</td><td>Добавить limit или снять статус подтверждения</td></tr><tr><td>Ссылка на security.txt записана как permission</td><td>Канал связи смешали с authorization</td><td>Найти отдельную запись о владельце и допустимом методе</td><td>Остановить активную проверку до согласования</td></tr><tr><td>Высокий score требует «срочно чинить»</td><td>Оценку тяжести приняли за decision</td><td>Проверить exposure, owner, обратимость и критерий</td><td>Назначить triage и выбрать обратимый шаг</td></tr><tr><td>Интеграция не имеет владельца</td><td>Third-party boundary не вошла в карту</td><td>Запросить owner и контракт обмена данными</td><td>Зафиксировать evidence gap, не объявлять zero risk</td></tr></tbody></table></div>\n<h2>Порядок действий</h2>\n<ol><li>Выберите один ценный пользовательский сценарий и назовите его начало и конец.</li><li>Составьте карту активов: ID, граница, владелец, класс данных и вопрос проверки.</li><li>Разделите инвентаризацию и authorization. До активного действия запишите среду, окно, метод, запреты и stop condition.</li><li>Для каждого утверждения создайте evidence card с наблюдением, источником, версией, статусом и ограничением.</li><li>Проверьте отрицательные ветки: что происходит без владельца, без разрешения, без источника и при попытке расширить вывод.</li><li>Переведите пробелы в hypothesis или evidence gap. Не называйте их finding только потому, что формулировка звучит уверенно.</li><li>Назначьте обратимый следующий шаг и критерий закрытия. После проверки сохраните ссылку на результат и пересмотрите scope, если граница изменилась.</li></ol>\n<h2>Ограничения и путь возврата</h2>\n<p>Такая модель не обнаруживает уязвимости сама. Она не заменяет ручное тестирование, автоматические проверки, threat modeling, анализ кода или договор с владельцем внешней системы. Стандарт помогает выбрать язык и метод, но не создаёт evidence. Карта не покрывает автоматически скрытые сервисы. Один успешный сценарий не доказывает безопасность остальных ролей и состояний.</p>\n<p>Если новое наблюдение опровергло карточку, не стирайте историю. Верните статус в <code>hypothesis</code> или <code>evidence-gap</code>, сохраните причину пересмотра, уберите вывод из списка подтверждённых findings и назначьте владельца следующего запроса. Это и есть rollback документа. Для реального проекта отдельно определите хранение, доступ и удаление материалов; учебный пример этого не решает.</p>\n<p>Критерий готовности проверяем. Для выбранного сценария существует versioned scope record. Каждая граница имеет владельца. Каждое активное действие связано с отдельным authorization record. Каждое утверждение связано с источником, наблюдаемым фактом, версией и limit. Отрицательные ветки останавливают неподтверждённый вывод. Следующий шаг имеет owner, reversible action и criterion. Если хотя бы одного поля нет, аудит не завершён: результатом остаётся конкретный evidence gap, а не общий статус «проверено».</p>\n<h2>Проверяемые источники</h2>\n<ul><li><a href=\"https://csrc.nist.gov/pubs/sp/800/115/final\" target=\"_blank\" rel=\"noopener noreferrer\">NIST SP 800-115: Technical Guide to Information Security Testing and Assessment</a> — официальный документ о планировании, проведении, анализе и снижении рисков технических проверок. Он не задаёт scope конкретной системы и не даёт разрешение на тест.</li><li><a href=\"https://owasp.org/www-project-web-security-testing-guide/v42/\" target=\"_blank\" rel=\"noopener noreferrer\">OWASP Web Security Testing Guide v4.2</a> — официальное руководство с версиями и идентификаторами сценариев тестирования. Оно не подтверждает coverage или finding в конкретном проекте.</li><li><a href=\"https://www.rfc-editor.org/rfc/rfc9116.html\" target=\"_blank\" rel=\"noopener noreferrer\">RFC 9116: A File Format to Aid in Security Vulnerability Disclosure</a> — первичный источник о формате security.txt и границе между disclosure-контактом и разрешением на testing.</li></ul>"
}