Какие уязвимости можно найти в вашем приложении?
11.04.20
Список, который мы рассмотрели, покрывает большую часть «универсальных» уязвимостей, встречающихся в приложениях на разных языках программирования.
Каждый день мы «обучаем» наш сканер приложений находить всё новые уязвимости. Анализируем приложения на 32 языках и знаем о “дырах”, которые встречаются почти в каждом. Об этих «универсальных» уязвимостях мы сегодня и расскажем. Как они возникают, какие сценарии могут привести к их успешной реализации злоумышленником. При каких действиях приложения стоит насторожиться, что служит сигналом наличия в приложении закладок.
● Внедрение
● Закладки
● Отсутствие/использование слабых алгоритмов шифрования
● Манипуляции с логами
● Небезопасная работа с куки
● Утечка информации
Внедрение
Куда только не внедряются: в запросы SQL, LDAP, XML, XPath, XSLT, XQuery. Все эти уязвимости объединяет использование недоверенных данных. Злоумышленник получает доступ к информации или изменяет поведение приложения. Пример недоверенных данных — пользовательский ввод, который недостаточно валидируется.
Атаки типа «Внедрение» (Injection) занимают первое место в рейтинге уязвимостей веб-приложений «OWASP Top 10 2017».
Внедрение в SQL-запрос. Недоверенные данные попадают в SQL-запрос к базе данных.
Если нет правильной валидации вводимых данных, злоумышленник может испортить SQL-запрос:
● передать в него вредоносный код;
● добавить символ «--» или «;» и оборвать корректную SQL-команду: всё, что после «--», интерпретируется как комментарий, а символ «;» обозначает конец команды;
● угадать пароль, последовательно выполнив серию SQL-запросов.
Внедрение в XML. Приложения используют XML для хранения или обмена данными, поэтому могут содержать ценные данные.
Если злоумышленник может записывать данные в XML-документ, то он может изменять и его семантику:
● В наиболее безобидном случае он может внедрить в документ лишние теги, в результате чего XML-парсер завершит работу с ошибкой.
● А может произойти и более серьёзный инцидент. Злоумышленник изменит аутентификационные данные в базе клиентов или цены в базе товаров магазина.
● Внедрение в XML может привести к межсайтовому скриптингу (XSS) — внедрению вредоносного кода, который выполнится в браузере пользователя при открытии страницы, что не менее серьёзно.
Внедрение в XQuery — это вариация классической SQL-инъекции, только вектор атаки — XML-база данных, а недоверенные данные попадают в XQuery-выражение.
Внедрение в XSLT (язык преобразования XML-документов) возникает, если приложение использует данные из недоверенного источника при работе с XSL.
Приложения используют XSL для преобразования XML-документов. Стилевые XSL-файлы содержат функции, которые описывают трансформацию, и при некорректной реализации могут содержать уязвимости.
Злоумышленник может изменить структуру и содержимое стилевого XSL-файла, а значит и соответствующего XML-файла. Возможные последствия:
● XSS-атака (внедрение в выдаваемую веб-системой страницу вредоносного кода и взаимодействие этого кода с сервером злоумышленника);
● получение доступа к системным ресурсам;
● выполнение произвольного кода;
● XXE-атака (XML eXternal Entity — внедрение внешней сущности в XML).
Внедрение в команды LDAP (Lightweight Directory Access Protocol — «легкорасширяемый протокол доступа к каталогам») может привести к утрате конфиденциальности данных или их модификации. В данном случае недоверенные данные попадают в LDAP-запрос.
Внедрение вредоносной команды интерпретатора. Недоверенные данные попадают в команду интерпретатора. Злоумышленник может подобрать такой ввод, что команда успешно выполнится, а злоумышленник при этом получит полномочия в приложении, которыми ранее не обладал.
Небезопасная загрузка файла. Теперь из недоверенного источника приходит целый файл. Злоумышленник может выгрузить на сервер вредоносные данные или код.
Если пользователи корпоративной сети могут выгружать файлы в публично доступные директории, злоумышленник может использовать это для удалённого выполнения на сервере компании вредоносного кода.
Небезопасное включение внешнего файла в HTML. Уязвимости типа «file inclusion» возникают, когда пользователь вводит путь к подключаемому файлу.
Современные скриптовые языки позволяют динамически подключать код из сторонних файлов, чтобы использовать его повторно. Этот механизм применяют для единого внешнего вида страниц или для разделения кода на небольшие модули. Злоумышленник может подменить путь и подключить свой файл.
Рекомендуем ИБ-службам предприятий составить «белый список» допустимых путей и позволять пользователям корпоративной сети добавлять файлы только из этого списка.
Закладки
Закладки — это преднамеренно внесённые участки кода, которые при определённых условиях реализуют недокументированную функциональность.
Специальные учётные записи. Если приложение сравнивает значение переменной пароля или логина с константным значением, стоит насторожиться: эта учётная запись может быть частью закладки.
Как происходит на практике?
Разработчик приложения использует специальную учётную запись (возможно, с повышенными привилегиями) при отладке и оставляет соответствующие участки кода в финальной версии, сохранив за собой доступ к приложению.
Злоумышленник может декомпилировать приложение, извлечь константные значения специальной учётной записи и получить доступ к приложению. Поэтому нельзя хранить логины, пароли, ключи в исходном коде приложения.
Скрытая функциональность (НДВ). Код скрытой функциональности запускается, когда срабатывает определенный триггер. В веб-приложениях триггером часто служит «невидимый» параметр запроса. Иногда дополнительно происходит проверка, с какого IP пришел запрос с триггером, чтобы активировать закладку мог только её автор. Такие проверки служат сигналом к возможным закладкам.
Недокументированная сетевая активность:
● соединение со сторонними ресурсами в фоновом режиме;
● прослушивание недокументированных портов;
● передача информации по протоколами SMTP, HTTP, UDP, ICMP.
В коде подозрительное соединение с адресом, который не входит в список заведомо безопасных? Рекомендуем его удалить.
Изменение параметров безопасности. Приложение содержит код, который изменяет значение переменной, хранящей успешность аутентификации.
Распространённая ошибка — использование присваивания (=) вместо сравнения (==). В методах, связанных с аутентификацией, она особенно опасна и может быть частью бэкдора:
if (isAuthenticated = true)
{
someDangerousAction();
}
Временной триггер (timebomb) — это закладка, которая срабатывает в определенный момент времени.
Приложение сравнивает текущую дату с конкретными годом, месяцем и днём: 1 января 2021 года всех ждёт сюрприз:
Date now = java.util.Date(); // current time
if ((now.getYear() == 2021) && (now.getMonth() == 1) && (now.getDate() == 1))
{
activateNewYearBackdoor();
}
А, возможно, что нет… На практике при поиске временных триггеров часто происходят ложные срабатывания. Причина — API времени используют и по назначению: запись в лог, вычисление времени выполнения, временные метки для ответов сервера на HTTP-запросы. Но мы рекомендуем не закрывать глаза на все подобные срабатывания, так как знаем реальные примеры таких уязвимостей.
Мёртвый код, то есть код, который есть, но ничего полезного не делает. Мёртвый код сам по себе не опасен, но может быть частью закладки, которую распределили по нескольким файлам. Другой вариант — триггер планируется внедрить позже. В любом случае, мёртвый код должен вызывать подозрения.
Отсутствие/использование слабых алгоритмов шифрования
Основные проблемы с шифрованием — не используется вовсе или используются слабые алгоритмы, а ключи и соль слишком простые или хранятся небезопасно. Последствие всех этих уязвимостей одно — конфиденциальные данные проще украсть.
Уязвимости типа «утечка конфиденциальных данных» (Sensitive Data Exposure) занимают третье место в рейтинге уязвимостей веб-приложений «OWASP Top 10 2017».
Рекомендация — использовать шифрование, но со знанием дела.
Использование незащищённого протокола HTTP вместо HTTPS грозит атакой «человек посередине».
HTTPS основан на HTTP и SSL / TLS, то есть он шифрует передаваемые данные. Это защищает их от несанкционированного доступа и изменения. Это касается не только страниц, где пользователь вводит логин и пароль или данные банковских карт. Злоумышленник может подменить информационный сайт по HTTP и заставить пользователя ввести данные на поддельной странице (фишинговая атака).
Ключ шифрования задан в исходном коде. Такие ключи доступны каждому разработчику приложения. После того, как приложение установлено, удалить ключ из кода можно только посредством обновления.
Константные строки легко извлекаются из скомпилированного приложения декомпиляторами. Поэтому злоумышленнику необязательно иметь доступ к исходному коду, чтобы узнать значение используемого ключа. В реальных приложениях случается, что в качестве значения ключа задают null или пустую строку, что просто недопустимо.
Рекомендация: генерируйте ключи криптостойкими ГПСЧ (генераторами псевдослучайных чисел) и храните с помощью специальных модулей.
Небезопасный алгоритм дополнения при шифровании. Если алгоритм шифрования RSA используется без OAEP-дополнения, зашифрованные данные становятся уязвимыми.
Алгоритм OAEP нужен, чтобы обработать сообщения перед использованием RSA. Сначала сообщение дополняется до фиксированной длины с помощью OAEP, затем шифруется с помощью RSA. Такая схема шифрования называется RSA-OAEP и является частью действующего стандарта.
Недостаточный размер ключа шифрования. Если вы используете ключ малой длины, шифрование уязвимо для атаки методом перебора.
Криптоанализ не стоит на месте: новые алгоритмы атак, бОльшие мощности компьютеров. Параметры шифрования, которые раньше считались безопасными, устаревают и уже не рекомендуются к использованию. Так, RSA с длиной ключа 1024 бит перестал считаться безопасным в 2010–2015 годах.
Слабый алгоритм хеширования. MD2, MD5, SHA1 являются небезопасными.
Чтобы найти коллизии для функций MD2 и MD5, существенных ресурсов не требуется.
Для SHA1 есть примеры двух разных файлов с одинаковыми хешами. Алгоритм взлома предложили сотрудники Google и Центра математики и информатики в Амстердаме.
Если пароли пользователей хранятся в виде хешей, но с использованием небезопасной хеш-функции, возможен такой сценарий:
Хеш-функция для хранения паролей должна быть устойчивой к коллизиям и не слишком быстрой, чтобы нельзя было атаковать перебором. Есть безопасные алгоритмы: PBKDF2, bcrypt, scrypt.
Несколько интересных цифр: с помощью PBKDF2 скорость перебора ключей сократили до 70 штук в секунду для Intel Core2 и около 1 тысячи на ПЛИС Virtex-4 FX60. Для сравнения, классические функции хеширования пароля LANMAN имеют скорость перебора около сотен миллионов вариантов в секунду.
Слабый алгоритм шифрования. Как и в случае алгоритмов хэширования, безопасность алгоритма шифрования определяется временем и ресурсами, которые нужны для дешифрования. Среди уязвимых алгоритмов — RC2, RC4, DES. DES из-за небольшой длины ключа (56 бит) можно взломать методом полного перебора.
Слабый генератор псевдослучайных чисел (ГПСЧ) порождает предсказуемые последовательности. Злоумышленник может обойти аутентификацию и захватить сессию пользователя.
ГПСЧ порождают цепочки чисел на основе начального значения параметра seed. Есть два типа ГПСЧ: статистические и криптографические.
● Статистические ГПСЧ порождают предсказуемые последовательности, которые по статистическим характеристикам похожи на случайные. Их нельзя использовать для обеспечения безопасности.
● Результат работы криптографических ГПСЧ, наоборот, невозможно предугадать, если значение параметра seed получено из источника с высокой энтропией. Значение текущего времени обладает небольшой энтропией и также небезопасно в качестве seed.
В Java ГПСЧ из классов java.util.Random и java.lang.Math порождают предсказуемые последовательности и не должны использоваться для информационной «безопасности».
Слабое зерно генератора псевдослучайных чисел. Использовать в качестве seed значение из недоверенного источника небезопасно. Соответствующий генератор псевдослучайных чисел (ГПСЧ) порождает предсказуемую последовательность.
Работа многих криптографических алгоритмов основана на использовании криптографически стойкого ГПСЧ. Некоторые алгоритмы принимают в качестве дополнительного аргумента значение seed и для каждого значения этого параметра порождают предсказуемую последовательность. В таком случае безопасность системы основана на предположении о том, что значения seed будут непредсказуемы.
Соль задана в исходном коде. Вспомним, для чего нужна соль. Чтобы взломать пароль методом перебора, используют заранее составленные таблицы со значениями хеш-функций от популярных паролей. Соль — произвольная строка, которая подаётся на вход хеш-функции вместе с паролем, чтобы затруднить такую атаку.
Если соль хранится в исходном коде, проблемы те же, что и с паролями и ключами. Значение соли доступно разработчикам и легко получить злоумышленникам, а убрать соль из финальной версии приложения можно будет только с обновлением.
Манипуляции с логами
Подделка файла лога. Приложение записывает недоверенные данные в журнал событий (лог). Злоумышленник может подделать записи лога или внедрить туда вредоносный код.
Как правило, приложения записывают в лог историю транзакций для дальнейшей обработки, отладки или сбора статистики. Разбирают логи вручную или автоматически.
Если записывать в лог данные «как есть», злоумышленник сможет:
● внедрить в лог фальшивые записи;
● нарушить структуру файла, вызвав сбои обработчика логов;
● внедрить вредоносный код, эксплуатирующий известные уязвимости в обработчике.
Вывод сообщений в стандартные потоки. Неструктурированное логирование (вывод сообщений об ошибках в стандартные потоки out или err) небезопасно. Вместо этого используйте структурированное логирование.
Структурированное логирование позволяет генерировать лог с уровнями, метками времени, стандартным форматированием. Если в программе реализован механизм структурированного логирования, но при этом сообщения об ошибках выводятся в стандартные потоки, может получиться, что в логе не окажется критически важной информации.
Выводить сообщения об ошибках в стандартные потоки допустимо только на ранних стадиях разработки.
Небезопасная работа с куки
Небезопасная работа с куки. Приложение включает в куки данные из недоверенного источника. Это ведёт к отравлению кэша, XSS, «расщеплению ответа».
Если ещё внедрить вредоносный код (межсайтовый скриптинг), злоумышленник сможет изменять куки пользователя.
Поскольку куки задаются в заголовке HTTP-ответа, отсутствие валидации данных, включаемых в куки, может привести к атаке типа «расщепление ответа». «Расщеплением ответа» (HTTP response splitting) называется атака, при которой злоумышленник посылает такой HTTP-запрос, ответ на который примется жертвой сразу за два HTTP-ответа (вместо правильного одного).
Если злоумышленник задаст в качестве параметра author строку вида Hacker \r\nHTTP/1.1 200 OK\r\n..., ответ будет расщеплён на два следующим образом:
HTTP/1.1 200 OK
...
Set-Cookie: author=Hacker
HTTP/1.1 200 OK
...
Содержимое второго ответа полностью контролируется злоумышленником, что приводит к отравлению кэша, XSS, вредоносным перенаправлениям и другим атакам.
Куки без HttpOnly. Приложение создаёт куки без флага httpOnly. Если флаг httpOnly включается в заголовок ответа http, получить куки с помощью JavaScript-кода уже нельзя. И если пользователь откроет страницу с уязвимостью типа межсайтовый скриптинг (XSS), браузер не раскроет куки третьим лицам. Если же флаг httpOnly не установлен, то куки (обычно, сессионные куки) можно украсть с помощью скрипта.
Здесь и далее в разделе: уязвимости типа «утечка конфиденциальных данных» (Sensitive Data Exposure) занимают третье место в рейтинге уязвимостей web-приложений «OWASP Top 10 2017».
Куки для слишком общего домена. Если домен для куки слишком общий (например, .example.com), уязвимость в одном приложении делает уязвимыми и другие приложения в том же домене.
Куки со слишком общим параметром path. Если путь в куки указан неточно (например, /), ситуация как с общим доменом: уязвимость в одном приложении подвергает опасности и другие приложения в том же домене.
Куки не по SSL. Приложение создаёт куки, не устанавливая флаг secure равным true. Такие куки можно передавать в незашифрованном виде по HTTP. Вспоминаем уязвимость Использование незащищённого протокола HTTP.
Куки с неограниченным сроком действия. Если хранить ценные куки слишком долго, злоумышленник может успеть получить к ним доступ.
По умолчанию используются непостоянные (сессионные) куки, которые не сохраняются на диск и удаляются после закрытия браузера. Разработчик может указать срок хранения куки. Тогда куки будут записаны на диск и сохранены между перезапусками браузера и перезагрузками компьютера.
Утечка информации
Внешняя утечка информации через страницы ошибок. Приложение использует стандартные страницы ошибок. В них может попасть информация о конфигурации системы.
Сообщения об ошибках и отладочная информация записываются в лог, выводятся в консоль или передаются пользователю. Из сообщений об ошибках злоумышленник может узнать об уязвимостях системы, что облегчит его работу. Например, ошибка базы данных может говорить о незащищённости от SQL-инъекции. Информация о версии операционной системы, сервера приложений и конфигурации системы также пойдут в ход.
Внешняя утечка ценной информации. В данном случае речь идёт о внешней утечке: информация о системе передаётся на другую машину по сети. Внешние утечки опаснее внутренних.
Внутренняя утечка ценной информации. Механизм эксплуатации, как и в предыдущих пунктах, но в данном случае речь идёт о внутренней утечке: информация о системе записывается в лог или выводится на экран.
Утечка конфиденциальных данных. Ценные персональные данные попадают в приложение из разных источников: от пользователя, из базы данных, из стороннего хранилища. Зачастую эти данные не помечены как конфиденциальные либо представляют ценность не сами по себе, а только в определённом контексте.
Безопасность и конфиденциальность персональных данных противоречат друг другу. С точки зрения безопасности, нужно подробно записывать информацию о действиях в системе, чтобы выявлять вредоносные действия. С точки зрения приватности — наоборот: если логировать конфиденциальную информацию, риск её утечки больше. Сохранить конфиденциальность важнее.
Резюме
Список, который мы рассмотрели, покрывает большую часть «универсальных» уязвимостей, встречающихся в приложениях на разных языках программирования. Есть уязвимости, специфичные для конкретных языков. О них мы расскажем в последующих обзорах.
Как себя обезопасить? Учитывать приведённые рекомендации при разработке, внимательно читать документацию, проверять приложения с помощью анализаторов.
SecurityLab
11.04.20
Список, который мы рассмотрели, покрывает большую часть «универсальных» уязвимостей, встречающихся в приложениях на разных языках программирования.
Каждый день мы «обучаем» наш сканер приложений находить всё новые уязвимости. Анализируем приложения на 32 языках и знаем о “дырах”, которые встречаются почти в каждом. Об этих «универсальных» уязвимостях мы сегодня и расскажем. Как они возникают, какие сценарии могут привести к их успешной реализации злоумышленником. При каких действиях приложения стоит насторожиться, что служит сигналом наличия в приложении закладок.
● Внедрение
● Закладки
● Отсутствие/использование слабых алгоритмов шифрования
● Манипуляции с логами
● Небезопасная работа с куки
● Утечка информации
Внедрение
Куда только не внедряются: в запросы SQL, LDAP, XML, XPath, XSLT, XQuery. Все эти уязвимости объединяет использование недоверенных данных. Злоумышленник получает доступ к информации или изменяет поведение приложения. Пример недоверенных данных — пользовательский ввод, который недостаточно валидируется.
Атаки типа «Внедрение» (Injection) занимают первое место в рейтинге уязвимостей веб-приложений «OWASP Top 10 2017».
Внедрение в SQL-запрос. Недоверенные данные попадают в SQL-запрос к базе данных.
Если нет правильной валидации вводимых данных, злоумышленник может испортить SQL-запрос:
● передать в него вредоносный код;
● добавить символ «--» или «;» и оборвать корректную SQL-команду: всё, что после «--», интерпретируется как комментарий, а символ «;» обозначает конец команды;
● угадать пароль, последовательно выполнив серию SQL-запросов.
Внедрение в XML. Приложения используют XML для хранения или обмена данными, поэтому могут содержать ценные данные.
Если злоумышленник может записывать данные в XML-документ, то он может изменять и его семантику:
● В наиболее безобидном случае он может внедрить в документ лишние теги, в результате чего XML-парсер завершит работу с ошибкой.
● А может произойти и более серьёзный инцидент. Злоумышленник изменит аутентификационные данные в базе клиентов или цены в базе товаров магазина.
● Внедрение в XML может привести к межсайтовому скриптингу (XSS) — внедрению вредоносного кода, который выполнится в браузере пользователя при открытии страницы, что не менее серьёзно.
Внедрение в XQuery — это вариация классической SQL-инъекции, только вектор атаки — XML-база данных, а недоверенные данные попадают в XQuery-выражение.
Внедрение в XSLT (язык преобразования XML-документов) возникает, если приложение использует данные из недоверенного источника при работе с XSL.
Приложения используют XSL для преобразования XML-документов. Стилевые XSL-файлы содержат функции, которые описывают трансформацию, и при некорректной реализации могут содержать уязвимости.
Злоумышленник может изменить структуру и содержимое стилевого XSL-файла, а значит и соответствующего XML-файла. Возможные последствия:
● XSS-атака (внедрение в выдаваемую веб-системой страницу вредоносного кода и взаимодействие этого кода с сервером злоумышленника);
● получение доступа к системным ресурсам;
● выполнение произвольного кода;
● XXE-атака (XML eXternal Entity — внедрение внешней сущности в XML).
Внедрение в команды LDAP (Lightweight Directory Access Protocol — «легкорасширяемый протокол доступа к каталогам») может привести к утрате конфиденциальности данных или их модификации. В данном случае недоверенные данные попадают в LDAP-запрос.
Внедрение вредоносной команды интерпретатора. Недоверенные данные попадают в команду интерпретатора. Злоумышленник может подобрать такой ввод, что команда успешно выполнится, а злоумышленник при этом получит полномочия в приложении, которыми ранее не обладал.
Небезопасная загрузка файла. Теперь из недоверенного источника приходит целый файл. Злоумышленник может выгрузить на сервер вредоносные данные или код.
Если пользователи корпоративной сети могут выгружать файлы в публично доступные директории, злоумышленник может использовать это для удалённого выполнения на сервере компании вредоносного кода.
Небезопасное включение внешнего файла в HTML. Уязвимости типа «file inclusion» возникают, когда пользователь вводит путь к подключаемому файлу.
Современные скриптовые языки позволяют динамически подключать код из сторонних файлов, чтобы использовать его повторно. Этот механизм применяют для единого внешнего вида страниц или для разделения кода на небольшие модули. Злоумышленник может подменить путь и подключить свой файл.
Рекомендуем ИБ-службам предприятий составить «белый список» допустимых путей и позволять пользователям корпоративной сети добавлять файлы только из этого списка.
Закладки
Закладки — это преднамеренно внесённые участки кода, которые при определённых условиях реализуют недокументированную функциональность.
Специальные учётные записи. Если приложение сравнивает значение переменной пароля или логина с константным значением, стоит насторожиться: эта учётная запись может быть частью закладки.
Как происходит на практике?
Разработчик приложения использует специальную учётную запись (возможно, с повышенными привилегиями) при отладке и оставляет соответствующие участки кода в финальной версии, сохранив за собой доступ к приложению.
Злоумышленник может декомпилировать приложение, извлечь константные значения специальной учётной записи и получить доступ к приложению. Поэтому нельзя хранить логины, пароли, ключи в исходном коде приложения.
Скрытая функциональность (НДВ). Код скрытой функциональности запускается, когда срабатывает определенный триггер. В веб-приложениях триггером часто служит «невидимый» параметр запроса. Иногда дополнительно происходит проверка, с какого IP пришел запрос с триггером, чтобы активировать закладку мог только её автор. Такие проверки служат сигналом к возможным закладкам.
Недокументированная сетевая активность:
● соединение со сторонними ресурсами в фоновом режиме;
● прослушивание недокументированных портов;
● передача информации по протоколами SMTP, HTTP, UDP, ICMP.
В коде подозрительное соединение с адресом, который не входит в список заведомо безопасных? Рекомендуем его удалить.
Изменение параметров безопасности. Приложение содержит код, который изменяет значение переменной, хранящей успешность аутентификации.
Распространённая ошибка — использование присваивания (=) вместо сравнения (==). В методах, связанных с аутентификацией, она особенно опасна и может быть частью бэкдора:
if (isAuthenticated = true)
{
someDangerousAction();
}
Временной триггер (timebomb) — это закладка, которая срабатывает в определенный момент времени.
Приложение сравнивает текущую дату с конкретными годом, месяцем и днём: 1 января 2021 года всех ждёт сюрприз:
Date now = java.util.Date(); // current time
if ((now.getYear() == 2021) && (now.getMonth() == 1) && (now.getDate() == 1))
{
activateNewYearBackdoor();
}
А, возможно, что нет… На практике при поиске временных триггеров часто происходят ложные срабатывания. Причина — API времени используют и по назначению: запись в лог, вычисление времени выполнения, временные метки для ответов сервера на HTTP-запросы. Но мы рекомендуем не закрывать глаза на все подобные срабатывания, так как знаем реальные примеры таких уязвимостей.
Мёртвый код, то есть код, который есть, но ничего полезного не делает. Мёртвый код сам по себе не опасен, но может быть частью закладки, которую распределили по нескольким файлам. Другой вариант — триггер планируется внедрить позже. В любом случае, мёртвый код должен вызывать подозрения.
Отсутствие/использование слабых алгоритмов шифрования
Основные проблемы с шифрованием — не используется вовсе или используются слабые алгоритмы, а ключи и соль слишком простые или хранятся небезопасно. Последствие всех этих уязвимостей одно — конфиденциальные данные проще украсть.
Уязвимости типа «утечка конфиденциальных данных» (Sensitive Data Exposure) занимают третье место в рейтинге уязвимостей веб-приложений «OWASP Top 10 2017».
Рекомендация — использовать шифрование, но со знанием дела.
Использование незащищённого протокола HTTP вместо HTTPS грозит атакой «человек посередине».
HTTPS основан на HTTP и SSL / TLS, то есть он шифрует передаваемые данные. Это защищает их от несанкционированного доступа и изменения. Это касается не только страниц, где пользователь вводит логин и пароль или данные банковских карт. Злоумышленник может подменить информационный сайт по HTTP и заставить пользователя ввести данные на поддельной странице (фишинговая атака).
Ключ шифрования задан в исходном коде. Такие ключи доступны каждому разработчику приложения. После того, как приложение установлено, удалить ключ из кода можно только посредством обновления.
Константные строки легко извлекаются из скомпилированного приложения декомпиляторами. Поэтому злоумышленнику необязательно иметь доступ к исходному коду, чтобы узнать значение используемого ключа. В реальных приложениях случается, что в качестве значения ключа задают null или пустую строку, что просто недопустимо.
Рекомендация: генерируйте ключи криптостойкими ГПСЧ (генераторами псевдослучайных чисел) и храните с помощью специальных модулей.
Небезопасный алгоритм дополнения при шифровании. Если алгоритм шифрования RSA используется без OAEP-дополнения, зашифрованные данные становятся уязвимыми.
Алгоритм OAEP нужен, чтобы обработать сообщения перед использованием RSA. Сначала сообщение дополняется до фиксированной длины с помощью OAEP, затем шифруется с помощью RSA. Такая схема шифрования называется RSA-OAEP и является частью действующего стандарта.
Недостаточный размер ключа шифрования. Если вы используете ключ малой длины, шифрование уязвимо для атаки методом перебора.
Криптоанализ не стоит на месте: новые алгоритмы атак, бОльшие мощности компьютеров. Параметры шифрования, которые раньше считались безопасными, устаревают и уже не рекомендуются к использованию. Так, RSA с длиной ключа 1024 бит перестал считаться безопасным в 2010–2015 годах.
Слабый алгоритм хеширования. MD2, MD5, SHA1 являются небезопасными.
Чтобы найти коллизии для функций MD2 и MD5, существенных ресурсов не требуется.
Для SHA1 есть примеры двух разных файлов с одинаковыми хешами. Алгоритм взлома предложили сотрудники Google и Центра математики и информатики в Амстердаме.
Если пароли пользователей хранятся в виде хешей, но с использованием небезопасной хеш-функции, возможен такой сценарий:
- Злоумышленник знает хеш пароля.
- Используя уязвимость алгоритма хеширования, злоумышленник вычисляет строку, для которой хеш такой же, как и для пароля.
- С помощью вычисленной строки злоумышленник проходит аутентификацию.
Хеш-функция для хранения паролей должна быть устойчивой к коллизиям и не слишком быстрой, чтобы нельзя было атаковать перебором. Есть безопасные алгоритмы: PBKDF2, bcrypt, scrypt.
Несколько интересных цифр: с помощью PBKDF2 скорость перебора ключей сократили до 70 штук в секунду для Intel Core2 и около 1 тысячи на ПЛИС Virtex-4 FX60. Для сравнения, классические функции хеширования пароля LANMAN имеют скорость перебора около сотен миллионов вариантов в секунду.
Слабый алгоритм шифрования. Как и в случае алгоритмов хэширования, безопасность алгоритма шифрования определяется временем и ресурсами, которые нужны для дешифрования. Среди уязвимых алгоритмов — RC2, RC4, DES. DES из-за небольшой длины ключа (56 бит) можно взломать методом полного перебора.
Слабый генератор псевдослучайных чисел (ГПСЧ) порождает предсказуемые последовательности. Злоумышленник может обойти аутентификацию и захватить сессию пользователя.
ГПСЧ порождают цепочки чисел на основе начального значения параметра seed. Есть два типа ГПСЧ: статистические и криптографические.
● Статистические ГПСЧ порождают предсказуемые последовательности, которые по статистическим характеристикам похожи на случайные. Их нельзя использовать для обеспечения безопасности.
● Результат работы криптографических ГПСЧ, наоборот, невозможно предугадать, если значение параметра seed получено из источника с высокой энтропией. Значение текущего времени обладает небольшой энтропией и также небезопасно в качестве seed.
В Java ГПСЧ из классов java.util.Random и java.lang.Math порождают предсказуемые последовательности и не должны использоваться для информационной «безопасности».
Слабое зерно генератора псевдослучайных чисел. Использовать в качестве seed значение из недоверенного источника небезопасно. Соответствующий генератор псевдослучайных чисел (ГПСЧ) порождает предсказуемую последовательность.
Работа многих криптографических алгоритмов основана на использовании криптографически стойкого ГПСЧ. Некоторые алгоритмы принимают в качестве дополнительного аргумента значение seed и для каждого значения этого параметра порождают предсказуемую последовательность. В таком случае безопасность системы основана на предположении о том, что значения seed будут непредсказуемы.
Соль задана в исходном коде. Вспомним, для чего нужна соль. Чтобы взломать пароль методом перебора, используют заранее составленные таблицы со значениями хеш-функций от популярных паролей. Соль — произвольная строка, которая подаётся на вход хеш-функции вместе с паролем, чтобы затруднить такую атаку.
Если соль хранится в исходном коде, проблемы те же, что и с паролями и ключами. Значение соли доступно разработчикам и легко получить злоумышленникам, а убрать соль из финальной версии приложения можно будет только с обновлением.
Манипуляции с логами
Подделка файла лога. Приложение записывает недоверенные данные в журнал событий (лог). Злоумышленник может подделать записи лога или внедрить туда вредоносный код.
Как правило, приложения записывают в лог историю транзакций для дальнейшей обработки, отладки или сбора статистики. Разбирают логи вручную или автоматически.
Если записывать в лог данные «как есть», злоумышленник сможет:
● внедрить в лог фальшивые записи;
● нарушить структуру файла, вызвав сбои обработчика логов;
● внедрить вредоносный код, эксплуатирующий известные уязвимости в обработчике.
Вывод сообщений в стандартные потоки. Неструктурированное логирование (вывод сообщений об ошибках в стандартные потоки out или err) небезопасно. Вместо этого используйте структурированное логирование.
Структурированное логирование позволяет генерировать лог с уровнями, метками времени, стандартным форматированием. Если в программе реализован механизм структурированного логирования, но при этом сообщения об ошибках выводятся в стандартные потоки, может получиться, что в логе не окажется критически важной информации.
Выводить сообщения об ошибках в стандартные потоки допустимо только на ранних стадиях разработки.
Небезопасная работа с куки
Небезопасная работа с куки. Приложение включает в куки данные из недоверенного источника. Это ведёт к отравлению кэша, XSS, «расщеплению ответа».
Если ещё внедрить вредоносный код (межсайтовый скриптинг), злоумышленник сможет изменять куки пользователя.
Поскольку куки задаются в заголовке HTTP-ответа, отсутствие валидации данных, включаемых в куки, может привести к атаке типа «расщепление ответа». «Расщеплением ответа» (HTTP response splitting) называется атака, при которой злоумышленник посылает такой HTTP-запрос, ответ на который примется жертвой сразу за два HTTP-ответа (вместо правильного одного).
Если злоумышленник задаст в качестве параметра author строку вида Hacker \r\nHTTP/1.1 200 OK\r\n..., ответ будет расщеплён на два следующим образом:
HTTP/1.1 200 OK
...
Set-Cookie: author=Hacker
HTTP/1.1 200 OK
...
Содержимое второго ответа полностью контролируется злоумышленником, что приводит к отравлению кэша, XSS, вредоносным перенаправлениям и другим атакам.
Куки без HttpOnly. Приложение создаёт куки без флага httpOnly. Если флаг httpOnly включается в заголовок ответа http, получить куки с помощью JavaScript-кода уже нельзя. И если пользователь откроет страницу с уязвимостью типа межсайтовый скриптинг (XSS), браузер не раскроет куки третьим лицам. Если же флаг httpOnly не установлен, то куки (обычно, сессионные куки) можно украсть с помощью скрипта.
Здесь и далее в разделе: уязвимости типа «утечка конфиденциальных данных» (Sensitive Data Exposure) занимают третье место в рейтинге уязвимостей web-приложений «OWASP Top 10 2017».
Куки для слишком общего домена. Если домен для куки слишком общий (например, .example.com), уязвимость в одном приложении делает уязвимыми и другие приложения в том же домене.
Куки со слишком общим параметром path. Если путь в куки указан неточно (например, /), ситуация как с общим доменом: уязвимость в одном приложении подвергает опасности и другие приложения в том же домене.
Куки не по SSL. Приложение создаёт куки, не устанавливая флаг secure равным true. Такие куки можно передавать в незашифрованном виде по HTTP. Вспоминаем уязвимость Использование незащищённого протокола HTTP.
Куки с неограниченным сроком действия. Если хранить ценные куки слишком долго, злоумышленник может успеть получить к ним доступ.
По умолчанию используются непостоянные (сессионные) куки, которые не сохраняются на диск и удаляются после закрытия браузера. Разработчик может указать срок хранения куки. Тогда куки будут записаны на диск и сохранены между перезапусками браузера и перезагрузками компьютера.
Утечка информации
Внешняя утечка информации через страницы ошибок. Приложение использует стандартные страницы ошибок. В них может попасть информация о конфигурации системы.
Сообщения об ошибках и отладочная информация записываются в лог, выводятся в консоль или передаются пользователю. Из сообщений об ошибках злоумышленник может узнать об уязвимостях системы, что облегчит его работу. Например, ошибка базы данных может говорить о незащищённости от SQL-инъекции. Информация о версии операционной системы, сервера приложений и конфигурации системы также пойдут в ход.
Внешняя утечка ценной информации. В данном случае речь идёт о внешней утечке: информация о системе передаётся на другую машину по сети. Внешние утечки опаснее внутренних.
Внутренняя утечка ценной информации. Механизм эксплуатации, как и в предыдущих пунктах, но в данном случае речь идёт о внутренней утечке: информация о системе записывается в лог или выводится на экран.
Утечка конфиденциальных данных. Ценные персональные данные попадают в приложение из разных источников: от пользователя, из базы данных, из стороннего хранилища. Зачастую эти данные не помечены как конфиденциальные либо представляют ценность не сами по себе, а только в определённом контексте.
Безопасность и конфиденциальность персональных данных противоречат друг другу. С точки зрения безопасности, нужно подробно записывать информацию о действиях в системе, чтобы выявлять вредоносные действия. С точки зрения приватности — наоборот: если логировать конфиденциальную информацию, риск её утечки больше. Сохранить конфиденциальность важнее.
Резюме
Список, который мы рассмотрели, покрывает большую часть «универсальных» уязвимостей, встречающихся в приложениях на разных языках программирования. Есть уязвимости, специфичные для конкретных языков. О них мы расскажем в последующих обзорах.
Как себя обезопасить? Учитывать приведённые рекомендации при разработке, внимательно читать документацию, проверять приложения с помощью анализаторов.
SecurityLab