XSS и ошибки разработчиков на веб-сервисах

      Комментарии к записи XSS и ошибки разработчиков на веб-сервисах отключены

Сначала разберем, что такое XSS и его виды.

 

XSS — Cross-Site Scripting — Одна из множества уязвимостей веб приложений, которая позволяет внедрить вредоносный код, на страницу.

Есть 2 типа XSS:

 

  1. Активная — XSS, которая статично находится на странице
  2. Пассивная — XSS, которая динамично отображается на странице, при определенном запросе

 

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

Начнем с ошибочных представлений разработчиков:

 

  1. Разработчик думает, что XSS — это инъекция только в HTML-сущность и только. Данное ошибочное мнение складывается изо дня в день. На самом же деле, XSS могут быть не только в HTML, они могут быть почти везде, к примеру даже в картинке.
  2. Разработчик уверен, что отфильтровав спец символы, можно защититься от XSS. Данные мнение частично верно, но в большинстве случаев разработчики фильтруют только кавычки (< и >) и забывают про апострофы, которые потом могут попасть в атрибуты чего-либо.

 

А сейчас давайте разберем несколько типов атаки:

 

Обычный тип

 

Представим у нас есть PHTML (PHP + HTML) код

 

<!DOCTYPE HTML>
<html>
    <head>
        <title>Привет!</title>
    </head>
    <body>
        Привет, <?=(isset($_GET['name']) ? $_GET['name'] : "незнакомец")?>!
    </body>
</html>

 

Данный код выводит "Привет, незнакомец!", если нету GET параметра с именем name, но если же параметр есть, то тогда выведет "Привет, {$_GET['name']}!". При помощи GET-запроса, делаем запрос на наш скрипт: index.php?name=Admin. Выводит "Привет, Admin!".

 

Теперь попробуем вывести наш вредоносный код. Для этого делаем запрос: index.php?name=<script>document.write('Hacker')</script>. Теперь нам выведет "Привет, Hacker!". Как видим, наш код document.write('Hacker') выполнился.

 


 

Так-же можно внедрять вредоносный код при внедрении в атрибуты. Для примера возьмем PHTML (PHP + HTML) код:

 

<html>
    <head>
        <title>Привет!</title>
    </head>
    <body>
        Ваше имя: <input value="<?=(isset($_GET['name']) ? $_GET['name'] : "незнакомец")?>">
    </body>
</html>

 

Как видим, у нас выполнился код, где имя содержится в inpute (Текстовом поле). Теперь для внедрения нашего кода нужно всего лишь сделать запрос:index.php?name=»>. Как видим мы добавили«>`, тем самым закрыв атрибут и тэг:

 


 

Способ защиты:

 

Для защиты от данной уязвимости в PHP может использоваться функция htmlspecialchars. Использовать её довольно просто — для этого в отрезок PHP-кода просто добавим обработчик htmlspecialcharsПолучается:

 

<?=(isset($_GET['name']) ? htmlspecialchars($_GET['name']) : "незнакомец")?>

 

И наши XSS уже не работают.

 


 

Скриптовой тип

 

Представим, что у нас есть PHTML (PHP + HTML) код:

 

<!DOCTYPE HTML>
<html>
    <head>
        <title>Привет!</title>
        <script>
        function deleteNews(id) {
            // Удаление новости
            alert("Успешно удалено");
        }
        </script>
    </head>
    <body>
        <a onclick="deleteNews('<?=(isset($_GET['id']) ? htmlspecialchars($_GET['id']) : "0")?>')">Вывести наш ID</a>
    </body>
</html>

 

Данный код выводит ссылку "Удалить новость", где ID новости передается в GET параметре id. При помощи GET-запроса делаем запрос на наш скрипт: index.php?name='); alert(1);//. Теперь при нажатии на ссылку, выведет наш alert(1), несмотря на htmlspecialchars. Это происходит из-за того, что htmlspecialchars не фильтрует по умолчанию одинарные кавычки.

 

Способ защиты:

 

Есть несколько способов защиты:

 

  • Тот же htmlspecialchars, но на этот раз с функцией addslashes. Получается:
    <a onclick="alert('<?=(isset($_GET['id']) ? htmlspecialchars(addslashes($_GET['id'])) : "0")?>')">Вывести наш ID</a>
  • В данном способе используется функция json_encode, это поможет избежать лишнего экранирования. Получается:
    <a onclick="alert(<?=htmlspecialchars(json_encode(isset($_GET['id']) ? $_GET['id'] : "0" ))?>)">Вывести наш ID</a>
  • Оставить только числа. В данном способе используется преобразование в integer (Так как ID — это численное значение). Получается:
    <a onclick="alert(<?=(isset($_GET['id']) ? (int)$_GET['id'] : "0" )?>)">Вывести наш ID</a>

    Таким образом мы оставляем только числа.

 


 

Изображения

 

Многие, сейчас задаются вопросом «Почему же изображения и при чем они тут вообще?». В наше время все используют аватарки, картинки и т.п. Но неправильная фильтрация может повлечь за собой последствия! Итак, уязвимость заключается в том, что если фильтровать по типу «Изображение» или нет, то можно разрешить загрузку таких файлов, как SVG. Что такое SVG (.svg или .svgz)?

 

SVG — Язык для построения векторной графики на XML

Mime-Type для SVG: image/svg+xml

 

В чем же уязвимость?

 

SVG может отображаться в браузерах, но в чем же опасность? Как ни странно, но SVG может использовать JavaScript. Для этого просто нужно прописать в тэг svg атрибут onload. Пример:

 

<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" baseProfile="tiny" xmlns="https://www.w3.org/2000/svg" xmlns:xlink="https://www.w3.org/1999/xlink"
     width="480" height="360" onload="alert(document.cookie)">
    <image xlink:href="https://my_sniffer/" x="0" y="0" height="50px" width="50px"/>
</svg>

 

Теперь, если загрузить данный файл на сервер (пусть будет путь https://site.ru/uploads/avatar.svg ) и перейти по нему, то выполнится код из onload.

 

Способ защиты:

 

Фильтровать файлы по расширения (.png, .jpg, .jpeg) и после чего проверять их валидность.

 


 

Ссылки

 

К примеру у нас есть скрипт для защиты от OpenRedirect`a на PHTML (PHP + HTML):

 

<!DOCTYPE HTML>
<html>
    <head>
        <title>Переход на небезопасный сайт!</title>
    </head>
    <body>
        <a href="<?=(isset($_GET['url']) ? htmlspecialchars($_GET['url']) : "https://habrahabr.ru")?>">Перейти на небезопасный сайт!</a>
    </body>
</html>

 

Уязвимость заключается в том, что мы можем использовать не только http || https-протоколы, а также javascript и data-протоколы. Для демонстрации перейдем по ссылке: script.php?url=javascript:alert(document.cookie);//. Теперь при нажатии на странице на ссылку, у нас вылезут наши cookie`s.

 

Способ защиты:

 

Фильтровать URL по regex`у
/^((http|https)\:\/\/)[a-zA-Z0-9\.\/\?\:@\-_=#]+\.([a-zA-Z0-9\&\.\/\?\:@\-_=#])*$/is и пропускать, только ссылки проходящие его

 

Рекомендации:

 

  1. Использовать специальный HTTPHeader: X-XSS-Protection
  2. Использовать специальный HTTPHeader: Content-Security-Policy

 

Конструкция <?= ?>

 

Это конструкция Short Open Tag с выводом данных (print), следующих после =