DoS-атака (аббревиатура от Denial of Service) — это атака с целью остановить или замедлить обработку запросов клиентов. DoS-атаки не имеют цели украсть или повредить данные клиентов. Сутью атаки является создание проблем с доступностью вычислительных ресурсов, из-за которых процессы не выполняются за приемлемое время. Вычислительными ресурсами обычно являются:
Атаки могут быть разделены на две группы: DDoS (distributed denial-of-service) и DoS-атаки уровня приложения.
DDoS-атака достигается созданием огромного количества обычных клиентских запросов (входных данных) к API системы. Атака производится множеством устройств, поэтому и называется распределённой. Обычно для системы эти устройства и их запросы не имеют явных проблем для процессов её внутренней логики. Запросы не содержат вредоносных или использующих уязвимостей данных. Проблемы возникают, когда сетевой канал сервера не имеет достаточной пропускной способности для обработки всех запросов. Или вычислительные ресурсы машины, на которой установлен сервер, исчерпываются.
Для совершения атаки используются заранее заражённые устройства, которые делают запросы к цели по команде. Атакующим не требуется широкий сетевой канал, поэтому сетевая активность заражённого устройства может быть незаметна для владельца. Зачастую невозможно отличить реальных пользователей от заражённых атакующих. Такая ситуация может быть решена развёртыванием дополнительных ресурсов для системы на время атаки. Это может быть технически сложно и дорого, но едва ли существующим в системе данным клиентов будет нанесён урон.
DoS-атаки уровня приложения производятся через особенности и проблемы архитектур программ и оборудования. Название "атака уровня приложения" связано с 7-м уровнем модели OSI, который называется уровнем приложения. Атаки уровня приложения также нацелены на достижение состояния исчерпания ресурсов хост-машины. Атаки производятся малым количеством устройств, но с использованием уязвимостей или архитектурных проблем системы. Для использования этих уязвимостей и проблем подбираются специальные данные, обработка которых приводит к нарушению процессов.
Зачастую проблемы находятся в спецификациях и стандартах грамматик и форматов, откуда они в неявном виде переходят в парсеры и сериализаторы. Но ошибки в реализациях также не исключены.
Примером проблемы в стандартах и спецификациях является XEE-атака, для совершения которой требуется наличие API, принимающего XML-файлы. Если XML-парсер API сконфигурирован без защиты от разворачивания вложенных XML-сущностей, то может произойти исчерпание ресурсов машины парсером.
Некоторые другие уязвимости в коде также могут быть использованы для DoS-атак. Например, инъекция кода с большой вычислительной сложностью через XSS-уязвимость или SQL-инъекцию. Хотя эти уязвимости могут быть использованы для совершения более опасных атак для кражи и повреждения данных.
При неправильной архитектуре системы случайная DoS-атака может произойти даже без злого умысла. Ошибки в архитектуре системы могут быть причиной большого расхода ресурсов даже при работе с обычными данными. Например:
Подробнее рассмотрим случай, когда обработка регулярных выражений может исчерпать ресурсы системы. Такая ситуация называется ReDoS (Regular Expression Denial of Service). Рассмотрим следующий код на языке C#:
string userInput = GetInput();
Regex regex = new Regex(@"(a+)+b");
bool isMatch = regex.IsMatch(userInput);
....
Выражение 'a+' декларирует найти одно вхождение или более символа 'a'. Выражение взято в скобки и в таком виде к нему применяется квантификатор '+'. Выражение '(a+)+' декларирует найти одно или более вхождений группы '(a+)'. Наконец, полное выражение декларирует найти символ 'b' после нахождения предыдущих подстрок. Минимально подходящая строка: 'ab'.
Это синтетический пример. Но он содержит пример ошибки катастрофического отката.
Для исследования возьмём строку 'aaaa'. В ней нет текста, который ищется регулярным выражением. Минимальной найденной подстрокой для '(a+)' будет один символ. Поэтому движок регулярных выражений будет перебирать всю строку в поиске 'b'. При неуспешном поиске движок отсекает последний символ в надежде, что среди новых комбинаций найдётся удовлетворяющая шаблону регулярного выражения.
Этот механизм называется откатом, и движок переберёт всю строку. Время поиска растёт экспоненциально. Поэтому проблема называется катастрофическим откатом.
Итак, уязвимым регулярное выражение будет когда:
Защититься от этой проблемы можно установкой ограничения по времени выполнения поиска:
string userInput = GetInput();
Regex regex = new Regex(@"(a+)+b",
RegexOptions.None,
matchTimeout: TimeSpan.FromSeconds(1));
bool isMatch = regex.IsMatch(userInput);
Время поиска специфицируется аргументом 'matchTimeout'. Если это время будет превышено, произойдёт выброс исключения 'RegexMatchTimeoutException'.
Также побороть проблему поможет создание более точных регулярных выражений.
0