Разбираем изменения в OWASP Top 10 версии 2025 года на примерах и рассматриваем, как SAST может помочь избежать уязвимостей.

OWASP Top 10 — это список десяти наиболее опасных угроз безопасности веб-приложений. Он служит ориентиром для разработчиков, архитекторов и специалистов по информационной безопасности, помогая сосредоточиться на самых критических рисках при создании веб-приложений.
С момента выхода предыдущей версии списка в 2021 году ландшафт угроз существенно изменился, и в 2025 году OWASP представил его обновлённую редакцию: OWASP Top 10:2025.
В этой статье мы рассмотрим новые категории уязвимостей из обновлённого списка и покажем, как некоторые из этих угроз можно выявить с помощью статического анализатора PVS-Studio. Для OWASP, кстати, у нас есть отдельная категория диагностических правил. Подробнее об этом можно прочитать в нашей документации.
О предыдущей версии OWASP Top 10 (2021) мы уже писали — ознакомиться со статьёй можно по этой ссылке.
Что поменялось?
Как и было сказано ранее, OWASP Top 10 обновляется не только ради новизны — изменения в списке отражают эволюцию реальных угроз. По сравнению с версией 2021 года новый перечень не только сохранил большинство категорий, но также существенно переработал их приоритеты и внёс две новые: A03:2025 Software Supply Chain Failures и A10:2025 Mishandling of Exceptional Conditions.
Кроме того, некоторые формулировки были уточнены для лучшего соответствия современным практикам. Например, акцент в логировании сместился с пассивной записи событий на необходимость оперативного оповещения и реагирования, а фокус на аутентификации стал более точным.
A01: Broken Access Control
Данная категория объединяет в себе уязвимости, приводящие к несанкционированному раскрытию информации, изменению или уничтожению всех данных или выполнению бизнес-функций за пределами полномочий пользователя.
В OWASP Top 10:2025 эта категория дополнительно включает риски, ранее выделенные как Server-Side Request Forgery (SSRF) — в предыдущей версии (2021) SSRF занимала отдельную позицию A10. Такое объединение подчёркивает общую природу этих угроз: неконтролируемый доступ к ресурсам, будь то внутренние файлы, сетевые сервисы или данные других пользователей.
Broken Access Control по-прежнему остаётся на первом месте, что подтверждает: ошибки контроля доступа — одна из самых критичных и распространённых проблем в современных веб-приложениях.
Например, вот такой фрагмент кода из проекта Power-Fx:
public static void Check(Engine engine, string pathInput) { EngineSchema schema; if (pathInput != null) { var json = File.ReadAllText(pathInput); schema = JsonSerializer.Deserialize<EngineSchema>(json); } .... }
Предупреждение PVS-Studio: V5609 Possible path traversal vulnerability. Potentially tainted data from the 'pathInput' variable is used as path.
Здесь путь к файлу передаётся напрямую от пользователя через параметр pathInput, проходит только проверку на null и сразу используется для чтения файла. Это классическая path traversal-уязвимость: злоумышленник может передать значение вроде ../../../etc/passwd и получить несанкционированный доступ к произвольным файлам на сервере.
Проблемы Broken Access Control не ограничиваются только файловой системой. Они также возникают, например, и на уровне логики авторизации.
Так, в Spring метод vote из AccessDecisionVoter можно реализовать следующим образом:
@Override public int vote(Authentication authentication, FilterInvocation filterInvocation, Collection<ConfigAttribute> attributes) { boolean isAdmin = hasAdminRole(authentication); String requestMethod = filterInvocation.getRequest().getMethod(); if ("DELETE".equals(requestMethod) && !isAdmin) { return ACCESS_GRANTED; } return ACCESS_GRANTED; }
Здесь метод всегда возвращает ACCESS_GRANTED, включая случаи, когда обычный пользователь пытается выполнить привилегированную операцию, что является прямым нарушением принципа минимальных привилегий.
На подобную ошибку в коде анализатор PVS-Studio выдал бы срабатывание диагностического правила V5328 Using non-restrictive authorization checks could lead to security violations.
Полный список CWE из категории A01:2025 Broken Access Control
CWE-22 Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
CWE-59 Improper Link Resolution Before File Access ('Link Following')
CWE-200 Exposure of Sensitive Information to an Unauthorized Actor
CWE-359 Exposure of Private Personal Information to an Unauthorized Actor
CWE-379 Creation of Temporary File in Directory with Insecure Permissions
CWE-402 Transmission of Private Resources into a New Sphere ('Resource Leak')
CWE-441 Unintended Proxy or Intermediary ('Confused Deputy')
CWE-497 Exposure of Sensitive System Information to an Unauthorized Control Sphere
CWE-538 Insertion of Sensitive Information into Externally-Accessible File or Directory
CWE-566 Authorization Bypass Through User-Controlled SQL Primary Key
CWE-615 Inclusion of Sensitive Information in Source Code Comments
CWE-732 Incorrect Permission Assignment for Critical Resource
A02 Security Misconfiguration
Эта категория объединяет уязвимости, связанные с небезопасной конфигурацией: включение лишних портов или служб, небезопасная настройка, использование данных извне для определения системных свойств и т.д.
С момента предыдущей версии категория поднялась с 5 на 2 место в списке. Это сигнал о том, что даже небольшие ошибки в конфигурации всё чаще становятся точкой входа для атак на приложения.
С конфигурацией, например, может произойти проблема из-за пришедших извне данных.
public void ExecuteSqlQuery(....) { .... string catalog = Request.QueryString["catalog"]; using (SqlConnection dbConnection = IO.GetDBConnection()) { dbConnection.ConnectionString = $"Data Source=....; " + $"Initial Catalog={catalog}; " + $"User ID=....; " + $"Password=....;"; .... } .... }
В данном примере формируется строка для подключения к базе данных. В параметр Initial Catalog записываются данные, не прошедшие предварительно никакой валидации, из-за чего злоумышленник может передать любое название каталога и получить информацию, доступ к которой не был предусмотрен.
Исправить подобную ситуацию мы могли бы проверкой приходящих от пользователя данных:
public void ExecuteSqlQuery(...., HashSet<string> validCatalogNames) { .... string catalog = Request.QueryString["catalog"]; if(!validCatalogNames.Contains(catalog)) return; using(SqlConnection dbConnection = IO.GetDBConnection()) { dbConnection.ConnectionString = $"Data Source=....; " + $"Initial Catalog={catalog}; " + $"User ID=....; " + $"Password=....;"; .... } .... }
Здесь перед использованием полученного значения мы проверяем, что catalog содержится в коллекции validCatalogNames. Таким образом, мы разрешим пользователю доступ к ограниченному перечню каталогов.
Подобные дефекты находятся анализатором PVS-Studio с помощью диагностического правила V5624 Use of potentially tainted data in configuration may lead to security issues.
Также из-за проблем с конфигурацией может возникнуть риск XXE-атаки. Например, XML-парсер, получающий данные из внешнего источника, может быть сконфигурирован небезопасно.
Возьмём для примера вот такой формат XML-файла, с которым приложение должно работать:
<?xml version="1.0" encoding="utf-8" ?> <shop> <itemID>62</itemID> </shop>
Допустим, обработкой занимается следующий код:
public static void processItemWithID(String pathToXmlFile) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); var document = builder.parse(pathToXmlFile); // <= var nodeList = document.getElementsByTagName("itemID"); String itemiD = nodeList.item(0).getTextContent(); try { long itemIDvalue = Long.parseLong(itemiD); // process the item with 'itemIDvalue' value System.out.printf("An item with the %d ID was processed.%n", itemIDvalue); } catch (NumberFormatException e) { System.out.printf("%s is not valid 'itemID' value.%n", itemiD); } }
Для приведённого выше XML-файла приложение выведет вот такую строку:
An item with the '62' ID was processed.
Если же мы попытаемся использовать непредусмотренное значение для поля ID, приложение сообщит об ошибке:
"Hello world" is not valid 'itemID' value.
Хоть код и выполняет поставленную перед ним задачу, он уязвим к XXE-атакам из-за того, что:
содержимое XML поступает от пользователя;
XML-парсер сконфигурирован так, чтобы обрабатывать внешние сущности;
вывод может передаваться обратно пользователю.
Чтобы скомпрометировать данный код, злоумышленник может воспользоваться, например, вот таким XML-файлом:
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file://D:/MySecrets.txt"> ]> <shop> <itemID>&xxe;</itemID> </shop>
В этом файле объявляется внешняя сущность xxe, которая будет обработана парсером. В итоге содержимое файла D:/MySecrets.txt (например, This is an XXE attack target.), находящегося на машине, где запущено приложение, будет выдано пользователю:
This is an XXE attack target. is not valid 'itemID' value.
Для того, чтобы обезопаситься от подобной атаки, можно запретить обработку внешних сущностей, а также игнорировать обработку DTD. Для примера выше мы бы сделали это так:
String feature = "http://apache.org/xml/features/disallow-doctype-decl"; factory.setFeature(feature, true);
Подобные дефекты безопасности выявляются анализатором PVS-Studio с помощью диагностического правила V5335 Potential XXE vulnerability. Insecure XML parser is used to process potentially tainted data.
Полный список CWE из категории A02:2025 Security Misconfiguration
CWE-5 J2EE Misconfiguration: Data Transmission Without Encryption
CWE-13 ASP.NET Misconfiguration: Password in Configuration File
CWE-315 Cleartext Storage of Sensitive Information in a Cookie
CWE-526 Exposure of Sensitive Information Through Environmental Variables
CWE-611 Improper Restriction of XML External Entity Reference
CWE-614 Sensitive Cookie in HTTPS Session Without 'Secure' Attribute
CWE-776 Improper Restriction of Recursive Entity References in DTDs ('XML Entity Expansion')
CWE-942 Permissive Cross-domain Policy with Untrusted Domains
CWE-1174 ASP.NET Misconfiguration: Improper Model Validation
A03 Software Supply Chain Failures
В OWASP Top 10 2025 прежняя категория Vulnerable and Outdated Components (A06:2021) эволюционировала в A03:2025 – Software Supply Chain Failures. Это изменение подчёркивает, что угрозы больше не ограничиваются использованием устаревших библиотек: сегодня злоумыш��енники атакуют всю цепочку поставок — от репозиториев кода и CI/CD-пайплайнов до финальных артефактов развёртывания.
Список CWE данной категории, однако, всё ещё почти полностью состоит из проблем с используемыми компонентами:
использование устаревшей функции (CWE-477);
использование компонентов с известными уязвимостями (CWE-1035);
использование неподдерживаемых сторонних компонентов (CWE-1104);
использование компонента, который невозможно обновить (CWE-1329);
использование недостаточно надёжного компонента (CWE-1357);
зависимость от уязвимого стороннего компонента (CWE-1395).
PVS-Studio умеет искать уязвимые компоненты в C#-проектах с помощью правила V5625 Referenced package contains vulnerability. Оно использует механизм SCA и проверяет, что задействованные в проекте зависимости не имеют известных уязвимостей.
A04 Cryptographic Failures
Эта категория объединяет группу уязвимостей, связанных с некорректным шифрованием конфиденциальных данных: использование устаревших криптографических алгоритмов или хеш-функций, передача информации в незашифрованном виде и т.д.
По сравнению с предыдущей версией эта категория опустилась со второй позиции на четвёртую.
К ней относятся ошибки, связанные с использованием устаревших алгоритмов шифрования или хеширования. Например, в нашем инструменте есть правило V5314 Use of an outdated hash algorithm is not recommended.
Вот пример срабатывания этого правила из проекта DBeaver:
private boolean checkLockPassword() { BaseAuthDialog dialog = new BaseAuthDialog(....); if (dialog.open() == IDialogConstants.OK_ID) { final String userPassword = dialog.getUserPassword(); if (!CommonUtils.isEmpty(userPassword)) { try { final byte[] md5hash = MessageDigest.getInstance("MD5") // <= .digest(userPassword.getBytes(....)); final String hexString = CommonUtils.toHexString(md5hash) .toLowerCase(Locale.ENGLISH) .trim(); if (hexString.equals(dataSource.getLockPasswordHash())) { return true; } UIUtils.showMessageBox(....); } catch (Throwable e) { DBWorkbench.getPlatformUI().showError(....); } } } return false; }
Предупреждение PVS-Studio: V5314. Use of the 'MD5' hash algorithm is not recommended. Such code may cause the exposure of sensitive data.
Здесь анализатор указывает на то, что алгоритм шифрования MD5 является устаревшим.
Но также есть и другие подозрительные моменты, относящиеся к криптографии, которые могут привести к уязвимости приложения. Например, как во фрагменте из того же DBeaver:
public static String generateNewId(DBPDriver driver) { long rnd = new Random().nextLong(); // <= if (rnd < 0) rnd = -rnd; return driver.getId() + "-" + Long.toHexString(System.currentTimeMillis()) + "-" + Long.toHexString(rnd); }
Предупреждение PVS-Studio: V5307. Potentially predictable seed is used in pseudo-random number generator.
Здесь проблема в том, что мы каждый раз создаём новый экземпляр класса Random, из-за чего, в зависимости от JDK, получаемые числа будут недостаточно случайными. Чтобы это исправить, мы могли бы вынести создание экземпляра Random на уровень класса и при необходимости использовать один и тот же объект.
Полный список CWE из категории A04:2025 Cryptographic Failures
CWE-296 Improper Following of a Certificate's Chain of Trust
CWE-335 Incorrect Usage of Seeds in Pseudo-Random Number Generator(PRNG)
CWE-337 Predictable Seed in Pseudo-Random Number Generator (PRNG)
CWE-338 Use of Cryptographically Weak Pseudo-Random Number Generator(PRNG)
CWE-757 Selection of Less-Secure Algorithm During Negotiation('Algorithm Downgrade')
CWE-916 Use of Password Hash With Insufficient Computational Effort
CWE-1240 Use of a Cryptographic Primitive with a Risky Implementation
CWE-1241 Use of Predictable Algorithm in Random Number Generator
A05 Injection
Injection — уязвимости, которые возникают из-за попадания ненадёжных данных в критические точки приложения (например, при выполнении SQL-запроса). Такие данные заставляют программу вести себя не так, как планировалось изначально. Как следствие, возможна порча конфиденциальных данных, их обнародование или остановка выполнения программы.
По сравнению с предыдущей версией данная категория опустилась с A3 до A5. Причём Injection в новой версии перечня всё также занимает место между Cryptographic Failures и Insecure Design (см. ниже). Данная категория, вероятнее всего, заняла позицию ниже в силу более обширного тестирования приложений с помощью различных инструментов. Сегодня ни один серьёзный проект не обходится без проверок на инъекции.
Конкретно в нашем инструменте правил, обнаруживающих дефекты, относящиеся к данной категории, довольно много. Обширный список различных инъекций хорошо ищется с помощью инструментов статического анализа:
Argument injection – V5311 (Java);
Reflection injection – V5322 (Java);
Cookie inkection – V5630 (C#).
Для примера посмотрим на то, как выглядит Cookie injection:
public void ChangeCookie() { String cookieValue = Request.Form["userRole"]; Response.Cookies.Add( new HttpCookie(WebLocalizationConfiguration.CookieName, cookieValue) { Expires = Clock.Now.AddYears(2), Path = Request.ApplicationPath } ); .... }
В HttpResponse добавляется новый объект класса HttpCookie, который инициализируется на основе данных из внешнего источника — формы (Request.Form). Использование данных без какой-либо проверки или валидации может привести к тому, что злоумышленники смогут повлиять на работу приложения.
Исправить ситуацию можно было бы, например, вот такой проверкой:
.... String cookieValue = Request.Form["userRole"]; if (!Regex.IsMatch(cookieValue, DataValidationPattern)) return; ....
Полный список CWE из категории A05:2025 Injection
CWE-76 Improper Neutralization of Equivalent Special Elements
CWE-77 Improper Neutralization of Special Elements used in a Command ('Command Injection')
CWE-78 Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
CWE-79 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
CWE-80 Improper Neutralization of Script-Related HTML Tags in a Web Page (Basic XSS)
CWE-83 Improper Neutralization of Script in Attributes in a Web Page
CWE-86 Improper Neutralization of Invalid Characters in Identifiers in Web Pages
CWE-88 Improper Neutralization of Argument Delimiters in a Command ('Argument Injection')
CWE-89 Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
CWE-90 Improper Neutralization of Special Elements used in an LDAP Query ('LDAP Injection')
CWE-93 Improper Neutralization of CRLF Sequences ('CRLF Injection')
CWE-94 Improper Control of Generation of Code ('Code Injection')
CWE-95 Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')
CWE-96 Improper Neutralization of Directives in Statically Saved Code ('Static Code Injection')
CWE-97 Improper Neutralization of Server-Side Includes (SSI) Within a Web Page
CWE-99 Improper Control of Resource Identifiers ('Resource Injection')
CWE-113 Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Response Splitting')
CWE-159 Improper Handling of Invalid Use of Special Elements
CWE-470 Use of Externally-Controlled Input to Select Classes or Code ('Unsafe Reflection')
CWE-610 Externally Controlled Reference to a Resource in Another Sphere
CWE-643 Improper Neutralization of Data within XPath Expressions ('XPath Injection')
CWE-644 Improper Neutralization of HTTP Headers for Scripting Syntax
A06 Insecure Design
Insecure Design — это категория, посвящённая уязвимостям, которые закладываются ещё до написания первой строки кода. Речь идёт о недостатках в архитектуре и проектировании приложения: отсутствии моделирования угроз, игнорировании принципов безопасного проектирования (security-by-design), слабой бизнес-логике или отсутствии контроля целостности критических операций.
В отличие от ошибок реализации, которые можно исправить рефакторингом или патчами, архитектурные недостатки невозможно устранить, не перепроектировав систему. Даже безупречно написанный код, основанный на изначально небезопасной архитектуре, будет оставаться уязвимым.
Категория Insecure Design впервые появилась в OWASP Top 10 в 2021 году под номером A04 и в 2025 году переместилась на позицию A06. Это не означает, что проблема стала менее актуальной — скорее, другие риски (например, связанные с цепочками поставок или обработкой исключений) вышли на передний план.
Хотя статический анализ не может напрямую увидеть отсутствие threat modeling, он способен выявлять симптомы небезопасного дизайна.
Предположим, в банковском приложении реализована функция перевода средств следующим образом:
public void transferMoney( String fromAccountId, String toAccountId, BigDecimal amount ) { Account from = accountRepository.findById(fromAccountId); Account to = accountRepository.findById(toAccountId); from.debit(amount); to.credit(amount); }
На первый взгляд — всё логично. Но где проверка:
Достаточно ли средств на счёте?
Не заблокирован ли аккаунт?
Имеет ли текущий пользователь право переводить с этого счёта?
Не является ли это повторным выполнением уже обработанного запроса?
Такая архитектура изначально не предусматривает защиту от мошенничества, перерасхода или CSRF-подобных атак. Это — классический случай Insecure Design.
PVS-Studio может помочь выявить некоторые проявления таких проблем дизайна, но напрямую указать на то, что приложение неверно спроектировано, к сожалению, статический анализ не в силах.
Полный список CWE из категории A06:2025 Insecure Design
CWE-316 Cleartext Storage of Sensitive Information in Memory
CWE-362 Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')
CWE-444 Inconsistent Interpretation of HTTP Requests ('HTTP Request Smuggling')
CWE-451 User Interface (UI) Misrepresentation of Critical Information
CWE-454 External Initialization of Trusted Variables or Data Stores
CWE-525 Use of Web Browser Cache Containing Sensitive Information
CWE-539 Use of Persistent Cookies Containing Sensitive Information
CWE-598 Use of GET Request Method With Sensitive Query Strings
CWE-646 Reliance on File Name or Extension of Externally-Supplied File
CWE-1021 Improper Restriction of Rendered UI Layers or Frames
CWE-1022 Use of Web Link to Untrusted Target with window.opener Access
A07 Authentication Failures
Это группа уязвимостей, связанных с ошибками в управлении сеансами или аутентификацией пользователей. Обычно подобные уязвимости способны привести к компрометации паролей, ключей безопасности или токенов сеанса, также они позволяют злоумышленнику присвоить себе идентификационные данные.
В предыдущей версии OWASP Top 10 данная категория называлась Identification and Authentication Failures и находилась на той же 7 позиции. В этой версии, как вы могли заметить, название сместилось в сторону непосредственно аутентификации, чтобы более точно соответствовать списку CWE для этой категории.
В качестве примера дефекта, относящегося к данной категории, можно привести вот такую абстрактную ситуацию:
public static void main(String[] arg) { .... JSch jsch = new JSch(); Session session = jsch.getSession(user, host, 22); session.setPassword("123fj"); .... }
"А действительно, почему бы нам не сохранить пароль прямо в коде?.. В смысле, его оттуда легко получить?.. А почему вдруг я несу ответственность за то, что кто-то это заэксплойтит?.."
Чтобы не слушать таких вопросов, просто используйте хранилища, в которых данные будут храниться в зашифрованном виде. Ну и про разграничение доступа для таких хранилищ забывать нельзя. Обычный пользователь не должен иметь возможности туда как-либо попасть.
public static void main(String[] arg) { .... JSch jsch = new JSch(); Session session = jsch.getSession(user, host, 22); session.setPassword(dataStorage.getPassword); .... }
Подобные ошибки выявляются анализатором PVS-Studio с помощью диагностического правила V5305 Storing credentials inside source code can lead to security issues, а для C#-проектов есть аналогичное V5601.
Полный список CWE из категории A07:2025 Authentication Failures
CWE-288 Authentication Bypass Using an Alternate Path or Channel
CWE-297 Improper Validation of Certificate with Host Mismatch
CWE-298 Improper Validation of Certificate with Host Mismatch
CWE-299 Improper Validation of Certificate with Host Mismatch
CWE-303 Incorrect Implementation of Authentication Algorithm
CWE-307 Improper Restriction of Excessive Authentication Attempts
CWE-350 Reliance on Reverse DNS Resolution for a Security-Critical Action
CWE-640 Weak Password Recovery Mechanism for Forgotten Password
CWE-940 Improper Verification of Source of a Communication Channel
CWE-941 Incorrectly Specified Destination in a Communication Channel
A08 Software or Data Integrity Failures
Software or Data Integrity Failures — группа уязвимостей, приводящих к нарушению целостности программного обеспечения. Обновления без цифровой подписи, небезопасная десериализация, загрузка зависимостей из небезопасных репозиториев и т.д.
Эта категория, так же как и предыдущая, не изменила своей позиции в списке, а чуть изменила название с Software and Data Integrity Failures для большей ясности.
Возьмём для примера случай небезопасной десериализации.
У атак, осуществляемых через десериализацию данных извне, могут быть различные цели и варианты реализации. Например, злоумышленник может подменить данные в десериализуемом объекте, что может привести к несанкционированному увеличению прав доступа или присвоению невалидного значения какому-либо полю объекта.
Лучший способ избежать подобных ситуаций — не давать пользователям возможности отправлять приложению данные для сериализации. Но если всё-таки появилась такая необходимость, то стоит использовать безопасные библиотеки для сериализации/десериализации, а также контролировать приходящие извне данные.
Возьмём такую конфигурацию:
public void notSecure(HttpServletRequest req, HttpServletResponse res) throws .... { ServletInputStream servletIS = req.getInputStream(); ObjectInputStream objectIS = new ObjectInputStream(servletIS); // <= Object object = objectIS.readObject(); }
Она не очень безопасна. А вот такой код уже сильно лучше:
class SecureObjectInputStream extends ObjectInputStream { public SecureObjectInputStream(InputStream in) throws IOException { super(in); } @Override protected Class<?> resolveClass(ObjectStreamClass osc) throws .... { List<String> allowedClasses = new ArrayList<>(); allowedClasses.add(AllowedClass1.class.getName()); allowedClasses.add(AllowedClass2.class.getName()); if (!allowedClasses.contains(osc.getName())) { throw new InvalidClassException("Unauthorized deserialization", osc.getName()); } return super.resolveClass(osc); } } .... public void withCheck(HttpServletRequest req, HttpServletResponse res) throws .... { ServletInputStream servletIS = req.getInputStream(); ObjectInputStream objectIS = new SecureObjectInputStream(servletIS); Object object = objectIS.readObject(); }
В этом варианте создан класс SecureObjectInputStream, который является наследником ObjectInputStream. В нём мы переопределили метод resolveClass, что позволяет проверить, какого типа объект мы собираемся десериализовать. Описанное в методе поведение позволит нам не допустить десериализацию небезопасного объекта.
Подобные дефекты выявляются анализатором PVS-Studio с помощью диагностического правила V5333 Possible insecure deserialization vulnerability. Potentially tainted data is used to create an object during deserialization, а для C# проектов есть аналогичное V5611.
Полный список CWE из категории A08:2025 Software or Data Integrity Failures
CWE-565 Reliance on Cookies without Validation and Integrity Checking
CWE-784 Reliance on Cookies without Validation and Integrity Checking in a Security Decision
CWE-829 Inclusion of Functionality from Untrusted Control Sphere
CWE-830 Inclusion of Web Functionality from an Untrusted Source
CWE-915 Improperly Controlled Modification of Dynamically-Determined Object Attributes
A09 Security Logging & Alerting Failures
Эта категория объединяет недостатки в системах аудита, мониторинга и оповещения, которые затрудняют обнаружение, расследование инцидентов безопасности и реагирование на них. В отличие от предыдущей версии OWASP Top 10 (2021), где речь шла о Security Logging and Monitoring Failures, в 2025 году акцент сместился с пассивной записи событий на активное оповещение и реагирование — отсюда и изменение названия на "Alerting".
Проблема не в том, что логи не пишутся, а в том, что:
критические события (например, множественные неудачные попытки входа, доступ к защищённым ресурсам без прав, подозрительные транзакции) не фиксируются вообще;
логи недостаточно детализированы (нет IP-адреса, user agent, идентификатора сессии);
или, что ещё хуже, никто не получает уведомления при возникновении аномалий — система "молчит", пока не станет слишком поздно.
Статический анализатор, конечно, не настроит логирование в вашем проекте, но есть некоторые ситуации, когда PVS-Studio может помочь вам и с этой категорией — как минимум, с сохранением целостности логов.
Например, в какой-то ситуации нам необходимо залогировать пользовательский ввод, но делаем мы это без предварительной проверки данных:
public class InputHelper { private final Logger logger = LoggerFactory.getLogger(InputHelper.class); private String username; public void process(InputStream stream) { Scanner scanner = new Scanner(stream); String userInput = scanner.next(); String logMessage = "User '" + userName + "' entered value: '" + userInput + "'."; logger.info(logMessage); // <= } }
В таком случае злоумышленник может внедрить произвольные данные о событиях, которые никогда не происходили, и ввести человека, анализирующего логи, в заблуждение. Например, злоумышленник введёт такое значение:
2022/r/nINFO: User 'Admin' logged out.
Тогда в логах мы увидим вот такой результат:
INFO: User 'SomeUser' entered value: '2022'. INFO: User 'Admin' logged out.
Обнаружить подобные ситуации поможет правило V5319 Possible log injection. Potentially tainted data is written into logs или аналогичное для C#-проектов V5619.
Полный список CWE из категории A09:2025 Security Logging & Alerting Failures
A10 Mishandling of Exceptional Conditions
Ну и на десерт ещё одна абсолютно новая категория в OWASP Top 10 версии 2025 года. Впервые в истории OWASP Top 10 внимание уделяется не только тому, что код делает, но ещё и тому, что происходит, если он ломается. Ситуации, когда приложение либо игнорирует ошибки, либо реагирует на них созданием новых уязвимостей, вполне себе распространены.
Подобные дефекты могут приводить к:
утечке конфиденциальной информации (например, стектрейсы в ответе пользователю);
отказу в обслуживании (неперехваченные исключения завершают поток или процесс);
обходу защитных механизмов (ошибка в проверке и переход к следующему шагу без авторизации);
потере контекста инцидента (проглатывание исключений без логирования).
Статический анализ довольно эффективен в выявлении таких проблем, потому что многие из них проявляются как антипаттерны в коде.
Например, простейший случай:
.... try { authService.authenticate(user, password); } catch (AuthenticationException e) {} ....
Казалось бы, просто не обработали Exception, но из-за такого случая, например, может произойти ситуация, когда пользователь внезапно оказывается авторизованным по умолчанию.
Также неприятной была бы ситуация, когда мы перетираем одно исключение с помощью другого:
.... try { processPayment(); } catch (Exception e) { throw new RuntimeException("Payment failed"); } ....
В таком случае мы теряем стек исходного исключения, что мешает нам обнаружить источник проблемы.
Тема исключений настолько обширна, что иногда даже смешно от того, какие ошибки можно допустить. Например, вот такой фрагмент из проекта Apache NiFi:
public void finishTransferFlowFiles( final CommunicationsSession commSession ) throws IOException { if (postResult == null) { new IllegalStateException(....); } .... }
Предупреждение PVS-Studio: V5303 The object was created but it is not being used. The 'throw' keyword could be missing.
Мы обработали определённую ситуацию, когда postResult будет равен null, и даже создали нужное нам IllegalStateException. Одна проблема — мы забыли его бросить :).
В общем, новая категория — кладезь различных интересностей, которые вам поможет найти статический анализатор, например, PVS-Studio.
Полный список CWE из категории A10:2025 Mishandling of Exceptional Conditions
CWE-209 Generation of Error Message Containing Sensitive Information
CWE-215 Insertion of Sensitive Information Into Debugging Code
CWE-280 Improper Handling of Insufficient Permissions or Privileges
CWE-478 Missing Default Case in Multiple Condition Expression
CWE-550 Server-generated Error Message Containing Sensitive Information
CWE-703 Improper Check or Handling of Exceptional Conditions
CWE-754 Improper Check for Unusual or Exceptional Conditions
Заключение
OWASP Top 10:2025 — это не просто обновлённый список угроз. Это отражение того, как меняется сама природа атак: от классических инъекций к компрометации цепочек поставок, от ошибок кода к провалам в проектировании, от молчаливых логов к опасному игнорированию сбоев.
Две новые категории — Software Supply Chain Failures (A03) и Mishandling of Exceptional Conditions (A10) — особенно ясно показывают: безопасность больше не ограничивается просто чистым кодом. Она охватывает весь жизненный цикл ПО: от выбора зависимостей и архитектурных решений до реакции на исключения.
Статический анализ остаётся одним из самых эффективных инструментов для раннего выявления рисков. Конечно, не все категории OWASP Top 10 можно покрыть SAST напрямую — особенно те, что связаны с конфигурацией, CI/CD или человеческими процессами. Но даже там, где анализатор не даёт прямого ответа, он помогает выявить симптомы незрелой практики безопасности: отсутствие валидации, слабые проверки, незащищённые точки входа.
Попробовать статический анализатор PVS-Studio можно с помощью бесплатной лицензии, которая доступна здесь. Мы рассмотрели различные сценарии, в которых анализатор помогает найти дефекты безопасности, описанные в OWASP Top 10, так почему бы вам не попробовать проверить свой проект на их наличие? :)
Безопасность — это не функция, которую можно включить. Это дисциплина, встроенная в каждый этап разработки. И чем позже вы начнёте её применять, тем дороже обойдётся пренебрежение ею.
Memento Securitatis.
Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Valerii Filatov. OWASP Top 10 2025—from code to supply chain: Expanding boundaries of security.
