Что такое заголовки в запросах

Что такое HTTP, или как браузеры общаются с веб-серверами

В статье про устройство веба и как происходит серфинг я упомянул, что браузер отправляет запрос к веб-серверу. Но что представляет из себя запрос? Это куча машиночитаемых квантовых кодов и сингулярных шифров? Программистская магия? Вовсе нет.

Что такое HTTP

HTTP — это протокол передачи данных для клиент-серверных приложений.

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

  • При встрече на протянутую руку принято отвечать рукопожатием. Отсутствие рукопожатия — это тоже ответ, иногда даже более красноречивый, чем само рукопожатие.
  • Девушкам же руку не протягивают — это тоже часть протокола. Можно и им руку протянуть, но в большинстве случаев не поймут, а в некоторых странах заставят жениться.
  • Электрические розетки — хотя в разных странах они разные, внутри одной страны они одинаковы.
  • Разъёмы для кабелей — USB type B, USB type C, mini USB, micro USB. Производители приняли внегласный протокол и производят кабели и устройства именно таких форматов, иначе при прочих равных пользователи их не поймут и не будут покупать их продукцию (исключение — Apple).
  • Правила дорожного движения — знаки, разметка и светофоры помогают пешеходам дойти, а автомобилистам доехать до места назначения без происшествий.
  • Формы налоговых деклараций и прочих бюрократических документов.

Любой из протоколов нас ни к чему не обязывает, это не ГОСТ, он лишь рекомендует поступать так или иначе, если мы хотим добиться желаемой цели — понимания от окружающих людей, одобрения от покупателей, сохранения продаж, избежания аварий и штрафов, получения веб-страницы от сервера.

HTTP — это набор некоторых правил, которым должны следовать клиенты и сервера, если они хотят, чтобы их правильно поняли.

HTTP-клиентами чаще всего являются браузеры — Google Chrome, Mozilla Firefox, Safari, Opera, Yandex Browser и другие. А серверами являются веб-сервера. Вот эта приставка «веб-» и указывает на то, что это не просто какой-то сервер, а сервер, который умеет принимать запросы и отвечать на них по протоколу HTTP. Как он будет устроен внутренне — не определено и не важно. Наиболее популярными в мире веб-серверами являются Nginx, Apache2, но вы можете написать и свой — в некоторых языках это делается крайне легко, см. пример на Golang.

Прикидываемся браузером, или делаем HTTP-запрос из терминала

Чтобы понять, как браузер общается с сервером, нужно думать как браузер, нужно стать браузером.

Попробуем обратиться к веб-странице http://http.maxkuznetsov.ru так, как это делают браузеры под капотом. Для этого отправим запрос из терминала/командной строки с помощью утилиты netcat. Чаще всего она установлена по умолчанию: в Mac OS X — это «nc», в других ОС может быть «ncat» или «netcat». (Или воспользуйтесь онлайн-сервисом https://reqbin.com/u4178vu3, в котором слева и справа выберите табы Raw для отображения «голых» запросов и ответов. Но из терминала получится нагляднее.)

Дальше ничего не произойдёт, терминал подвиснет — это нормально. Команда netcat подключилась к серверу по адресу http.maxkuznetsov.ru к 80-му порту, и сервер ждёт от нас текст запроса.

Порты — это как номера квартир в доме. Чтобы доставить письмо, почтальону нужно знать не только дом, но и номер квартиры. Причём в некоторых квартирах почтальону ответят, если он в них постучится, а другие — нет, потому что там никто не живёт. А кто-то ответит, что адресат уже давно здесь не живёт и дадут новый адрес почтальону (редирект запроса).

В компьютерных сетях всё точно также. На одном адресе (IP или доменном имени) могут висеть и ожидать запросов несколько портов одновременно. Чтобы избежать путаницы, сообщество разработчиков договорилось для наиболее популярных серверов выделять одни и те же порты: SSH — 22, FTP — 21, база данных MySQL — 3306, веб-сервера — 80. Это лишь соглашение и рекомендация, можно поднять какой угодно сервер на каком угодно порту, но для клиентов это скорее всего станет неожиданностью.

Когда в браузере мы вбиваем в адресной строке http.maxkuznetsov.ru, браузер подставляет порт 80 незаметно для нас. Вы можете убедиться в этом, вбив в адрес не http.maxkuznetsov.ru, а http.maxkuznetsov.ru:80 — результат не изменится.

Введём в терминале такие строки запроса.

После Host нужно ввести две пустые строки: одна строка отступа, вторая содержит тело запроса, но в данном примере оно пустое. Такие правила протокола HTTP. Получив вторую пустую строку, веб-сервер поймёт, что запрос завершён, обработает его и пришлёт ответ, включающий интересующую нас веб-страницу с html.

После этого браузер разбирает ответ, убирает техническую информацию и отображает html-страницу в кодировке UTF-8 — так ему сказал сервер в заголовке Content-Type. Если в HTML включены CSS, Javascript, картинки, то браузер запросит их отдельными запросами ровно таким же образом. Если он их уже запрашивал раньше, то возьмёт из локального кэша. Поэтому первый раз страницы грузятся визуально дольше.

Разберём структуру запроса и ответа более детально.

Структура HTTP-запроса

Каждый запрос имеет один и тот же формат:

протокол

Указывает, какая конкретная версия протокола HTTP будет использоваться. Чаще всего 1.0 и 1.1, но могут встречаться устаревшая 0.9 или новая 2.0. Однако, веб-сервер может не поддерживать указанную версию и вернуть ошибку. На практике подавляющее количество веб-серверов поддерживают 1.0 и 1.1.

Относительный путь (без доменного имени) до документа. В нашем примере указан корень /, но путь может быть любым: /index.php, /catalog/food/milk. Под документом понимаются не только файлы с расширением .html, но и любые другие файлы, например картинки, .css, .js.

метод

Определяет, что веб-сервер должен сделать с документом, найденным по указанному «/пути».

  • GET — вернуть документ — GET /messages/1.
  • HEAD — вернуть только заголовки без самой страницы. Это подходит для случая, когда мы хотим проверить, что ссылка на документ валидная. Пример: HEAD /messages/1
  • POST — отправить данные для создания документа — POST /messages (и детали нового сообщения).
  • PUT — заменить документ
  • PATCH — частично обновить документ
  • DELETE — удалить документ
  • TRACE, CONNECT — технические методы, которые можно пропустить.
  • OPTIONS — просьба к веб-серверу вернуть разрешённые настройки для запросов к указанному документу. Ответ включает в себя в том числе список разрешённых методов.

На практике примерно 80% запросов приходится на GET, 15% — на POST и 5% — на все остальные методы.

Заголовки

Они опциональны (в нашем примере их не было вовсе) и подсказывают веб-серверу, как именно нужно обработать запрос. Например, что клиент отправляет запрос в виде текста с кодировкой utf-8, а ожидает получить json в кодировке cp1251.

Наиболее частые на практике заголовки:

  • Accept — в каком формате ожидаем ответ: обычный текст, html, xml, json, что угодно ещё.
  • Accept-Charset — кодировка тела запроса: utf8, cp1251, koi8.
  • Authorization — данные для авторизации между запросами. Здесь чаще всего передаются токены API. Авторизация между запросами будет рассмотрена ниже.
  • Accept-Language — список языков, которые нас бы устроили. Например: «Accept-Language: ru».
  • Cache-Control — настройки кэширования страниц
  • Cookie — известные браузеру куки. В них сохраняются идентификаторы сессий и пользовательские предпочтения.
  • Referrer — с какой страницы был сделан текущий запрос. Полезно для аналитики сайта и для возвращения юзера на первоначальную страницу после регистрации, например.
  • User-Agent — тип клиента (чаще всего тип вашего браузера). Пример: «Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36». Это поле часто используется на сервере, чтобы отслеживать количество запросов с одного устройства и блокировать их при превышении лимита. Однако это не панацея, ведь после блокировки злоумышленник может поменять User-Agent на любой другой.

Для GET-запросов тело не имеет смысла, так как всё, что нужно — это путь в стартовой строке и заголовки. Но что происходит, когда мы хотим отправить информацию на сервер? Логин-пароль, форма обратной связи, форма создания поста? Для этого используется POST-запрос.

Каждый элемент формы имеет аттрибут name. В нашем примере страница http://http.maxkuznetsov.ru содержит форму с единственным тегом input, который имеет name=«name». Именно это имя и введённое пользователем в инпут значение будут отправлены на сервер. В консоли такой браузерный запрос будет выглядеть так:

Обратите внимание, что POST запрос очень похож на GET, мы даже обращаемся к тому же документу «/». Однако есть и отличия:

  • вместо второй пустой строки в конце запроса содержатся данные: «name=Max»
  • эти данные могут быть в разном формате, поэтому мы должны явно указать веб-серверу, что это данные из формы — application/x-www-form-urlencoded
  • также мы сообщаем серверу, что в теле запроса содержится ровно 8 символов — «Content-Length: 8». Это техническое поле, которое браузер выполняет на лету, а нам приходится считать самим.

В ответ придёт знакомая страница, но с другим h1 заголовком — php-скрипт, обрабатывающий страницу, подставил вместо «http world» введённое нами имя.

Структура HTTP-ответа на основе примера выше

Можно заметить, что структура ответа похожа на структуру запроса. Но есть несколько нюансов. Первая строка ответа выглядит иначе:

протокол

Значение поля то же самое, что и в запросе. Но может отличаться от версии, что запросил браузер, если веб-сервер её не понимает.

статус и пояснение

HTTP-статус из трёх цифр и короткая поясняющая фраза. Все фразы стандартизированы и чётко соответствуют статусу.

Статусов больше сотни, но не все их них используются браузерами. Некоторые предусмотрены на далёкое будущее, а некоторые слишком специфичны.

Первая цифра статуса указывает на класс:

  • 1xx — информационные — технические статусы, вероятнее всего вы их не увидите в реальной жизни
  • 2xx — успешно обработанные запросы с детализацией. Наиболее частые: 200 — всё ок, 201 — документ был создан, 204 — запрос завершился успешно, но ответ содержит заголовки и пустое тело. На практике реальные API не парятся и в 95% случаев возвращают код 200, а детали успешной операции отсылаются в теле.
  • 3xx — перенаправление — запрос следует выполнить по другому адресу, который передаётся в заголовке Location. Частые: 301 — документ перенесён навсегда, 302 — документ перенесён временно. Они довольно критичны для поисковых ботов, которые индексируют ваш сайт. 301 говорит боту, чтобы он запомнил новый адрес страницы, а прежний забыл.
  • 4xx — ошибка клиента — запрос содержит не все или некорректные данные (400), требуется аутентификация (401) или не хватает прав на выполнение операции (403), запрошенной страницы не существует (404) или http метод запроса для этой страницы запрещён (405).
  • 5xx — ошибка на сервере — сервер не справился или произошла непредвиденная ошибка (500), ошибка обработки запроса вышестоящим сервером, например php-fpm не отвечает nginx’у (502), сервер временно не отвечает по техническим причинам (503), сервер не дождался ответа и запрос отвалился по таймауту (504). Например, стандартное ограничение на время выполнения php-скрипта — 30 секунд. Если скрипт делает запрос к стороннему ресурсу, который под нагрузкой, то nginx покажет 504ю ошибку.

При этом даже неуспешный статус не запрещает серверу вернуть веб-страницу, которую браузер отобразит как ни в чём не бывало. Попробуйте зайти на несуществующую страницу моего блога: https://maxkuznetsov.ru/non-existed-page. Сервер вернёт 404 вместо 200, но мы всё равно можем показать пользователю что-то полезное.

заголовки

Заголовки сервера выполняют ту же роль, что и заголовки запроса. Есть общие заголовки, как Cache-Control, но есть и свои уникальные.

  • Allow — определяет список разрешённых http методов для запросов
  • Location — адрес для перенаправления.
  • WWW-Authenticate — информация про метод аутентификации, запрос должен послать соответствующую информацию в хедере Authorization.

Тело ответа также отделяется от группы заголовков пустой строкой. При этом в теле может передаваться что угодно — текст, html, json, xml, картинки и прочие файлы. Все они отдаются браузеру в одинаковом формате, но с отличающемся заголовком Content-Type, который и поясняет браузеру, как отобразить контент пользователю: как html-страницу, как картинку, показать встроенный в браузер PDF-просмотрщик или начать скачивание файла.

Про аутентификацию и авторизацию

Если посмотреть на структуру HTTP запросов и ответов становится понятно, что каждый запрос для веб-сервера является изолированным и не сохраняет состояния. То есть если вы сделаете два одинаковых запроса с одного браузера, веб-сервер обработает их так, будто они были присланы разными пользователями.

В жизни это ограничение обходят двумя путями:

  1. хранят уникальный идентификатор сессии в куках (cookies), которые браузер по требованию сервера сохраняет локально и затем прикрепляет к каждому запросу в виде заголовка «Cookie». Cервер при каждом запросе разбирает заголовок с куками и по сохранённому там идентификатору «узнаёт» пользователя.
  2. через заголовок Authorization браузер посылает серверу в каждом запросе токен (форматы могут быть разными), по которому сервер определяет пользователя аналогично сессиям. Этот способ чаще всего используется в API.

Поскольку http протокол передаёт все данные в незащищённом виде, то ни один из этих способов не является безопасным, а идентификатор сессии или токен могут быть легко перехвачены злоумышленником. В качестве решения проблемы следует использовать более безопасного брата HTTP — HTTPS.

Что важно понимать про HTTP

  1. HTTP — это протокол общения клиент-серверных приложений в вебе. Набор правил, который помогает клиентам (прежде всего браузерам) и веб-серверам понимать друг друга.
  2. HTTP — это про формат общения, а не про управление сервером HTTP-командами. Клиент может отправить что угодно: удали страницу сайта, создай нового пользователя, выдай список всех пользователей — но сервер не обязан их выполнять, он лишь обязан ответить в формате HTTP, чтобы клиент его понял. То есть благодаря HTTP сервер поймёт, что клиент хочет, а потом уже решит, как это обработать и вернёт результат. Может быть удалит страницу, а может и нет.
  3. В HTTP общение всегда начинает клиент. А веб-сервер висит и ждёт. Сейчас есть способы инициировать запрос с сервера, но изначально протокол для этого не предназначен.
  4. HTTP-протокол не имеет шифрования, поэтому передавать персональные данные и прочие приватные данные через него не безопасно. В таком случае нужно использовать HTTPS.
  5. Простой способ изучить заголовки запроса и ответа — открыть консоль браузера на нужной странице и обновить её. В разделе Network/Сеть отобразятся все запросы с этой страницы, включая запросы на картинки и статические файлы.

Несколько слов о наступающем будущем — HTTP/2

Первая версия протокола HTTP была принята 20 лет назад. После этого 10 лет была тишина, пока Google не стал разрабатывать свой протокол SPDY поверх HTTP, что дало ускорение работе над HTTP/2. После серёзных подвижек Google отказался от разработки SPDY в пользу HTTP/2.

Вторая версия протокола отличается от первой чуть меньше, чем полностью.

  • Протокол уже стал бинарен, а значит человеко нечитаемый.
  • Несмотря на возможность работать без шифрования, все современные браузеры будут поддерживать именно вариант с шифрованием.
  • В протоколе предусмотрена возможность push-сообщений, инициированных сервером.
  • Протокол позволяет мультиплексирование — отправку нескольких запросов внутри одного соединения.
  • Умеет сжимать данные заголовков.

Новый протокол безопаснее и в несколько раз быстрее. Самое приятное, что последние версии современных браузеров понимают http2, и половина наиболее крупных и популярных сайтов уже готовы к переходу на него. С приходом http2 веб станет ещё более интерактивным, а приложения приблизятся к десктопным.

HTTP запрос

Запрос это сообщение, посылаемое клиентом серверу.
Первая строка этого сообщения включает в себя метод, который должен быть применен к запрашиваемому ресурсу, идентификатор ресурса и используемую версию протокола. Для совместимости с протоколом HTTP/0.9, существует два формата HTTP запроса:

Если HTTP/1.0 сервер получает Простой-Запрос, он должен отвечать Простым-Ответом HTTP/0.9. HTTP/1.0 клиент, способный обрабатывать Полный-Ответ, никогда не должен посылать Простой-Запрос.

Строка статуса

Строка Статуса начинается со строки с названием метода, за которым следует URI-Запроса и использующаяся версия протокола. Строка статуса заканчивается символами CRLF. Элементы строки разделяются пробелами (SP). В Строке Статуса не допускаются символы LF и CR, за исключением заключающей последовательности CRLF.

Следует отметить, что отличие Строки Статуса Полного-Запроса от Строки Статуса Простого- Запроса заключается в присутствии поля Версия-HTTP.

Метод

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

Список методов, допускаемых отдельным ресурсом, может быть указан в поле Заголовка-Содержания «Баллов». Тем не менее, клиент всегда оповещается сервером через код статуса ответа, допускается ли применение данного метода для указанного ресурса, так как допустимость применения различных методов может динамически изменяться. Если данный метод известен серверу, но не допускается для указанного ресурса, сервер должен вернуть код статуса «405 Method Not Allowed», и код статуса «501 Not Implemented», если метод не известен или не поддерживается данным сервером. Общие методы HTTP/1.0 описываются ниже.

Метод GET служит для получения любой информации, идентифицированной URI-Запроса. Если URI- Запроса ссылается на процесс, выдающий данные, в качестве ответа будут выступать данные, сгенерированные данным процессом, а не код самого процесса (если только это не является выходными данными процесса).

Метод GET изменяется на «условный GET», если сообщение запроса включает в себя поле заголовка «If-Modified-Since». В ответ на условный GET, тело запрашиваемого ресурса передается только, если он изменялся после даты, указанной в заголовке «If-Modified-Since». Алгоритм определения этого включает в себя следующие случаи:

  • Если код статуса ответа на запрос будет отличаться от «200 OK», или дата, указанная в поле заголовка «If-Modified-Since» некорректна, ответ будет идентичен ответу на обычный запрос GET.
  • Если после указанной даты ресурс изменялся, ответ будет также идентичен ответу на обычный запрос GET.
  • Если ресурс не изменялся после указанной даты, сервер вернет код статуса «304 Not Modified».

Использование метода условный GET направлено на разгрузку сети, так как он позволяет не передавать по сети избыточную информацию.

Метод HEAD аналогичен методу GET, за исключением того, что в ответе сервер не возвращает Тело- Ответа. Метаинформация, содержащаяся в HTTP заголовках ответа на запрос HEAD, должна быть идентична информации HTTP заголовков ответа на запрос GET. Данный метод может использоваться для получения метаинформации о ресурсе без передачи по сети самого ресурса. Метод «Условный HEAD», аналогичный условному GET, не определен.

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

  • Аннотация существующих ресурсов;
  • Добавления сообщений в группы новостей, почтовые списки или подобные группы статей;
  • Для доставки блоков данных обрабатывающим данные процессам
  • Расширение баз данных через операцию добавления;

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

Клиент может предложить URI для идентификации нового ресурса, включив в запрос заголовок «URI». Тем не менее, сервер должен рассматривать этот URI только как совет и может сохранить тело запроса под другим URI или вообще без него.

Если в результате обработки запроса POST был создан новый ресурс, ответ должен иметь код статуса, равный «201 Created», и содержать URI нового ресурса.

Метод PUT запрашивает сервер о сохранении Тела-Запроса под URI, равным URI-Запроса. Если URI-Запроса ссылается на уже существующий ресурс, Тело-Запроса должно рассматриваться как модифицированная версия данного ресурса. Если ресурс, на который ссылается URI-Запроса не существует, и данный URI может рассматриваться как описание для нового ресурса, сервер может создать ресурс с данным URI. Если был создан новый ресурс, сервер должен информировать направившего запрос клиента через ответ с кодом статуса «201 Created». Если существующий ресурс был модифицирован, должен быть послан ответ «200 OK», для информирования клиента об успешном завершении операции. Если ресурс с указанным URI не может быть создан или модифицирован, должно быть послано соответствующее сообщение об ошибке.

Фундаментальное различие между методами POST и PUT заключается в различном значении поля URI-Запроса. Для метода POST данный URI указывает ресурс, который будет управлять информацией, содержащейся в теле запроса, как неким придатком. Ресурс может быть обрабатывающим данные процессом, шлюзом в какой нибудь другой протокол, или отдельным ресурсом, допускающим аннотации. В противоположность этому, URI для запроса PUT идентифицирует информацию, содержащуюся в Содержании-Запроса. Использующий запрос PUT точно знает какой URI он собирается использовать, и получатель запроса не должен пытаться применить этот запрос к какому-нибудь другому ресурсу.

DELETE

Метод DELETE используется для удаления ресурсов, идентифицированных с помощью URI-Запроса. Результаты работы данного метода на сервере могут быть изменены с помощью человеческого вмешательства (или каким-нибудь другим способом). В принципе, клиент никогда не может быть уверен, что операция удаления была выполнена, даже если код статуса, переданный сервером, информирует об успешном выполнении действия. Тем не менее, сервер не должен информировать об успехе до тех пор, пока на момент ответа он не будет собираться стереть данный ресурс или переместить его в некоторую недостижимую область.

Метод LINK устанавливает взаимосвязи между существующим ресурсом, указанным в URI-Запроса, и другими существующими ресурсами. Отличие метода LINK от остальных методов, допускающих установление ссылок между документами, заключается в том, что метод LINK не позволяет передавать в запросе Тела-Запроса, и том, что в результате работы данного метода не создаются новые ресурсы.

UNLINK

Метод UNLINK удаляет одну или более ссылочных взаимосвязей для ресурса, указанного в URI- Запроса. Эти взаимосвязи могут быть установлены с помощью метода LINK или какого-нибудь другого метода, поддерживающего заголовок «Link». Удаление ссылки на ресурс не означает, что ресурс прекращает существование или становится недоступным для будущих ссылок.

Поля Заголовка-Запроса

Поля Заголовка-Запроса позволяют клиенту передавать серверу дополнительную информацию о запросе и о самом клиенте.

Кроме того через механизм расширения могут быть определены дополнительные заголовки; приложения, которые их не распознают, должны трактовать эти заголовки, как Заголовки-Содержания.

Ниже будут рассмотрены некоторые из Заголовков-Запроса.

В случае присутствия поля From, оно должно содержать полный E-mail адрес пользователя, который управляет программой-агентом, осуществляющей запросы. Этот адрес должен быть задан в формате, определенном в RFC 822. Формат данного поля следующий: From = «From» «:» спецификация адреса. Например:

From: webmaster@WWW.org

Данное поле может быть использовано для функций захода в систему, а также для идентификации источника некорректных или нежелательных запросов. Оно не должно использоваться, как несекретная форма разграничения прав доступа. Интерпретация этого поля состоит в том, что обрабатываемый запрос производится от имени данного пользователя, который принимает ответственность за применяемый метод. В частности, агенты-роботы должны использовать этот заголовок для того, чтобы можно было связаться с тем человеком, который отвечает за работу робота, в случае возникновения проблем. Почтовый Internet адрес, указывающийся в этом поле, не обязан соответствовать адресу того хоста, с которого был послан данный запрос. По возможности, адрес должен быть доступным Internet адресом вне зависимости от того, является ли он в действительности Internet E-mail адресом или Internet E-mail представлением адреса других почтовых систем.

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

If-Modified-Since

Поле заголовка If-Modified-Since используется с методом GET для того, чтобы сделать его условным: если запрашиваемый ресурс не изменялся со времени, указанного в этом поле, копия этого ресурса не будет возвращена сервером; вместо этого, будет возвращен ответ «304 Not Modified», несодержащий Тела- Ответа.

Пример использования заголовка:

If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT

Целью этой особенности является предоставление возможности эффективного обновления информации локальных кэшей с минимумом передаваемой информации. Тот же результат может быть достигнут применением метода HEAD с последующим использованием GET, если сервер указал, что содержимое документа изменилось.

User-Agent

Поле заголовка User-Agent содержит информацию о пользовательском агенте, пославшем запрос. Данное поле используется для статистики, прослеживания ошибок протокола, и автоматического распознавания пользовательских агентов. Хотя это не обязательно, пользовательские агенты должны всегда включать это поле в свои запросы. Поле может содержать несколько строк, представляющих собой название программного продукта, необязательную косую черту с указанием версии продукта, а также другие программные продукты, составляющие важную часть пользовательского агента. По соглашению, продукты указываются в списке в порядке убывания их значимости для идентификации приложения.

User-Agent: CERN-LineMode/2.15 libwww/2.17b3

Строка, описывающая название продукта, должна быть короткой и давать информацию по существу — использование данного заголовка для рекламирования какой-либо другой, не относящейся к делу, информации не допускается и рассматривается, как не соответствующее протоколу. Хотя в поле версии продукта может присутствовать любая строка, данная строка должна использоваться только для указания версии продукта. Поле User-Agent может включать в себя дополнительную информацию в комментариях, которые не являются частью его значения.

Комментарии и пожелания присылайте по адресу : webmaster@genesis.ricor.ru
Copyright ╘ 1998 Gensis Net. All rights reserved.

Протокол HTTP

XYZ School

HTTP — это упрощенный протокол прикладного уровня, который размещается поверх TCP и в основном известен как транспортный канал для World Wide Web и локальных интрасетей. Однако это классический протокол, который используется помимо гипертекста для многих других задач, например, в серверах доменных имен и системах распределенного управления объектами посредством своих методов запросов, кодов ошибок и заголовков. Сообщение HTTP представляется в MIME-подобном формате; оно содержит метаданные о сообщении (например, тип его содержания и длину) и информацию о запросе и ответе, например, метод, используемый для отправки запроса.

Существуют два основных компонента, от которых зависит Web: сетевой протокол TCP/IP и HTTP. Почти все события в Web происходят через HTTP, и этот протокол преимущественно используется для обмена документами (такими, как Web-страницы) в World Wide Web.

HTTP — это протокол приложения клиент-сервер, через который взаимодействуют две системы, обычно использующие соединение TCP/IP. HTTP-сервер — это программа, слушающая на порте машины входящие HTTP-запросы.

HTTP-клиент через сокет открывает соединение с сервером, отправляет сообщение с запросом на конкретный документ и ждет ответа от сервера. Сервер отправляет сообщение, содержащее код нормального или аварийного завершения, заголовки с информацией об ответе и (если запрос обработан успешно) требуемый документ. Общий формат HTTP-сообщения одинаков для запросов и ответов:

В сообщение может входить любое число заголовков, и каждый из них располагается на отдельной строке (т.е. каждому заголовку предшествуют символы возврата каретки и перевода строки). Тело сообщения присутствует необязательно, но если оно имеется, то отделяется от заголовков двумя последовательностями CRLF.

В протоколе HTTP используются постоянные и непостоянные соединения. Непостоянные соединения применяются по умолчанию в версии 1.0 HTTP, в то время как постоянные соединения ~ в версии HTTP 1.1. Соединение называют , если любое TCP-соединение закрывается сразу же, как только сервер отправляет клиенту требуемый объект. Это означает, что соединение используется только для одного запроса и одного ответа и не сохраняется для других запросов и ответов.

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

HTTP-заголовки

HTTP-сообщение состоит из начальной строки, за которой следуют набор заголовков, пустая строка и некоторые данные. Начальная строка задает действие, требуемое от сервера, тип возвращаемых данных или код состояния.

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

Заголовки запросов

К числу наиболее важных HTTP-заголовков, которые можно включать в запросы, но нельзя включать в ответы, относятся:

Заголовок Accept

Это список MIME-типов, принимаемых клиентом, в формате тип/подтип. Элементы списка должны разделяться запятыми:

Элемент */* указывает, что все типы будут приняты и обработаны клиентом. Если тип запрошенного файла не может быть обработан клиентом, возвращается ошибка HTTP 406 «Not acceptable» (недопустимо).

Заголовок From

Указывает адрес электронной почты в Интернете учетной записи пользователя, под которой работает клиент, направивший запрос:

Позволяет клиенту указать адрес (URI) ресурса, из которого получен запрашиваемый URI. Этот заголовок дает возможность серверу сгенерировать список обратных ссылок на ресурсы для будущего анализа, регистрации, оптимизированного кэширования и т.д. Он также позволяет прослеживать с целью последующего исправления устаревшие или введенные с ошибками ссылки:

Представляет собой строку, идентифицирующую приложение-клиент (обычно браузер) и платформу, на которой оно выполняется. Общий формат имеет вид: программа/версия библиотека/версий, но это не неизменный формат:

Эта информация может использоваться в статистических целях, для отслеживания нарушений протокола и для автоматического распознавания клиента. Она позволяет приспособить ответ так, чтобы не нарушить ограниченные возможности конкретного клиента, например неспособность поддерживать HTML-таблицы.

Заголовки ответов

В ответы могут включаться следующие заголовки:

Заголовок Content-Type

Используется для указания типа данных, отправляемых получателю или, в случае метода HEAD, тип данных, который был бы отправлен в ответ на запрос GET:

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

Определяет точное расположение другого ресурса, к которому может быть перенаправлен клиент. Если это значение представляет собой полный URL, сервер возвращает клиенту «redirect» для непосредственного извлечения указанного объекта:

Если ссылка на другой файл относится к серверу, должен указываться частичный URL.

Заголовок Server

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

Общие заголовки

Несколько заголовков могут включаться как в запрос, так и в ответ, например:

Заголовок Date

Используется для установки даты и времени создания сообщения:

В НТТР/1.0 мы могли использовать в запросе заголовок Connection, указывая, что хотим сохранить соединение после отправки ответа. Теперь такое поведение принято по умолчанию, и в HTTP/1.1 можно использовать заголовок Connection, чтобы указать, что постоянное соединение не нужно:

HTTP-запросы

Каждый клиент посылает запрос, и сервер на него отвечает. Все запросы и ответы состоят из трех частей, а именно: строки запроса или ответа, секции заголовков и тела сущности (любого содержания, отправляемого вместе с сообщением, например, страницы HTML для отображения в браузере или данных формы, пересылаемых на сервер).

Клиент связывается с сервером в назначенном номере порта (по умолчанию равном 80) и запрашивает у сервера документ, задавая HTTP-команду, называемую методом, за которой следует адрес документа и номер версии HTTP. Клиент также отправляет серверу необязательную информацию в заголовках, чтобы сообщить серверу о своей конфигурации и приемлемых для него форматах документов. Информация заголовка дается в одной строке вместе с именем и значением заголовка. После заголовков клиент посылает пустую строку. Затем клиент отправляет дополнительные данные. Это могут быть данные формы, отправляемые на сервер методом POST, или файл, копируемый на сервер методом PUT.

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

Теперь исследуем каждую из этих секций. Метод — это HTTP-команда, начинающая первую строку запроса клиента. Метод информирует сервер о цели запроса клиента. Для HTTP определены семь методов: GET, HEAD, POST, OPTIONS, PUT, DELETE и TRACE, но HTTP-серверы могут также реализовать методы расширения, не определенные протоколом HTTP. Заметим, что названия методов зависят от регистра клавиатуры, поэтому, например, слово get не будет распознано как допустимый метод.

Метод GET используется для запроса информации, расположение которой на сервере определяется заданным URI. Этот метод широко применяется браузерами, чтобы извлекать документы для просмотра. Результат запроса GET генерируется разными способами. Это может быть файл, доступный с сервера, вывод программы, вывод, полученный на устройстве, и т. д.

Когда клиент в своем запросе использует метод GET, сервер отправляет ответ, содержащий строку состояния, заголовки и метаданные. Если сервер не может обработать запрос из-за ошибки или отсутствия авторизации, он отправляет объяснение в текстовом виде, помещая его в ответе в секцию данных.

Секция тела о сути запроса GET всегда остается пустой. Запрошенный клиентом ресурс (файл или программа) идентифицируется по его полному пути на сервере. Любая дополнительная информация, например, значения из формы, которую клиенту нужно отправить серверу, присоединяется вслед за URI как строка запроса:

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

Метод POST позволяет отправить данные серверу в клиентском запросе. Эти данные посылаются программе обработки данных, к которой у сервера есть доступ. Метод POST может использоваться для многих приложений, например, для обеспечения входных данных сетевых служб, программ интерфейса командной строки и т.д. Данные отправляются на сервер в секции тела сути клиентского запроса. Обработав запрос POST и заголовки, сервер передает это тело программе, указанной в URI.

В методе OPTIONS запрашивается информация о поддержке HTTP на Web-cepвeре. Метод OPTIONS может применяться с URL, чтобы извлечь информацию о конкретном документе или, с групповым символом *, чтобы получить информацию о возможностях сервера в целом. Информация возвращается в заголовках ответа.

HTTP-ответы

Ответ сервера на запрос клиента также подразделяется на три части. Первая строка—это строка ответа сервера, содержащая номер версии HTTP, номер, указывающий состояние запроса, и краткую фразу, описывающую это состояние. Далее следует информация заголовков, за ней — пустая строка и тело сущности (которое может быть пустым, например, в ответах на запросы HEAD и OPTIONS).

В качестве версии HTTP указывается та версия, которую сервер использует в ответе. Код состояния представляет собой трехбайтовое число, указывающее результат обработки сервером запроса клиента. Описание, следующее за кодом состояния, просто дает удобное для восприятия пользователем значение кода состояния. Хотя существует несколько определенных кодов состояния, сервер вправе устанавливать дополнительные коды. Некоторые наиболее распространенные определенные коды приводятся в следующей таблице:

Коды состояния запроса HTTP

Код Описание
200 ОК — запрос был получен и обработан
301 Ресурс перемещен постоянно
302 Ресурс перемещен временно
400 Неверный запрос—сообщение с запросом имеет некорректный формат
401 Несанкционированный доступ — у пользователя нет прав для доступа к запрошенному документу.
402 Ресурс доступен за плату
408 Тайм-аут запроса
500 Внутренняя ошибка сервера—ошибка помешала HTTP-серверу обработать запрос

После строки состояния сервер отправляет клиенту в заголовках информацию о себе и запрошенном документе. Заголовки завершаются пустой строкой (т.е. двумя идущими подряд последовательностями CRLF).

Если клиент запрашивал данные и запрос обработан успешно, эти данные будут отправлены в теле сущности после заголовков ответа. Они могут представлять собой копию запрошенного файла или содержание, сгенерированное динамически, например страницу ASP.NET или сценарий на стороне сервера. Если запрос клиента не выполнен, могут быть предоставлены дополнительные данные объясняющие, почему сервер не смог выполнить этот запрос.

В HTTP 1.0 сервер, завершив отправку запрошенных данных, отсоединяется от клиента и транзакция на этом заканчивается, если только не был отправлен заголовок Connection: Keep-Alive. Однако в HTTP 1.1 сервер должен поддерживать соединение, позволяя клиенту делать дополнительные запросы, даже если заголовок Connection не был отправлен. Если не нужно такое поведение, следует отправить заголовок Connection: close, который указывает, что после отправки ответа соединение должно быть закрыто.

Такие разные заголовки! Изучаем HTTP-взаимодействие

OFFZONE Moscow

Большинство из нас многократно слышали про способность сайтов узнавать информацию о посетителе (и всевозможные предупреждения по этому поводу), которую невозможно узнать из IP-адреса. Это такие «личные» данные, как операционная система, используемый браузер, язык системы. Кто же так жестоко палит нас? И как можно это использовать в своих благих намерениях? Об этом и многом другом ты узнаешь, прочитав статью до конца.

Для начала приведу немного теории о том, чем мы пользуемся довольно давно. HTTP (HyperText Transfer Protocol – «протокол передачи гипертекста») – клиент-серверный протокол передачи данных, который служит для получения информации с веб-сайтов. Был предложен создателем всея WWW Тимом Бернерсом-Ли. Структура его проста: тип сообщения, заголовки, тело сообщения. Существуют RFC, стандартизирующие HTTP (последняя версия – 1.1), согласно которым клиент должен посылать серверу заголовки, содержащие ту самую специфическую информацию о системе и браузере. Обычному пользователю это полезно: сайт в зависимости от клиента может выдать специфическую верстку (пример – google.com) или показать информацию на нужном языке. Однако для хакера раскрытие такой информации может быть вредно или даже опасно.

Представим ситуацию: некий Иван зашел на сайт, посмотрел на него и решил взломать. Загрузил проверенные соксы, поставил красивый дефейс и через несколько часов/дней сидел в участке. Ведь несложно сопоставить данные взломщика с данными остальных посетителей и найти настоящий IP (очень редко встретишь сайт без логирования). Да, некоторые факторы не учтены, однако, вариант возможный.

Техническая реализация

Итак, нам необходимо подделывать заголовки, которые браузер шлет серверу. Как кросс-браузерное решение я бы предложил старый быстрый Proxomitron. Изначально он предназначен для удаления рекламы и полного управления содержимым страницы, так что замечательно подходит для наших целей. Работает как HTTP-прокси. С первого взгляда интерфейс Proxomitron’а не очень дружелюбен, однако разобраться в нем – дело нехитрое. Если нужно использовать только подделку заголовков – слева убираем все галки кроме второй. Жмем на «Headers» и редактируем правила подмены: сразу после установки – в списке куча правил, добавить свое можно, нажав на кнопку New. Чтобы задействовать фильтр, нужна галка в поле «out». Обязательно прочитай русский хелп к программе – там отлично все расписано.

Я пользуюсь Mozilla Firefox и предпочитаю вместо внешних программ использовать плагины. Tamper Data позволяет перехватывать запросы и редактировать заголовки в реальном времени – незаменимая вещь при ручной проверке. Все просто: в окне плагина жмем «Запустить перехват» и вмешиваемся, когда необходимо. Имеются пресеты и богатые возможности по изменению значений заголовков.

Для постоянной же подмены заголовков лучше использовать плагин Modify Headers. Сразу после установки необходимо открыть настройки и поставить галку на «Always on», дабы подмена происходила всегда. Настройка элементарная – открыть главное окно плагина и добавить правил. Первое поле – выбор действия («Add» – добавить, «Modify» – изменить, «Filter» – исключить из запроса), второе – название заголовка, третье – значение; в четвертом поле можно оставить записку. Правила можно двигать, включать и выключать.

Вектор поиска

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

PHP-include не подходят, ибо файлы никогда не подключают в зависимости от заголовков. Хотя и есть возможные исключения, к примеру, инклуд файла в зависимости от языка. На практике не встречал.

Пассивные XSS основаны на том, что запрос будет делать непосредственно пользователь. Заставить жертву подменить заголовок едва ли удастся, именно поэтому этот тип нам не подходит. Единственная возможность использовать найденные подменой заголовков пассивные XSS – это если на страницу пишется Referer (ссылающаяся страница), да не простой, а дополнительно декодированный (избавленный от %xx). Тогда можно скриптом перенаправить жертву на себя с нужным параметром и после – на уязвимую страницу, так что параметр запишется в месте Referer’а. Сработает в идеальных условиях, на практике также не встречал.
Активные XSS подходят. Смысл в том, чтобы веб-приложение занесло в базу наш заголовок, а после показало администратору, естественно, не обработав.

SQL-инъекции подходят. Это самый простой тип, достаточно, как и обычно, подставлять кавычку.

PHP-исполнение кода очень редко встречается вообще, а с участием заголовков – еще реже. Однако бывает. Тут преимущество нашего метода в том, что GET и POST данным менее доверяют.

Итак, теперь необходимо составить строку, которая позволяла бы определить наличие уязвимости. Кавычка обязательна. Далее необходимо выйти из возможных тегов: простейший способ сделать это символами «>. И последнее – алерт, дабы не проспать. В итоге у меня вышло ‘»>. Ставить на обнаружение исполнения кода я не стал; если желаешь, добавь, например, чтобы вызвать ошибку и заметить уязвимость. Также можно добавить в конец обратный слеш (пытаясь экранировать закрывающую кавычку), бывают случаи с фильтрацией кавычек, бывают без нее. Считаешь, что строка слишком длинная и может обрезаться? Замени “document.cookie” на «1». Тут главное – приложить фантазию и создать свой идеальной вектор поиска уязвимостей.

Интересные заголовки

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

User-Agent

Главный враг шпиона. Больше всех выдает информации о посетителе: браузер, его версию и язык, движок браузера, версию движка, операционную систему. Данные могут быть написаны как угодно, однако примерный формат есть:

Браузер/Версия (Платформа; Шифрование; Система, Язык[; Что-нибудь еще]) [Дополнения].

В качестве платформы чаще всего можно увидеть X11 или Windows, иногда туда прямиком помещают систему, убирая соответствующий заголовок после. «Шифрование» может принимать три значения: “N” (None) – отсутствует, “I” (International) – слабое шифрование ключом до 40 бит, “U” (USA) – сильное шифрование с ключом 128 бит. Сейчас все браузеры используют только сильное шифрование. После скобки добавляется различная информация вроде движка, плагинов, дополнений.

В качестве браузера для совместимости очень часто указывают Mozilla, а уже после информации дописывают реальное название. Это связано с тем, что издавна девелоперы должны были (или просто любили) делать сайты не в соответствии с принятыми стандартами Консорциума Всемирной паутины (World Wide Web Consortium, W3C), а под наиболее распространенные в данное время браузеры, что приводило к еще большему доминированию последних. И сейчас такая практика существует, однако с тем отличием, что популярным браузерам даны дополнительные возможности, связанные с использованием JavaScript’а (например, на распространенном форуме Invision Power Board, в ветке 2.3.x, посмотрите профиль участника с отфильтрованным заголовком и без). Поэтому советую в строку User-Agent’а в любом случае включать определение распространенного браузера.

Referer

Сообщает о странице, с которой пришел пользователь. Заголовок, сильно полезный веб-мастерам для отслеживания путей попадания на их сайты. Написание – ошибка от английского «Referrer» («перенаправляющий»). Большинство браузеров позволяет отключать передачу этого заголовка, однако при этом обычно возникают проблемы с файлообменниками и сайтами-архивами, которым очень жалко отдавать контент без показа рекламы, так что они позволяют скачивать только при наличии их сайта в реферере. Можно подменять ради просмотра отдельных элементов сайта – например, картинок – без загрузки страниц, где они размещены (при условии, что без подделки это сделать не удастся). При пентесте стоит учитывать, что часто в базу записывают URL не полностью, а лишь нужную его часть, поэтому стоит пробовать «http://evil», «http://example.com/evil» и т.д.

X-Forwarded-For

Нестандартный заголовок, используемый неанонимными прокси-серверами для передачи реального IP клиента. Мы не можем вставить кавычку в определяемый сервером IP, зато можем заставить его думать, что это – всего лишь прокси, а настоящий IP – вот он, в X-Forwarded-For. Конечно, далеко не все скрипты используют и полагаются на XFF, но этот заголовок принято хотя бы логировать. Нельзя забывать проверять веб-приложение на наивность (да-да, некоторые сайты, увидев этот заголовок, забывают про обычный IP и пользуются только тем, что передано в данном заголовке). Формат: X-Forwarded-For: client_ip, proxy1_ip, . proxyN_ip.

Accept-Language

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

Accept-Charset

Сообщает допустимые кодировки и их приоритет. Не самый интересный заголовок, но стоит обратить на него внимание, ибо он может выдать твою систему простым «windows-1251».

X-Requested-With

Нестандартный заголовок, сообщает средство запроса. Используется при запросах из JavaScript без перезагрузки страницы. Соответственно полезен для имитации AJAX (Asynchronous Javascript and XML) запросов, для этого необходимо установить его в значение «XMLHttpRequest».

Authorization

Если серверу необходима авторизация пользователя, он об этом прямо сообщает, а браузер предлагает ввести логин и пароль. Именно в заголовке Authorization они передаются в виде «Basic base64(user:pass)». Такую авторизацию намного удобней брутить, чем те, которые располагаются непосредственно на странице (POST).

Cookie

Собственно, в этом заголовке посылаются (внезапно) куки. Для танкистов поясню: это информация, которую сайт сохраняет на компьютере клиента. Подмена данного заголовка полезна тогда, когда изменение кукисов невозможно другим образом.

Применение

Итак, практика. Я проводил исследование, в ходе которого некоторое время использовал «пассивное обнаружение уязвимостей». Суть в том, что достаточно однажды выставить замену заголовков, а после – лишь ловить алерты и исследовать бреши.

ЗаголовокЗначениеВключен
User-Agent Opera/10.60 Да
Referer Да
X-Forwarded-For Да
Accept-Language en,en-US;q=0.9 Нет
AuthorizationBasic MScyMzo0JzU2 Нет
X-Requested-WithXMLHttpRequest Нет
CookiePHPSESSID=!Нет

С первыми тремя, думаю, понятно. Если в ладах с английским, включи на постоянную подмену Accept-Language, дабы принимали за англичанина. Authorization уместно включать только при проверке конкретного сайта, ибо рискуете не понять, если где-нибудь действительно понадобится авторизация. Про применение заголовков X-Requested-With и Cookie я уже писал, однако поясню последний. В PHP довольно удобно хранить данные в сессиях: собственно данные – на сервере, у клиента – только идентификатор в куке «PHPSESSID» (название можно менять, но делают это, естественно, редко). Так вот, иногда этот идентификатор может состоять только из символов a-z, A-Z, 0-9 и ‘-,’, и при передаче чего-то иного вызывается ошибка, раскрывающая абсолютный путь:

Warning: session_start() [function.session-start]: The session id contains illegal characters, valid characters are a-z, A-Z, 0-9 and ‘-,’ in /var/www/data/www/login.php on line 2

Первое, на что я наткнулся – это поплывшая разметка. Да, действительно на многих сайтах происходил выход из какого-нибудь тега (бесполезный), и дальше образовывалась каша. Если ты решишь провести собственно исследование – будь готов. Еще одно: если чувствуешь, что что-то идет не так (например, не дают скачать файл, не показывают картинку во всю ширину, не работает перенаправление), выключай подмену Referer’а.

Никто не знает и не узнает, сколько алертов выловили админы, сколько они их увидели у себя в логах, сколько осталось незамеченными. Однако один случай обнаружения интересной активной XSS есть точно – гугловский сервис FeedBurner, который умеет обрабатывать RSS-фиды и логировать трафик сайта. Но последнее делал он не слишком качественно – не фильтровался Referer. Подробнее об этой уязвимости читай на raz0r.name/vulnerabilities/aktivnaya-xss-na-feedburner/ (wp.me/pft5J-4a) (не удивляйся, увидев алерт из-за XFF :)).

Довольно весело было заходить на всякие сайты с DLE (DataLife Engine), ибо популярный модуль DLE Referer Module не дружил (и не дружит) с экранированием плохих символов. Для убедительности советую пройтись по сайтам продавцов ICQ UIN’ов и увидеть много MySQL-ошибок, хотя картина уже не будет слишком печальной – я разослал владельцам сообщения об уязвимости, ведь неприятно, когда твои платежные данные и ссылки на оплату можно подменить.

Некоторое время назад на php.ru можно было наблюдать ошибки нефильтрации Referer’а и XFF. На данный момент уязвимость закрыта. Из ошибки с реферером:

MySQL Error = You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘»‘)’ at line 1

SQL = INSERT INTO oops_sessions (ID,UID,START,LAST,IPS,PAGES,PAGE,DATA,REFFER) VALUES (‘dpdu7rh90ehfsc62′,’0′,1238958331,1238958331,’xxx.xxx.xxx.xxx’,1,’/’,’a:1:’,’SQL-Inj’here’)

Еще один пример – cx75planet.ru. Уязвимы User-Agent и XFF. IPB показывает весь запрос. Кроме этих брешей, была замечена еще туча SQL-ошибок на сайтах всех мастей, большинство из которых просто имели самописные модули обработки информации о браузерах, рефах и т.д. Предоставляю тебе возможность найти их все :).

Подмена заголовков в PHP

Естественно, после ручного анализа SQL-уязвимости наступает работа автоматики. Подбор столбцов, полей, вынимание логинов, паролей и хешей – все уже давно делают скрипты. Однако большинство из них направлено на GET, POST или Cookie. Покажу, как можно получить страницу, посылая нужные заголовки. Предположим, у нас есть массив с такими заголовками и вызов функции request, которая должна возвращать страницу:

$headers = array (
‘User-Agent: Babytoy/0.5’,
‘Referer: http://refrefref.ref/omg.pl’
);
$html = request_socket(‘http://127.0.0.1/showmeheaders.php’, $headers);
echo $html;

Есть несколько основных видов получения страницы из PHP (полные версии функций ищи на диске ][):

Сокет

Заголовки напишешь в любом случае. Генерация пакета:

$packet = «GET HTTP/1.1rn»
. «Host: rn»
. implode(«rn», $headers) . «rn»
. «Connection: Closernrn»;
— file_get_contents()

Воспользуемся контекстом для задания нужных параметров:

$opts = array (
‘http’ => array (
‘header’ => implode(«rn», $headers) . «rn»
)
);
$context = stream_context_create($opts);
return file_get_contents($url, false, $context);

В curl’е все проще простого: вместе с остальными параметрами достаточно указать curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

Заключение

Хотелось бы обратить внимание, что подмена заголовков – не панацея от сливания информации. Не стоит забывать о JavaScript’е, Flash’е и интерактивных элементах, которые тоже вправе много чего разболтать. Используй NoScript и прочие AdBlock’и. Всегда экспериментируй и прикладывай выдумку, ищи там, где не ищет никто. Удачи!

HTTP. Какую информацию браузер передает в HTTP заголовках

HTTP — это HyperText Transfer Protocol (протокол передачи гипертекста), который используется для коммуникации с сайтом. Все, что вы сейчас видите в окне браузера, получено с помощью этого протокола.

Когда вы открываете сайт, браузер обменивается с ним данными в HTTP заголовках (HTTP Headers) и отправляет различную информацию о себе.

Запрос браузера может выглядеть так:

В чем опасность HTTP заголовков?

Становится доступна информация о вашем браузере, системе и IP.

При использовании прозрачных прокси настоящий IP может передаваться в специальных заголовках, тем самым раскрывая вас.

Через Referer становится доступен адрес источника, с которого вы перешли на сайт или сделали запрос.

На основе этих данных сайты могут составить уникальный цифровой отпечаток (fingerprint), с помощью которого вас можно идентифицировать даже после смены IP.

Что такое User Agent?

User Agent — это часть HTTP заголовков, которая содержит информацию о браузере и операционной системе.

Методы сохранения анонимности:

User Agent можно изменить в настройках некоторых браузеров или с помощью специальных плагинов (например, RMOSChange для Firefox / Internet Explorer, User-Agent Switcher для Chrome, User Agent Changer для Opera).

Для маскировки Referer можно использовать такие плагины, как Referer Control (для Chrome).

Существуют утилиты и плагины для прямого редактирования HTTP-запросов. (например, Modify Headers для Google Chrome)

Как вручную изменить User Agent в Firefox:

Введите в адресной строке: about:config и нажмите “I’ll be careful, i promise!”.

Найдите в появившемся окне, используя поиск: useragent

Убедитесь, что параметра general.useragent.override не существует.

Кликните правой кнопкой на пустом месте и выберите “New” —> “String”.

Введите в окне: general.useragent.override и нажмите “Ок”.

Введите новый User Agent (например, Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A ) и нажмите “Ок”.

Список примерных конфигураций user agent’ов вы можете найти в Интернете (например, здесь, здесь или здесь).

Вы можете проверить на нашем сайте HTTP-заголовки, которые отправляет ваш браузер:

QUERY_STRING — параметры, переданные скрипту, если строка запроса представляет собой адрес.

REQUEST_METHOD — метод запроса, который применялся для вызова скрипта GET или POST.

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

SERVER_PROTOCOL — имя и версия информационного протокола, через который была запрошена страница, к примеру ‘HTTP/1.1’.

REMOTE_ADDR — IP-адрес удаленного клиента, с которого был сделан запрос.

REMOTE_PORT — порт клиента, через который было установлено соединение с сервером.

HTTP_ACCEPT — предпочтения клиента относительно типа запрашиваемого документа.

HTTP_ACCEPT_LANGUAGE — предпочтения клиента относительно языка запрашиваемой страницы.

HTTP_USER_AGENT — информация о версии и типе операционной системы и браузера посетителя.

HTTP_ACCEPT_ENCODING — список кодировок сжатия, которые поддерживает браузер.

HTTP_HOST — имя сервера (в большинстве случаев совпадает с доменным именем сайта, расположенного на сервере).

HTTP_CONNECTION — тип соединения браузера с сервером. Значение keep-alive означает, что браузер поддерживает постоянное соединение и в течение одного сеанса может делать несколько запросов.

HTTP_COOKIE — данные о cookies сессии, сохраненные в браузере.

HTTP_UPGRADE_INSECURE_REQUESTS — передает значение “1” для автоматического перехода небезопасных (например, HTTP: ) запросов на безопасную альтернативу (например, HTTPS: ), прежде чем браузер загрузит их.

HTTP_CACHE_CONTROL — max-age определяет “срок годности” файла (в секундах), по истечении которого файл необходимо загружать заново.

HTTP_REFERER — адрес источника, с которого посетитель сделал запрос или зашел на сайт.

H Анатомия HTTP-запроса в черновиках

Анатомия HTTP-запроса

Каждый хороший разработчик должен знать, что происходит под капотом после того, как пользователь введет URL сайта в адресной строке браузера и нажмет кнопку «Перейти». На самом деле это самый частый вопрос на собеседовании. В этой статье мы разберем, что происходит во время обработки HTTP-запроса.

Терминология

Для того, чтобы понять, как обрабатывается запрос вам нужно знать следующие определения:

  • веб-сервер — программное обеспечение на сервере, которое позволяет принять и обработать входящий запрос
  • DNS — сокращение от Domain Name System (система доменных имен), которая просто как телефонная книга, связывает адрес сайта с IP-адресом
  • код ответа — число, которое обозначает тип ответа сервера. Общеизвестными являются 200 (все хорошо), 404 (не найдено), 302 (перенаправление), 500 (внутренняя ошибка сервера)

Шаг 1: поиск DNS

На самом деле веб-адреса представляют собой простую строку, которую выглядит как-то так: 216.58.198.174. Если вы перейдете по этому адресу с помощью браузера, то откроется Google. Доменное имя (google.com) это просто псевдоним, который позволяет пользователю легче запомнить адрес.

Итак, когда пользователь вводит доменное имя (например, google.com), браузер делает запрос к DNS и получает IP-адрес, который связан с этим именем.

Думайте о DNS как о телефонной книге. Вместо того, что запоминать номер Вани, вы можете записать его в телефонную книгу. Затем вы можете просто нажать «позвонить Ване» и ваш телефон найдет его номер в базе, и позвонит по этому номеру. В этой аналогии имя «Ваня» — это доменное имя, его номер — это IP-адрес, а телефонная книга — это DNS.

Шаг 2: выполнение запроса

После того, как браузер получил IP-адрес сервера от DNS, он может приступить к созданию запроса. Запрос содержит в себе заголовок и также может содержать тело запроса (например, данные из формы, которую отправил пользователь).

Заголовок содержит в себе следующие параметры:

  • Request method (метод запроса) — чаще всего это либо GET, либо POST. Обычно GET-запрос используется для получения данных (например при отображении веб-страницы), а POST — при отправке формы или данных (например, при авторизации или отправке почты).
  • Request URL (URL-запроса) — это полный URL, который говорит серверу, какую страницу запрашивает пользователь
  • Protocol (протокол) — версия протокола HTTP (обычно 1.2)

В итоге запрос будет выглядеть так:

Дополнительная информация может быть добавлена ниже. Они представлены в виде пар ключ/значение, где ключ — это идентификатор, название, а значение — собственно сам кусочек информации. Пример ниже включают в себя информацию о браузере пользователя (user-agent), куки (cookies), тип содержимого (content type), хост (host), которое в данном случае является названием домена и т.д. Полный HTTP-запрос выглядит как-то так:

Шаг 3: ответ сервера

После того, как сервер получил запрос, он генерирует ответ. Так же как и запрос ответ содержит различную информацию, включая:

  • HTTP-код ответа (смотрите раздел «Терминология»). Если запрос прошел успешно, он (код) обычно равен 200 (все хорошо)
  • дата и время генерации ответа
  • HTML-содержимое страницы

Обычный ответ сервера выглядит как-то так:

Поле Content-Type говорит, браузеру, какой тип содержимого ему следует ожидать. В данном случае это простой HTML. Таким образом, браузер узнает, что ему нужно отрендерить и показать HTML. Тип содержимого может быть также указан как картинка, видео, JSON и т.д. Это поле говорит браузеру, как нужно обработать полученную информацию.

HTML также подключает различные ресурсы, такие как изображения, видео, шрифты или внешние CSS и JavaScript-файлы. Браузер отправляет запросы к серверу для получения этих ресурсов, а затем размещает их на странице. Если вы откроете инструменты разработчика в Google Chrome (Ctrl+Shift+J) и откроете какой-нибудь сайт, то увидите запросы, которые выполнил браузер (вкладка Network).

Анатомия HTTP-запроса

Заключение

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

комментарии ( 9 )

Во-первых, для «оригинал тут» есть выбор публикация/перевод.

Во-вторых статей такого вида уже даже на хабре тонна и непонятно зачем этот мусор нужен ещё раз, да ещё и в хабе «программирование».

Это не считая того, что это же написано в help’е: https://habrahabr.ru/info/help/posts/:

Если нажать на слово «Публикацию» во фразе «Хочу опубликовать публикацию», то ниспадающее меню предложит вам выбрать второй доступный для создания вид записи — «Перевод». Механизм создания тот же, что и у публикации, но есть два дополнительных поля — «Автор оригинала» (тут надо указать имя автора оригинального текста) и «Ссылка на оригинал» (здесь — URL страницы оригинала).

Статья очень-очень базовая. На мой взгляд, ее польза несколько сомнительна, но тем не менее, позволю себе оставить пару замечаний.
Мне кажется, что упоминание того, что заголовок Host с доменным именем используется веб-сервером для возможности одновременной работы нескольких веб-ресурсов на одном IP-адресе заслуживает упоминания даже в такой базовой статье. Хотя бы для того, чтобы новичку было понятно, почему при блокировке одного IP блокируются другие сайты, хостящиеся на том же адресе.
«Заголовок» — это на самом деле «строка запроса» (request line), чтобы не создавать путаницы с заголовками (headers), это проблема не перевода, а оригинала. «Пары ключ-значение» — это как раз заголовки.
И еще, мне кажется, что в самых базовых статьях стоит освещать тот факт, что уже 17 лет протокол HTTP/1.1, позволяет не закрывать соединение после каждого запроса-ответа для того чтобы ускорить работу сети, избавившись от затрат на переподключение для каждого ресурса. Для того, чтобы сервер и клиент понимали, когда данные завершились, используется, на мой взгляд один из самых главных заголовков Content-length, значением которого является размер тела сообщения в байтах. Если игнорировать этот заголовок в своих приложениях, даже при указании HTTP/1.1 в строке ответа сервера, соединение будет фактически HTTP/1.0 (Конечно, если не указан Transfer-Encoding, но вот это уже advanced ИМХО) Вообще, последняя спека написана вполне себе человеческим языком и не слишком длинная.

… а что, новичкам можно давать ошибочную информацию?

А почему в ответ на вопрос «что происходит» выбран именно этот уровень абстракции? Почему не разбираются детали TCP/IP соединения? Или HTTPS, которого сейчас много? Или почему не разбирается, что происходит в браузере между моментом нажатия на Enter и отправкой собственно HTTP-запроса?

В конце концов, почему переход на страницу в браузере приравнивается к HTTP-запросу?

+1
Начиная про то, что запрос имён в DNS не такая и простая штука, как кажется, заканчивая тем, что на шаге 2 перед формированием запроса происходит хотя бы банальное подключение к серверу.

Очередная статья, очень низкого уровня, имхо не годная для хабра, а вот для начинающих эникеев/домохозяек сойдет.

> Анатомия HTTP-запроса
И уж точно статью нельзя назвать «Анатомией http», а так — «беглый осмотр веб-технологий»

Время указано в том часовом поясе, который установлен на Вашем устройстве.

4 примера использования http-заголовков, о которых вы прежде не знали

Перевод статьи «The power of http headers and 4 examples you did not know before».

Photo by Visual Design on Unsplash

Существует достаточно много http-заголовков. Большинство из них достаточно просты. Но есть также довольно мощные и при этом не слишком известные http-заголовки.

Hello http (заголовки)

Практически все в вебе пересылается через http. Эта аббревиатура знакома даже не-разработчикам, потому что они постоянно видят ее как часть ссылок.

Http расшифровывается как Hypertext Transfer Protocol. Этот протокол дает нам возможность пересылать гипертекст между браузером и сервером. Это отличная технология, работающая практически со времен изобретения веба, постоянно развивающаяся и предлагающая все больше крутых функций.

Что такое http-заголовки?

Если вы разработчик, то скорее всего вы уже слышали об http-заголовках, по крайней мере в контексте CORS. Но что из себя представляют эти заголовки и как их использовать?

Давайте сначала разберем, что они делают и как ими пользоваться.

Когда браузер запрашивает ресурс, например, страницу этого блога, он обращается к серверу с запросом. Этот запрос выглядит примерно так:

Вы видите URL или местонахождение ресурса, некоторые сведения о запросе, а также множество заголовков, касающихся запроса. Таким образом ваш браузер сообщает серверу определенные сведения о запросе. Например, какого типа данные он принимает или как клиент обрабатывает кеш.

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

Здесь содержится некоторая информация об использовании ресурса, которую сервер хотел бы сообщить браузеру. Например, если там используются cookies, то в заголовках указывается, какая кодировка применялась.

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

Большинство заголовков имеют довольно хорошие значения по умолчанию, которые можно не менять. При этом некоторые заголовки (например CORS-заголовки) могут представлять особую важность. Но есть еще много заголовков, о которых вы могли никогда не слышать, а между тем они очень полезны и стоит научиться ими пользоваться.

Заголовки, которых вы не знаете

Не волнуйтесь, в этой статье мы не будем касаться CORS. Мы рассмотрим http-заголовки, которые используются довольно редко, но могут помочь существенно улучшить коммуникацию между сервером и браузером.

If-Range

Что это такое и зачем это нужно?

Представьте, что вы начинаете скачивать объемный ресурс, например видео, изображение и т. п., а загрузка прерывается из-за проблем со связью. При помощи If-Range вы можете сообщить серверу, что представление не изменилось и можно переслать запрошенные в Range части. Таким образом будет пересылаться не весь ресурс (заново), а только недостающие части.

Это может быть очень полезно, когда вы работаете с большими ресурсами, а также когда предполагаются проблемы со связью (характерно для мобильных устройств). Благодаря этому заголовку получится загрузить весь ресурс, даже если соединение будет прерываться.

Как пользоваться

Можно использовать или с датой последней модификации ресурса, или с Etag, что может помочь при повреждении ресурса.

Пример

Vary появился в те времена, когда http использовался не только для веб-страниц.

В его основе лежит идея использования http для обмена информацией во многих (разных) форматах. Каким образом? Этот заголовок сообщает серверу, в каком виде нужно предоставить информацию.

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

Пример

Возьмем тот же пример с изображениями, зависящими от устройства. Чтобы сообщить серверу, что он должен получить информацию об устройстве пользователя, вы можете просто передать в заголовке «user agent».

Как пользоваться

Просто вставьте заголовок, который сервер должен проверить, прежде чем решить, какой ресурс отсылать.

Content-Disposition

Когда серверу отправляется запрос для отображения сайта, браузеру понятно, что он должен отобразить ресурс, который придет в ответе. Но может быть и такое, что сервер отсылает ресурс, который браузер должен автоматически начать загружать на компьютер пользователя (это может быть картинка или pdf и т. п.). При помощи заголовка Content Disposition сервер может сообщить браузеру, что именно тот должен делать с прилагаемым ресурсом.

Пример

Если определить значение Content-disposition как attachment, браузер будет знать, что этот ресурс предназначен для скачивания, а не просто для показа.

Как пользоваться

Вы можете определить этот заголовок как inline или attachment, причем inline это значение по умолчанию.

Feature-Policy

Это довольно новый заголовок, поэтому он поддерживается пока только современными браузерами. Но я все равно хочу его упомянуть, потому что считаю очень полезным в некоторых случаях. В общем, Feature-Policy сообщает браузеру, какие функции или API браузер должен предоставить документу и его фреймам для использования.

Например, он может запретить все скрипты или фреймы на сайте, чтобы разрешить чувствительные API, такие как камера или микрофон.

Как пользоваться

Directive — это название функционала. Полный список вариантов можно посмотреть здесь. А allowlist определяет, какие именно источники могут использовать то, что указано в directive.

Пример

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

Другие заголовки

Есть и другие заголовки, стоящие упоминания:

Заключение

Https-заголовки — отличная и очень полезная вещь. Порой они могут быть довольно сложными, а кроме того разработчику тяжело охватить все доступные заголовки и изучить, какие именно преимущества они дают. К тому же, когда вы создаете сайт, особенно в части фронтенда, вы не слишком часто имеете с ними дело, за исключением разве что CORS-заголовков. Но я думаю, что из-за этого разработчики упускают некоторые возможности. Http-заголовки обеспечивают куда лучшую коммуникацию между сервером и пользователями, а все мы знаем, что коммуникация — ключ к хорошим отношениям.

Надеюсь, в этой статье мне удалось познакомить вас с миром http-заголовков. Если здесь пропущен еще какой-то особенно интересный и полезный заголовок — не стесняйтесь добавлять в комментариях!

Горин Павел/ автор статьи

Павел Горин — психолог и автор популярных статей о внутреннем мире человека. Он работает с темами самооценки, отношений и личного роста. Его экспертность основана на практическом консультировании и современных психологических подходах.

Понравилась статья? Поделиться с друзьями:
psihologiya-otnosheniy.ru
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: