8 lines
18 KiB
JSON
8 lines
18 KiB
JSON
{
|
||
"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>"
|
||
}
|