АйТи Фреш
Главная / Статьи / Информационная безопасность
Информационная безопасность

Как я провожу аудит безопасности сайта небольшой компании: от границ проверки до повторного теста

Автор: Семёнов Евгений Сергеевич, директор ООО «АйТи-Фреш» · · ~15 мин чтения
Иллюстрация: аудит безопасности сайта находит открытую резервную копию и доступ к чужим документам за замком HTTPS
Замок HTTPS защищает дверь, но не открытые окна рядом с ней

Аудит безопасности сайта — это не прогон сканера, а четыре шага: согласовать границы, найти пути к данным и админке, вручную подтвердить риск и перепроверить исправление. Ниже мой порядок для компании до 50 мест: что проверять первым, как отделять угрозы от шума сканера и какие правки дают максимум.

С чего начинается аудит: границы проверки и резервная копия

Сайт открывается, заявки приходят, замок HTTPS горит — и руководитель считает вопрос закрытым. Я начинаю с неприятного уточнения: HTTPS защищает канал, но не спасает от старой CMS, чужих документов в личном кабинете, открытой админки или резервной копии в публичном каталоге. Поэтому аудит информационной безопасности сайта я никогда не начинаю со сканера. Сначала письменно фиксирую домены, IP-адреса, тестовые учётные записи, разрешённые действия и время работ.

Это не бюрократия. Активный сканер отправляет необычные запросы, перебирает параметры и может создавать записи в приложении. На небольшом сайте этого хватает, чтобы засыпать CRM тестовыми заявками, заблокировать пользователя или положить старый PHP-процесс. Проверка без согласованной области опасна даже для собственного сайта, если хостинг и CMS обслуживает подрядчик.

В область я включаю не только основной домен: поддомены, внешний IP, панели управления, API, личный кабинет, формы, интеграции с CRM и почтой, CDN, DNS, хранилище и процесс публикации. Отдельно отмечаю, где лежат персональные данные и у кого административный доступ. У малого бизнеса самая опасная точка часто не на главной странице, а на забытом тестовом поддомене, в старой панели phpMyAdmin или в архиве, который разработчик оставил рядом с сайтом.

До активных тестов делаю резервную копию и проверяю восстановление — именно проверяю, а не верю зелёной галочке в панели. Затем собираю пассивную картину: DNS-записи, сертификаты, HTTP-заголовки, технологии и открытые порты. Если сайт критичен для продаж, активное сканирование провожу на копии, максимально похожей на боевую, а на рабочем сервере подтверждаю только конкретные находки.

Забытые поддомены я ищу не перебором, а по журналам Certificate Transparency: каждый выпущенный публичный сертификат попадает в открытые логи, и поиск по домену на crt.sh за минуту показывает, какие имена когда-либо получали сертификат. В половине проектов там находится что-то вроде test, old или dev, о чём текущий администратор не знает. Второй источник — DNS-зона у регистратора: сверяю её с тем, что реально отвечает, и удаляю записи, которые указывают на чужие или освободившиеся адреса облачных провайдеров.

Не сканируйте IP провайдера, SaaS-интеграции и другие чужие системы без отдельного разрешения их владельца. Даже безобидный скан может нарушить договор и работу чужого сервиса.
Памятка: С чего начинается аудит: границы проверки и резервная копия — схема
Памятка: С чего начинается аудит: границы проверки и резервная копия. Открыть схему в полном размере

Что проверять первым: доступ, обновления и данные

Я начинаю не с HTTP-заголовков и не с красивого отчёта. Сначала ищу пути к административному доступу: слабые и повторно используемые пароли, отсутствие MFA, общие учётные записи, открытые панели, секреты в репозитории, сброс пароля через плохо защищённую почту. Затем сверяю версии CMS, плагинов, веб-сервера и ОС с бюллетенями производителей. Известная уязвимость в доступном из интернета компоненте — работа на сегодня, а не пункт квартального плана.

Следом разбираю функции, через которые идут данные: авторизацию, смену роли, загрузку файлов, поиск, формы, экспорт, API. Опираюсь на OWASP Web Security Testing Guide и OWASP Top 10:2025, где нарушение контроля доступа (Broken Access Control) по-прежнему на первом месте, категория A01. Но чек-лист не заменяет голову: нужно проверить, получит ли обычный пользователь чужой документ, если поменяет идентификатор в URL, и сверяет ли сервер принадлежность объекта. Автоматический сканер такую бизнес-логику понимает плохо — это хорошо видно и в нашем разборе, где мы нашли и устранили 47 уязвимостей в финтех-приложении: самые опасные находки там тоже были ручными.

Только после рисков захвата и утечки занимаюсь шифрами TLS, защитными заголовками и раскрытием версий. Они важны, но приоритет зависит от контекста. Отсутствующий X-Content-Type-Options я исправлю быстро, но не стану выдавать это за неминуемый взлом. Публичная резервная копия базы, пароль администратора без MFA или обход серверной проверки прав требуют реакции в тот же день.

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

Отдельно смотрю на людей и процессы вокруг сайта, потому что взламывают чаще через них, чем через код. Кто из сотрудников и подрядчиков имеет доступ к хостингу, регистратору домена и CMS, есть ли у каждого своя учётная запись, отзывался ли доступ у ушедшего разработчика. Учётка регистратора без MFA — это возможность увести домен целиком, и никакая настройка Nginx от этого не спасёт. Такие находки в отчёт идут наравне с техническими.

CVSS помогает сравнить техническую тяжесть, но не знает ваш бизнес. Для сайта с медицинскими или финансовыми данными утечка «средней» тяжести может оказаться самым дорогим пунктом отчёта.
Как я провожу аудит безопасности сайта небольшой компании: от границ проверки до повторного теста — схема
Схема к статье. Открыть схему в полном размере
Шкала приоритетов аудита безопасности сайта: от критичных находок к низким и сроки реакции
Сначала доступ и данные, заголовки — в плановом порядке

Инструменты: OWASP ZAP находит симптомы, человек доказывает риск

Для первого прохода я использую OWASP ZAP; на сентябрь 2026 года стабильная версия — 2.17.0, а дополнения к ней обновляются отдельно. Baseline Scan обходит сайт spider-ом и делает только пассивный анализ, без атак. Full Scan после обхода запускает активное сканирование и способен повлиять на приложение. Тег контейнера я фиксирую явно, чтобы результат можно было воспроизвести через месяц.

Осторожный пассивный запуск выглядит так. -t задаёт цель, -m ограничивает spider тремя минутами (по умолчанию одна), -r сохраняет HTML-отчёт. Каталог монтируется в /zap/wrk, и он должен быть доступен на запись пользователю внутри контейнера. Даже эту команду нельзя запускать против адреса вне согласованной области.

mkdir -p zap-report && chmod 777 zap-report
docker run --rm -t \
  -v "$(pwd)/zap-report:/zap/wrk/:rw" \
  ghcr.io/zaproxy/zaproxy:2.17.0 \
  zap-baseline.py -t https://example.com -m 3 -r baseline.html

После автоматики вручную прохожу ключевые сценарии через перехватывающий прокси: вход, восстановление пароля, просмотр и изменение объектов, загрузку, экспорт, выход. Проверяю cookies, CSRF-защиту, разграничение ролей и реакцию API на подмену идентификатора. Для набора ручных инструментов подойдёт и дистрибутив, который я описывал в обзоре инструментов пентеста в Kali Linux. Заголовки дополнительно проверяю в Mozilla HTTP Observatory, помня, что сам проект прямо пишет: он не ищет SQL-инъекции, уязвимые плагины и ошибки хранения паролей.

Сырую выгрузку сканера заказчику я не отдаю. Для каждой подтверждённой находки сохраняю запрос и ответ с вычищенными токенами и персональными данными, условия воспроизведения, адрес, возможное влияние и способ исправления. Ложные срабатывания помечаю отдельно. Разработчик получает нормальную задачу, директор — понятный риск вместо 180 страниц красных таблиц.

Full Scan я запускаю только на копии сайта, развёрнутой на отдельной машине с обезличенной базой. Разница в подготовке — пара часов, зато активные проверки не создадут в боевой CRM сотню фиктивных записей и не отправят клиентам письма из формы обратной связи. Если копию сделать нельзя, активные правила включаю выборочно и ограничиваю частоту запросов, а в согласованное окно рядом сидит человек заказчика, который видит журналы приложения.

Активный скан ZAP, перебор каталогов и проверка загрузки файлов могут менять данные и нагружать сервер. На рабочем сайте — только в согласованное окно и под наблюдением за журналами.

Разбор из практики: оздоровительный центр «Источник силы», 16 рабочих мест

Оздоровительный центр «Источник силы», 16 рабочих мест. Сайт с онлайн-записью и личным кабинетом, где клиенты скачивают PDF с индивидуальной программой и заключением специалиста по составу тела. Один виртуальный сервер: Ubuntu 22.04 LTS, Nginx 1.18.0 из репозитория дистрибутива, PHP 8.1-FPM, WordPress 6.4.3 и 14 плагинов, два из которых не обновлялись больше года. Сайт стоял за CDN-прокси, но origin-сервер отвечал напрямую по IP, админка WordPress была открыта всему интернету, MFA не было, а плагин резервного копирования складывал архивы в /wp-content/uploads/backup/.

Пассивная проверка заняла 40 минут и дала десятки предупреждений. Действительно важными оказались три: включённый листинг каталога копий, отсутствие HSTS и раскрытие версий в заголовках. В каталоге лежал архив на 540 МБ недельной давности с дампом базы и wp-config.php с паролем БД. К SSH пароль не подошёл, поэтому в отчёте я не писал, что сервер захвачен. Но в базе было 5 214 записей с именами, телефонами и e-mail, а заключения специалиста — это сведения о здоровье, особая категория персональных данных. Уровень — критический.

Ручная проверка личного кабинета нашла второй риск. Ссылка на PDF имела вид /download/?doc=1847, а сервер проверял только наличие сессии. Тестовый клиент менял номер и получал документы других клиентов. За 10 минут мы подтвердили доступ к 23 чужим файлам, остановили тест, сохранили минимальное доказательство и закрыли раздел на обслуживание. Классический IDOR — нарушение контроля доступа. Остальные 26 предупреждений сканера касались заголовков и версий и аварийных действий не требовали.

В первый же день удалили архивы из web-каталога, сменили пароль БД и ключи WordPress, закрыли firewall так, чтобы origin принимал HTTP(S) только от адресов CDN, включили MFA для трёх администраторов и временно отключили выдачу документов. За три дня разработчик добавил серверную проверку принадлежности документа и заменил последовательные номера на непрозрачные идентификаторы. Копии ушли в отдельное хранилище с отдельной учётной записью, плагины обновили после проверки на копии. Повторный тест утечку не воспроизвёл: из 29 пунктов остались четыре низких, принятые до планового релиза. Восстановление тестовой копии теперь занимает 34 минуты.

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

Если на сайте есть данные о здоровье, финансах или документах клиентов, ручная проверка доступа к объектам обязательна. Ни один автоматический сканер в этом кейсе IDOR не нашёл.
Цифры и версии: Разбор из практики: оздоровительный центр «Источник силы», 16 рабочих мест — схема
Цифры и версии: Разбор из практики: оздоровительный центр «Источник силы», 16 рабочих мест. Открыть схему в полном размере
Цифры кейса аудита сайта: публичный архив, IDOR в личном кабинете, сроки исправления
Две ручные находки весили больше, чем 26 предупреждений сканера

Исправления в Nginx: заголовки, HSTS и CSP без слепого копирования

HSTS включаю только после проверки, что сайт стабильно работает по HTTPS. Параметр always у add_header добавляет заголовок независимо от кода ответа. includeSubDomains опасен, если где-то остался HTTP-поддомен, поэтому сначала ставлю небольшой max-age, наблюдаю, затем увеличиваю срок. Включение домена в preload-список — отдельное решение: быстро отменить его не получится.

Ниже базовый фрагмент для Nginx 1.18.0 со стенда. CSP сначала включаю в режиме Content-Security-Policy-Report-Only, собираю нарушения и лишь затем перевожу в блокирующий режим: иначе старые виджеты, карты, аналитика и inline-скрипты перестают работать. Отдельно закрываю служебные файлы и архивы.

server {
    listen 443 ssl http2;
    server_name example.com;
    autoindex off;

    add_header Strict-Transport-Security "max-age=86400" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
    add_header Content-Security-Policy-Report-Only "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; report-uri /csp-reports" always;

    location ~ /\.(git|env|ht) { deny all; }
    location ~* \.(sql|bak|zip|tar|gz|7z)$ { deny all; }
}

Важная ловушка: если в каком-то location появится свой add_header, заголовки уровня server в нём перестанут отдаваться — директива наследуется только при отсутствии собственных. Как это обходить, я разбирал в статье про наследование add_header в nginx. Для cookies сессии требую Secure, HttpOnly и подходящий SameSite; выбор между Lax, Strict и None зависит от входа через внешнего провайдера. Загрузки храню вне исполняемого каталога, переименовываю на сервере, ограничиваю размер и проверяю формат по содержимому, а не по расширению.

После каждой правки конфигурации порядок один: nginx -t, затем systemctl reload nginx, затем проверка снаружи командой curl -sI https://example.com/ | grep -iE 'strict-transport|content-security|x-content-type' — и та же проверка для страницы ошибки 404 и для файла из uploads. Именно на них чаще всего выясняется, что заголовки отдаются не везде. Отчёты CSP в режиме Report-Only я собираю одну-две недели: за это время проявляются и виджет онлайн-записи, и счётчик аналитики, и чат поддержки, которые надо внести в политику до перевода в блокирующий режим.

На что можно не тратить первые часы: скрытие каждого баннера версии, погоня за максимальной оценкой внешнего сервиса, запрет всех редких методов HTTP без понимания приложения. Это делается планово. Более широкий список мер для корпоративного сайта — HTTPS, обновления, отделение сайта от внутренней сети, бэкапы, защита от ботов — я собрал в чек-листе безопасности корпоративного сайта.

Не копируйте CSP и HSTS вслепую. Ошибка в CSP ломает формы, аналитику и внешнюю авторизацию, а длинный HSTS с includeSubDomains может сделать недоступным старый HTTP-поддомен.

Что руководитель должен получить после аудита

Хороший итог аудита — не сертификат «сайт безопасен», такой гарантии не существует. Я отдаю реестр активов, перечень подтверждённых находок, доказательства без чувствительных данных, оценку влияния на бизнес, конкретные исправления, ответственных и сроки. Отдельно перечисляю ограничения: что не проверялось, где не было исходного кода или тестовой роли, какие действия запретил владелец. Без этого отчёт создаёт ложную уверенность.

Для компании до 50 рабочих мест выбираю простой ритм: пассивная автоматическая проверка после заметного релиза, ежемесячный контроль обновлений и внешней поверхности, ежеквартальное восстановление копии и ручной аудит критичных сценариев не реже раза в год. После серьёзной переделки авторизации, API, загрузки файлов или оплаты ждать ежегодного аудита нельзя — проверка нужна до публикации.

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

Мой вывод простой: малому бизнесу не нужен бесконечный пентест. Нужны инвентаризация, дисциплина обновлений, MFA, непубличные копии, серверная проверка прав и несколько часов внимательного ручного тестирования там, где лежат данные и деньги. Эти действия снимают основную часть реального риска.

Если подрядчик принёс только выгрузку сканера без ручного подтверждения, оценки влияния и повторной проверки, это ещё не аудит, а сырьё для него.
Памятка: Что руководитель должен получить после аудита — схема
Памятка: Что руководитель должен получить после аудита. Открыть схему в полном размере
Схема цикла аудита безопасности сайта: границы, сканер, ручная проверка, исправления, повторный тест
Аудит замыкается повторной проверкой, а не отчётом сканера

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

Можно ли провести аудит безопасности сайта самостоятельно?

Базовую часть — да: инвентаризация, обновления, MFA, поиск публичных копий, заголовки и пассивный ZAP Baseline. Ручную проверку авторизации, API и бизнес-логики лучше доверить специалисту, который подтвердит риск и не повредит данные.

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

Сканер находит технические признаки и известные шаблоны. Аудит добавляет согласованные границы, ручную проверку ролей и бизнес-логики, оценку влияния, приоритеты исправлений и повторный тест.

Опасно ли сканировать рабочий сайт?

Пассивная проверка сравнительно безопасна, хотя spider тоже создаёт нагрузку. Активное сканирование способно менять данные. Нужны резервная копия, окно работ, лимит запросов и план остановки.

Достаточно ли HTTPS и высокой оценки Observatory?

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

Как часто повторять аудит сайта?

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

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

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

📞 +7 903 729-62-41 💬 MAX: +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи