Русский

Инструменты разработчика · Кодер и декодер URL

Кодировка URL не является очисткой: декодированные параметры все равно необходимо экранировать

· Почему это важно

URL-кодировка безопасность хсс

Полезная нагрузка, закодированная в процентах, декодируется обратно в исходную форму и готова к экранированию вывода.
Оригинальная векторная иллюстрация ToolAcre

Процентное кодирование защищает структуру URL, а не ваши HTML, SQL или оболочку. В этом посте объясняется, почему правильно закодированное значение снова становится опасным в момент его декодирования, и где какое экранирование.

Почему кодировка URL сама по себе не может остановить атаки XSS

«Безопасный» параметр может запускать скрипт, если он закодирован для передачи, но декодирован перед рендерингом. Рассмотрим полезную нагрузку XSS, например тег img с процентным кодированием обработчика ошибок как %3Cimg%20src%3Dx%20onerror%3Dalert%281%29%3E. Если это передается в URL и декодируется кодом приложения перед вставкой в ​​HTML, браузер видит исходную разметку и выполняет обработчик. Процентное кодирование — это уровень представления; не меняет основную угрозу.

Полезная нагрузка безопасна только во время передачи, когда она представляет собой закодированную строку без специального значения для парсера HTTP или URL. В тот момент, когда он декодируется, он снова становится опасным, поскольку возвращается к исходной форме. Каждый нижестоящий контекст должен применять свои собственные правила экранирования, соответствующие тому, как он будет использовать данные. Кодировка URL не заменяет экранирование HTML, параметризацию SQL или обработку аргументов оболочки.

Для чего нужно процентное кодирование — сохранение однозначности разделителей в сети, не более того

Процентное кодирование точно защищает структуру URL. Амперсанд остается частью синтаксиса строки запроса и не интерпретируется как разделитель. Слэш не становится разделителем пути. Вопросительный знак не начинает фрагмент. Кодируя зарезервированные символы как %XX, синтаксический анализатор обрабатывает их как данные, а не как синтаксис. Это работает для одной задачи: сохранение однозначности структуры URL в проводной сети.

Декодирование полностью меняет эту улицу с односторонним движением. Восстановленные байты — это именно то, что было закодировано, не больше и не меньше. HTML-опасная строка остается опасной, SQL-вектор внедрения остается опасной, а команда оболочки остается опасной. Процентное кодирование — это не проверка ввода, не очистка и не граница безопасности. Это только формат представления.

Декодирование восстанавливает исходные байты, поэтому каждый нижестоящий контекст снова видит необработанное значение.

Контекстно-зависимое экранирование — это то, где действительно существует реальная защита. Контекст HTML нуждается в сущностях: меньше, чем становится <, больше, чем становится >, кавычки становятся ", амперсанд становится &amp;. SQL контексту нужны параметризованные запросы, отделяющие структуру от данных, предотвращающие проникновение злоумышленника. Контексту оболочки нужны массивы аргументов, позволяющие полностью избегать разделения слов и подстановки.

Каждый контекст имеет разные опасные символы и разные правила экранирования. Объект HTML безвреден в запросе SQL, но бесполезен для защиты. Обратная косая черта предотвращает внедрение SQL в некоторых базах данных, но не в других. Экранирование оболочки зависит от стиля цитирования. Разработчик должен понять назначение, прежде чем выбирать, как обращаться с данными.

Контекстно-зависимое экранирование — объекты HTML для разметки, параметризованные запросы для SQL, массивы аргументов для оболочек.

Рабочий пример: следующая полезная нагрузка от ссылки до журнала на странице показывает, где должно произойти кодирование и экранирование. Ссылка содержит закодированные полезные данные XSS в качестве параметра запроса. Сервер получает его в закодированном виде в теле запроса HTTP. Приложение декодирует параметр запроса, чтобы отобразить его на странице. Без экранирования вывода браузер отображает полезную нагрузку как HTML и выполняет ее.

Если тот же параметр зарегистрирован в файле, запись журнала явно содержит декодированную полезную нагрузку. Второе приложение читает журнал, снова декодирует его и вставляет его на страницу HTML без экранирования. Полезная нагрузка выполняется второй раз. На каждом этапе контекст определял, что безопасно. URL декодирование прошло безопасно. Хранение файлов было безопасным. Но вывод HTML без выхода был фатальным.

Рабочий пример: переход по одной полезной нагрузке из ссылки в журнал на страницу — где она кодируется, где она декодируется, где она должна быть экранирована.

Кодирование как инструмент обхода фильтров показывает, почему злоумышленники дважды кодируют и смешивают шестнадцатеричный регистр. Если брандмауэр ищет тег img, злоумышленник отправляет %3Cimg и надеется, что приложение декодирует один раз, но брандмауэр этого не делает. Если проверка отклоняет %3Cimg, но допускает другой случай, те же байты декодируются в ту же полезную нагрузку. Безопасность, зависящая от соответствия шаблону закодированных входных данных, является хрупкой.

Декодирование должно быть точным и абсолютно предсказуемым. Каноническая форма (строчные шестнадцатеричные буквы, известная кодировка) обеспечивает согласованную политику, но не решает основную проблему. Единственный надежный подход — разрешить декодирование там, где это необходимо, и применить контекстно-зависимое экранирование вывода непосредственно перед использованием. Декодирование никогда не бывает безопасным; необходим только для передачи.

Кодирование как инструмент обхода фильтров: почему злоумышленники дважды кодируют и смешивают шестнадцатеричный регистр и почему декодирование должно быть точным

Полная защита XSS требует полного понимания потоков данных, контекстов, через которые они проходят на каждом этапе, а также того, что необходимо для выхода из каждого контекста. Кодировка URL представляет собой одну небольшую часть: сохраняет структуру только во время передачи. Но одна фигура сама по себе не является защитой. Многие разработчики путают кодирование с очисткой, поскольку оба варианта подразумевают замену символов, но выполняют совершенно разные важные задачи.

Брандмауэр веб-приложений может обнаруживать шаблоны в полезных данных запроса, но кодирование легко обходит простые методы сопоставления шаблонов. Настройка WAF сложна и выходит за рамки кодирования URL. Надежная защита — это экранирование выходных данных в коде приложения в сочетании с проверкой входных данных, если это имеет смысл для вашего конкретного контекста и требований.

Что сюда не входит — полное XSS руководство по защите или настройка брандмауэра веб-приложений.

Полная защита XSS требует полного понимания потоков данных, контекстов, через которые они проходят на каждом этапе, а также того, что необходимо для экранирования каждого контекста во всем приложении. Кодировка URL представляет собой одну небольшую часть: сохраняет структуру только во время передачи. Но одна фигура сама по себе не является защитой. Многие разработчики путают кодирование с очисткой, поскольку оба варианта подразумевают замену символов, но выполняют совершенно разные важные задачи на протяжении всей разработки.

Протестируйте полезную нагрузку от начала до конца, чтобы увидеть, где кодирование и экранирование действительно имеют значение на протяжении всего процесса. Вставьте %3Cimg%20src%3Dx%20onerror%3Dalert%281%29%3E в декодер URL и посмотрите, как строка станет похожей на разметку. Затем вставьте результат в escape-объект HTML, чтобы увидеть, как текст становится безопасным. Два инструмента показывают четко видимые слои.

Вывод: кодирование для URL, escape для вывода — как кодировщик и декодер URL и escaper объект HTML сидят бок о бок в одном продукте для двух разных задач.

Вывод заключается в том, что кодирование и экранирование — это совершенно разные проблемы на разных уровнях. Кодировка URL защищает только передаваемую структуру. Экранирование вывода защищает отображаемый контент. Правильно закодированное значение по-прежнему требует экранирования вывода, когда оно достигает HTML. Правильно экранированная строка никогда не требует кодировки URL, если она не помещена в URL.

Применяйте правильную защиту на правильном уровне. Не полагайтесь на кодировку URL для предотвращения атак XSS. Не полагайтесь на экранирование HTML для сохранения структуры URL. Понимайте поток данных и применяйте соответствующие преобразования на каждом этапе. Кодировщик URL помогает вам увидеть, что делает кодирование; затем используйте escape-объект HTML для шага вывода.