Кибербезопасность. Атаки на веб-приложения
Веб-приложения сегодня повсюду, и они используются для управления практически всем, что вы можете себе представить. В этой главе мы рассмотрим атаки и безопасность веб-приложений.
IDOR ("Insecure Direct Object Reference" - "Небезопасная прямая ссылка на объект")
IDOR уязвимости возникают, когда разработчики не реализовали требования авторизации для доступа к ресурсам.
Ева, просто изменив идентификатор, например параметр документа Rest, может получить доступ к документам Алисы.
Это происходит, когда веб-приложение не обеспечивает авторизацию между объектами, позволяя злоумышленникам перечислять значения и проверять доступ к другим точкам данных.
Например, у нас может быть следующий псевдокод, не показывающий никаких признаков авторизации:
$id = getInputFromUser();
$doc = getDocument($id);
return $doc;
Приведенный выше код запрашивает ввод от пользователя, не выполняет проверку или дезинфекцию, затем выполняет поиск напрямую с помощью функции getDocument и возвращает рассматриваемый документ.
Лучшей реализацией будет проверка привилегий:
$id = getInputFromUser();
$user = findUsername();
$doc = "";
if (hasAccessToDocument($user, $id)) {
$doc = getDocument($id);
} else {
$doc = "Не авторизован для этого документа";
}
return $doc;
Подобные уязвимости легко найти, поскольку вы можете просто изменить простое число и посмотреть, получите ли вы доступ к чужим данным. Проверка того, авторизован ли пользователь в первую очередь, предотвращает эту уязвимость.
Избегайте "Волшебных чисел"
Приложение хочет избежать использования последовательностей чисел при обращении к данным. В примере IDOR документы имели идентификаторы от 1000 до 1002. Иногда эти числа называют "волшебными (магическими) числами", поскольку они напрямую указывают на ресурс на сервере, например, через базу данных, и все значения могут быть легко перечислены. Например, злоумышленник может проверить все идентификаторы документов от 0 до 10000 и записать любые результаты, обеспечивающие доступ к данным.
Хотя авторизация должна быть правильно реализована, также полезно использовать GUID ("Globally Unique Identifier" - "Глобальный уникальный идентификатор") или UUID ("Universally Unique Identifier" - "Универсальный уникальный идентификатор") при обращении к данным. Эти идентификаторы разработаны так, чтобы быть глобально уникальными и их невозможно перечислить из-за встроенной энтропии генерации чисел.
Вот как может выглядеть GUID:
- 3377d5a6-236e-4d68-be9c-e91b22afd216
SQL-инъекция
Многие веб-приложения подключены к базе данных. База данных содержит всю информацию, которую веб-приложение желает хранить и использовать.
SQL-инъекция - это метод, позволяющий злоумышленникам манипулировать языком SQL ("Structured Query Language" - "Язык структурированных запросов"), который использует разработчик веб-приложения. Обычно это происходит из-за отсутствия очистки данных. SQL регулярно используется разработчиками для доступа к ресурсам базы данных.
В запросе Евы на рисунке выше мы видим, что она вводит значение: 1000' OR '1'='1
Это приводит к тому, что результирующий SQL-запрос возвращает все строки таблицы, поскольку база данных оценивает этот оператор как всегда истинный. Подумайте об этом: база данных получает запрос, в котором значение может быть либо 1000, либо 1 равно 1; он будет возвращать значение каждый раз! Существует множество различных функций и операций SQL, которые мы можем использовать для управления синтаксисом, и этот пример - лишь один из очень многих.
Ниже приведен пример псевдокода, который содержит уязвимость SQL-инъекции.
$username = getUserName();
$pw = getPassword();
$user = mysql_query("SELECT * FROM userTable WHERE username = $username AND password = $pw");
if ($user) {
$loggedIn = True;
} else {
$loggedIn = False;
}
Мы видим, что нет никакой дезинфекции как для переменных имени пользователя, так и для переменных пароля; вместо этого они используются непосредственно в SQL, вызывая уязвимость. Код позволяет установить переменную $loggedIn, если запрос что-либо возвращает.
Чтобы злоумышленник мог воспользоваться этим, он может просто создать URL-адрес целевого домена с атакой в нём следующим образом:
/login?username=admin&password=password' OR '1'='1
Переменная пароля содержит символы SQL, в результате чего результирующая строка SQL возвращает строку, даже если пароль нам неизвестен. Результирующий SQL-запрос будет:
SELECT * FROM userTable WHERE username = 'admin' AND password = 'password' OR '1'='1'
Параметризованные запросы - это рекомендуемое решение для защиты от SQL-инъекций. В параметризованном запросе разработчики тщательно следят за тем, чтобы каждый ввод запроса был определен как конкретное значение и тип. Вот пример из приведенного выше кода, который считается безопасной реализацией:
$username = getUserName();
$pw = getPassword();
$parameterizedQuery = prepare_query("SELECT * FROM userTable where username = ? and password = ?");
$parameterizedQuery.setString(1, $username)
$parameterizedQuery.setString(2, $password)
$user = parameterizedQuery.execute();
if ($user) {
$loggedIn = True;
} else {
$loggedIn = False;
}
В приведенном выше примере разработчик тщательно сказал, что параметр 1 должен быть строкой и содержать имя пользователя и пароль во втором параметре.
XSS ("Cross-Site Scripting" - "Межсайтовый скриптинг")
XSS использует сервер для атаки посетителей сервера. Атака нацелена не на сам сервер, а на пользователей.
Сервер просто используется для отражения значений злоумышленников, обычно JavaScript, против посетителей, которые затем запускают данные злоумышленников в своём собственном браузере. Злоумышленник должен создать ввод, который сервер не очищает и не дезинфицирует, таким образом, когда посетитель кликает ссылку, содержащую значения злоумышленников, или посещает ресурс на веб-странице, который злоумышленник использовал в своей атаке, пользователь запускает код, который - предоставил злоумышленник.
Вот графический пример того, как Ева отправляет Алисе ссылку, содержащую XSS-атаку:
Эта атака называется отраженным XSS и предполагает, что Ева обнаруживает уязвимость, затем отправляет ссылку, содержащую атаку, ничего не подозревающему пользователю и заставляет его кликнуть ссылку. Ссылка содержит атаку и заставляет веб-сервер возвращать атаку жертве, кликнув ссылку.
Код, стоящий за этим, может быть чем-то простым, как этот пример псевдокода:
$nickname = etNickName();
echo "Привет $nickname, приятно познакомиться!";
Другой вид XSS-атаки называется хранимой XSS-атакой. В атаках Stored XSS злоумышленник может сохранять контент на веб-странице, который отражается каждый раз, когда кто-то посещает веб-сайт. Необязательно, чтобы кто-то кликнул ссылку.
На этом рисунке показано, как Ева может сохранять вредоносный код JavaScript для выполнения в любом браузере при посещении ресурса:
XSS-атаки могут многое сделать, например:
- Кража файлов cookie, которые могут использоваться для аутентификации;
- Дезинфекция веб-сайта, представление содержимого, которое веб-сервер не намеревался;
- Фишинговые пользователи, оставляющие учётные данные в поддельных формах входа.
Для защиты от XSS есть несколько рекомендаций:
- Разрешить веб-серверу возвращать заголовки CSP ("Content Security Policy" - "Политика безопасности контента"), которые строго решают, где и как выполняется JavaScript.
- Безопасно кодируйте выходные данные, которые веб-сервер возвращает пользователям, эффективно превращая символы HTML в закодированные безопасные символы.
HTML Кодирование
HTML кодирование позволяет веб-приложению безопасно возвращать обычно небезопасные символы. Например, следующие специальные символы могут быть закодированы в их соответствующие аналоги:
Специальные символы | HTML объект |
---|---|
< | < |
> | > |
" | " |
& | & |
’ | ’ |
Это даёт результат, который можно безопасно отображать. Затем мы можем использовать JavaScript на стороне клиента, чтобы безопасно превращать объекты HTML в значения.
CSP ("Content Security Policy" - "Политика безопасности контента")
Веб-сервер может контролировать, какой JavaScript разрешен для запуска на веб-сайте. Это не устраняет уязвимости, но добавляет глубокую защиту на случай неизвестной уязвимости.
Обычный и строгий CSP - предоставить пользователям веб-приложения список всех принятых исходных файлов JavaScript.
Кроме того, для CSP типично предотвращать выполнение встроенного JavaScript.
Чтобы упростить реализацию и обнаружение продолжающихся атак, CSP позволяет клиентам сообщать о нарушениях CSP на URL-адрес, предоставленный сервером.
Сканирование веб-приложений
Существует множество сканеров веб-приложений. Это позволяет сканировать приложения на наличие уязвимостей, таких как SQL-инъекция и XSS. В отличие от сканера сетевых уязвимостей, сканер веб-приложений обычно строится на эвристике, а не на сигнатурах и списках известных уязвимостей.
Сканеры веб-приложений полезны, особенно когда они встроены в процессы разработки, такие как CI ("Continuous Integration" - "Непрерывная интеграция") и CD ("Continuous Delivery" - "Непрерывная доставка").