Ядовитый ответ Кислицин Никита Хакер, номер #071, стр. 071-070-2 cook.php?set=lala2%0d%0aContent-Length:%201%0d%0a%0d%0a<script> alert(document.cookie)</script> %0d%0a%0d%0a Если теперь выполнить этот скрипт, произойдет довольно неожиданная штука. По крайней мере, для составителя этой программы. По задумке кодера, скрипт должен был только лишь установить пользователю cookie и вывести тело страницы. А при указанном значении переменной set происходит совершенно нестандартная вещь: посетителю выводится окошко, в котором черным по белому написано содержимое его кукисов. Непорядок, это же просто ужасно! Ты прекрасно знаешь и не раз убеждался в том, что в cookies иногда хранится конфиденциальная информация, а в нашем случае эти данные оказались общедоступными и пользователь находится в шаге, чтобы с ними расстаться. Что же произошло? Давай разберемся. Все дело в том, что когда программист отправляет при помощи функции header() собственную строку в заголовок страницы, он не проверяет значение подставляемой переменной. Все работает отлично, но до тех пор, пока на сценарий не наткнется хакер-негодяй. Он помещает в переменную специальное значение, которое дополняет заголовок страницы до корректного и, кроме того, самостоятельно определяет тело самого документа, оставляя не у дел данные, которые поступают в поток вывода позже. Чтобы проще было разобраться, надо посмотреть на заголовок страницы, который возвращает web-сервер. При помощи tcpdump я задампил нужный пакет. Вот его ASCII-содержимое: Заголовок страницы после внедрения ядовитой переменной HTTP/1.1 200OK Date: Thu, 07 Oct 2004 18:40:11 GMT Server: Apache/1.3.29 (Unix) X-Powered-By: PHP/5.0.1 //Тут начинается вставляемая программистом строка, внимание! Set-Cookie: val=lala2 //Все верно, устанавливаем плюшку Content-Length: 1 Keep-Alive: timeout=15, max=99 //Добавляемые PHP заголовки Connection: Keep-Alive Content-Type: text/html <script> alert(document.cookie)</script> //А вот и новое тело документа Ну что, просек фишку? Думаю, что нет :). Ведь по твоим ожиданиям после Set-Cookie должен сплошным текстом следовать кусочек заголовка и тело документа. Однако здесь отчетливо видно, что PHP вставляет в заголовок дополнительные параметры. Меня это поначалу тоже смущало, а потом стало понятно, что так хитро работает сама функция header: если она видит, что программист хочет вставить в заголовок последовательность символов, символизирующую его конец, то не позволяет ему это сделать и дописывает прежде некоторые дополнительные свойства. В этом нет ничего страшного, более того, такое поведение свойственно не всем версиям PHP: когда я экспериментировал с четвертой веткой, этой проблемы не возникало. Думаю, не все вопросы еще сняты. Например, нужно пояснить, каким именно образом и почему так, а не иначе составляется строка, изменяющая заголовок страницы. Как и следовало ожидать, все написано в RFC, специфицирующих протокол HTTP. Рассказываю. Каждое поле заголовка должно быть отделено от предыдущего последовательностью символов \r\n – возврат каретки и перевод строки. Если посмотреть в таблицу ASCII, эти символы имеют коды 13 и 10 соответственно. Переведя эти десятичные числа в шестнадцатеричную систему счисления, мы получим 0d и 0a. Именно поэтому перед Content-Length я вставил последовательность %0d%0a. Следует также знать, что заголовок заканчивается \r\n\r\n или %0d%0a%0d%0a в шестнадцатеричной системе. |