ЛУЧШИЙ САЙТ ДЛЯ ВЕБ-РАЗРАБОТЧИКОВ
Кибербезопасность. Уроки для начинающих

Кибербезопасность. Атаки на веб-приложения


Веб-приложения сегодня повсюду, и они используются для управления практически всем, что вы можете себе представить. В этой главе мы рассмотрим атаки и безопасность веб-приложений.


IDOR ("Insecure Direct Object Reference" - "Небезопасная прямая ссылка на объект")

IDOR уязвимости возникают, когда разработчики не реализовали требования авторизации для доступа к ресурсам.

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
Примечание: Если вы посмотрите на математику, стоящую за угадыванием числа, указанного выше, мы быстро увидим, что это нелегко пересчитать. Перечисление - это метод, который можно использовать для просмотра всех возможных вариантов значения, GUID или UUID предотвращают это.

SQL-инъекция

Многие веб-приложения подключены к базе данных. База данных содержит всю информацию, которую веб-приложение желает хранить и использовать.

SQL-инъекция - это метод, позволяющий злоумышленникам манипулировать языком SQL ("Structured Query Language" - "Язык структурированных запросов"), который использует разработчик веб-приложения. Обычно это происходит из-за отсутствия очистки данных. SQL регулярно используется разработчиками для доступа к ресурсам базы данных.

sqlinjection.svg

Peer-to-Peer

В запросе Евы на рисунке выше мы видим, что она вводит значение: 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 должен быть строкой и содержать имя пользователя и пароль во втором параметре.

Примечание: SQL-инъекция стала возможной, потому что разработчики тщательно не очищают ввод от пользователей и, таким образом, позволяют злоумышленнику обмануть приложение и базу данных, чтобы запустить неавторизованный код SQL.

XSS ("Cross-Site Scripting" - "Межсайтовый скриптинг")

XSS использует сервер для атаки посетителей сервера. Атака нацелена не на сам сервер, а на пользователей.

Сервер просто используется для отражения значений злоумышленников, обычно JavaScript, против посетителей, которые затем запускают данные злоумышленников в своём собственном браузере. Злоумышленник должен создать ввод, который сервер не очищает и не дезинфицирует, таким образом, когда посетитель кликает ссылку, содержащую значения злоумышленников, или посещает ресурс на веб-странице, который злоумышленник использовал в своей атаке, пользователь запускает код, который - предоставил злоумышленник.

Вот графический пример того, как Ева отправляет Алисе ссылку, содержащую XSS-атаку:

XSS

Эта атака называется отраженным XSS и предполагает, что Ева обнаруживает уязвимость, затем отправляет ссылку, содержащую атаку, ничего не подозревающему пользователю и заставляет его кликнуть ссылку. Ссылка содержит атаку и заставляет веб-сервер возвращать атаку жертве, кликнув ссылку.

Код, стоящий за этим, может быть чем-то простым, как этот пример псевдокода:

$nickname = etNickName();
echo "Привет $nickname, приятно познакомиться!";

Другой вид XSS-атаки называется хранимой XSS-атакой. В атаках Stored XSS злоумышленник может сохранять контент на веб-странице, который отражается каждый раз, когда кто-то посещает веб-сайт. Необязательно, чтобы кто-то кликнул ссылку.

На этом рисунке показано, как Ева может сохранять вредоносный код JavaScript для выполнения в любом браузере при посещении ресурса:

Сохранённый XSS

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" - "Непрерывная доставка").