Пятница , 29 Март 2024
ДомойПубликацииИ ещё немного об уязвимостях

И ещё немного об уязвимостях

Какой аспект является решающим для большинства заказчиков? С большой долей вероятности можно сказать, что это стоимость услуги.

Если исполнители называют цену в районе 200-300 долларов, а потом возникает кто-то и берёт ту же работу за 100 долларов, заказчик тает и радостно соглашается. Мало того, после работы ещё оставит хвалебный отзыв и не забудет попенять остальным, мол, вот какие жадные, в 3 раза больше денег просили, нажиться хотели, сволочи.

Но так ли всё просто на самом деле?

ujazvimosti

Несколько лет назад вкратце рассказывал об основных видах инъекций: PHP, SQL и XSS. Они актуальны и по сей день, даже в бо́льшей степени — количество людей, пытающихся постичь таинственный мир программинга, растёт. Повальное желание обучаться по видео ведёт к низкому качеству кода. Беда не в том, что пишут «не красиво», беда в другом: отсутствие представления о принципах работы в целом.

Простой пример: приложение получает параметр из формы. Пусть это будет число (возраст) из текстового поля. В строке браузера запрос выглядит примерно так:
domain/index.php?age=15

Допустим, мы ожидаем людей, старше 16 лет. Поэтому в единственном поле оставляем возраст — 15, и пишем текст с предложением «подрасти».

Как эту задачу обработает не опытный программист? Скорее всего, в лоб:

$age = $_GET['age'];

После чего выведет значение «как есть» в текстовое поле:

<input name="age" value="<?= $age ?>">

Всё хорошо? Допустим. Теперь изменим запрос к скрипту на такой:
domain/index.php?age="><script>alert(‘hello’);</alert>

HTML-код будет выглядеть так:

<input name="age" value=""><script>alert('hello');</alert>">

Здравствуй, XSS! В данном случае ничего страшного не происходит — выводится только сообщение hello в диалоге. Но код может быть не такой безобидный, например, текущие значения Cookie будут отсылаться на удалённый адрес. В худшем случае злоумышленних получает данные администратора и, как следствие, доступ к админ-панели.

«Ага, значит, данные нужно как-то защитить» — смекнёт начинающий программист. Спросив у Гугла, почти наверняка найдёт функцию addslashes(), которая экранирует кавычки и обратный слеш. Можно спать спокойно? Да фиг там! Изменяем запрос на такой:

<input name="age" value=""><script>alert(String.fromCharCode(104,101,108,108,111));</alert>">

Кавычек нет, следовательно, функция бесполезна. «Стоп!», — скажет внимательный читатель, — «вон же кавычки, в начале». Да, прошу прощения. Но, в данном случае, это никакого влияния на форму не окажет. Вывод будет таким:

<input name="age" value="\"><script>alert(String.fromCharCode(104,101,108,108,111));</alert>">

В IE и Chrome внедрена защита от подобных атак. Потенциально опасные внедрения браузеры отсекают. Между тем, периодически появляются репорты, как с помощью определённых последовательностей символов обойти фильтры. Посему, программист обязан самостоятельно фильтровать все поступающие данные.

«Хорошо», — ответит любознательный читатель, — «а я, с помощью JavaScript, запрещу вводить неправильные символы». Идея хорошая, но что мешает злоумышленнику посмотреть исходный код и отправить на сервер прямой запрос, введя данные в адресную строку браузера? Верный ответ — ничего.

Что делать в подобном случае? На мой взгляд, лучше приводить данные к тому типу, что ожидается, если уж PHP такой возможности не представляет автоматически. Элементарный пример:

$age = empty($_GET['age']) ? 0 : (int) $_GET['age'];

Одной строкой мы отсекли все потенциально опасные варианты, преобразовав переменную к целому типу. Не беда, если в поле будет введён текст — он преобразуется к значению 0 (ноль), а пользователю пишем предупреждение, что введены некорректные данные.

Это же справедливо и для других данных. Не важно, что ожидается — вещественное число, дата, что угодно — либо приводите тип к ожидаемому, либо пишите сообщение об ошибке, что данные поступили в «неизвестном» формате.

Как быть с текстом? Его же нужно вывести «как есть».

Специально для подобных случаев используем замечательную функцию htmlspecialchars() (не при получении параметра, а непосредственно при выводе пользователю!). Она заменяет спец-символы на соответствующие html-мнемоники:
< → &lt;
> → &gt;
" → &quot;
& → &amp;

Но! Эта обработка для вывода текста, содержащего HTML, и для записи в базу подобный трюк не нужен. Используйте функции, работающие на основе mysql_real_escape_string(). Имеющаяся в PHP addslashes() для экранирования не подходит.

Стремитесь получать данные в неизменном виде. Далее, в зависимости от контекста, производите нужные действия. Отправляете строку в базу данных — используйте mysql_real_escape_string(), для вывода в коде HTML-страницы подойдёт htmlspecialchars().

Часто у начинающих можно встретить такое:

$age = $_GET['age'];
$age = addslashes($age);
$age = htmlspecialchars($age);
// здесь код, работающий с переменной
// при записи в базу могут ещё раз накатить addslashes()
// вывод на страницу, но из-за того, что выводится не то, можеть быть такое:
echo $_GET['age'];

Как уже рассмотрели выше, от уязвимостей подобное не защищает, зато ведёт к потенциальным ошибкам при обработке входных данных. Повторю слова, которые должны восприниматься как истина: никаким данным, пришедшим от пользователей, доверять нельзя! Это касается и user-agent (идентификатор браузера), и зафильтрованной джава скриптом страницы. Браузеру можно не позволить отправить какие-то данные со страницы, но человек, знающий основы HTTP, составит запрос вручную (или программно) и, будьте уверены, скрипт не сумеет отличить подмены.

Рейтинг: 0

Автор публикации

2 070
не в сети 11 месяцев

x64 (aka andi)

Комментарии: 2893Публикации: 405Регистрация: 02-04-2009
Так себеНеплохоХорошоЗамечательноСупер! (2 голосов, в среднем: 5,00 из 5)
Загрузка...

Оставить комментарий

Политика конфиденциальности

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

Принять