Анализатор обнаружил логирование данных из внешнего источника без предварительной проверки. Это может нарушить процессы логирования или скомпрометировать содержание логов.
Ошибки, связанные с логированием данных, относятся к категории A09:2021 – Security Logging and Monitoring Failures списка OWASP Top 10 Application Security Risks.
Если логирование пользовательского ввода производится без проверок, то злоумышленник может внедрить произвольные данные в лог.
Рассмотрим пример. Предположим, что логи хранятся в простом текстовом формате. Узнать формат хранения логов можно разными способами. Например, если проект имеет открытый исходный код или с помощью какой-либо другой атаки. Возможный лог может иметь такой вид:
INFO: User 'SomeUser' entered value: '2022'.
INFO: User 'SomeUser' logged out.
Код, осуществляющий логирование, может выглядеть так:
public class InputHelper { HttpRequest Request {get; set;} Logger logger; string UserName; void ProcessUserInput() { string userInput = Request["UserInput"]; string logMessage = "INFO: User '" + UserName + "' entered value: '" + userInput + "'."; logger.Log(logMessage); .... } }
В таком случае злоумышленник может внедрить произвольные данные о событиях, которые никогда не происходили.
Например, злоумышленник вводит такой текст:
2022/r/nINFO: User 'Admin' logged out.
Тогда в логах появится такая запись, которая может ввести человека, анализирующего логи, в заблуждение:
INFO: User 'SomeUser' entered value: '2022'.
INFO: User 'Admin' logged out.
Рассмотрим другой вид атаки. Например, если логи хранятся в формате XML, то злоумышленник может внедрить такие данные, которые сделают содержимое отчёта некорректным. Также последующий процесс парсинга готовых логов может выдать неправильные данные или завершиться ошибкой. Пример уязвимого кода:
public class InputHelper { HttpRequest Request {get; set;} Logger logger; void ProcessUserInput() { string userID = Request["userID"]; logger.Info(userID); // <= .... } }
Злоумышленник может внедрить незакрытый тег и сделать невозможным парсинг XML-файла.
Список возможных уязвимостей зависит от архитектуры и настроек ввода, логгера, вывода логов или иных частей системы логирования. Например, атака на логи в формате XML может иметь следующие последствия:
Некоторых атак можно избежать экранированием символов, чтобы они не рассматривались как часть XML-синтаксиса. Например, начальный символ тега "<" следует экранировать как "<". Некоторые стандартные методы .NET для работы с XML, например, наследники 'XNode', реализуют экранирование записываемых в XML-дерево данных. Также .NET предоставляет отдельные от инфраструктуры XML классы для обеспечения безопасности. Пример более безопасного кода, использующего кодирование:
public class InputHelper { HttpRequest Request {get; set;} Logger logger; string EscapeCharsForXmlLog(string userInput) { return SecurityElement.Escape(userInput); } void ProcessUserInput() { string userInput = Request["userID"]; userInput = EscapeCharsForXmlLog(userInput); logger.Info(userInput); // <= .... } }
Ещё один пример: стандарт JSON запрещает наличие null-символов ("\0") в файлах. Если злоумышленник внедрит этот символ, это может сломать процесс сохранения или просмотра готовых логов. Null-символ следует экранировать как "\u0000".
Другой пример: если логи хранятся в реляционной СУБД, использующей SQL, отсутствие проверок входных данных может привести к SQL-инъекции (подробнее: диагностика V5608).
Также анализатор считает источниками небезопасных данных параметры методов, доступных из других сборок. Более подробно эта тема раскрыта в заметке "Почему важно проверять значения параметров общедоступных методов". Рассмотрим пример:
public class InputHelper { Logger logger; public void ProcessInput(string input) { Log("Input logged:" + input); } private void Log(string input) { logger.Log(LogLevel.Information, input); } }
В этом случае анализатор выдаст предупреждение низкого уровня достоверности на вызов метода 'Log'. Заражённый результат конкатенации строк используется для логирования.
Сделать этот код более безопасным можно также, как в примере выше — кодированием строки:
public class InputHelper { Logger logger; public void ProcessInput(string input) { Log(SecurityElement.Escape("Input logged:" + input)); } private void Log(string input) { logger.Log(LogLevel.Information, input); } }
Данная диагностика классифицируется как:
|