В этой статье мы рассмотрим структуру HTTP-сообщений и проанализируем, что происходит за кадром при просмотре веб-страниц.
Автор: Ryan Brown
Протокол HTTP используется в мировой паутине для обеспечения информационных транзакций между клиентом и сервером. На данный момент широко распространена версия HTTP/1.1, однако мировая индустрия вскоре начнет переходить на версию 2.0. Веб-сайты и веб-приложения являются тем, на чем построена всемирная паутина, однако между этими двумя сущностями есть ключевое различие, которое заключается в том, что веб-приложения принимают данные от пользователей. Веб-сайт может быть статическим, а веб-приложение обязательно должно быть динамическим. Веб-сайт хранит содержимое на веб-сервере, и ресурсы веб-сервера могут быть получены клиентами, однако сами ресурсы остаются неизменными. С другой стороны, веб приложение принимает данные от пользователя и динамически генерирует выходные сведения на базе того, что введено. В самом начале мировая паутина состояла только из веб-сайтов. Постепенно сайтов становилось все меньше, веб-приложения стали занимать более доминантную позицию.
Коммуникационная транзакция между клиентом и сервером через протокол HTTP состоит из того, что мы называем HTTP-сообщениями. HTTP-сообщение состоит из HTTP-запроса, посылаемого клиентом серверу, и HTTP-ответа, возвращаемого сервером клиенту на основе полученного запроса. Ключевой момент при тестировании безопасности веб-приложения связан с пониманием логики этих коммуникаций. В этой статье мы рассмотрим структуру HTTP-сообщений и проанализируем, что происходит за кадром при просмотре веб-страниц.
HTTP-запросы
Простой HTTP-запрос:
Рисунок 1: Элементарный HTTP-запрос
GET – HTTP-метод
/ - Путь к ресурсу
HTTP/1.1 – Версия протокола HTTP
HTTP-методы:
Протокол HTTP поддерживает несколько методов. В самой первой версии HTTP/1.0 было три метода: GET, POST и HEAD. В HTTP/1.1 появилось несколько новых методов (см. RFC 2616): OPTIONS, CONNECT, TRACE, PUT и DELETE. В RFC 5789, появившегося в 2010 году, добавился метод PATCH.
Рисунок 2: Перечень методов, поддерживаемых протоколом HTTP/1.1
GET используется для простого запроса ресурсов с веб-сервера. Параметры для этого метода передаются через URL.
POST используется для отсылки данных на веб-сервер через тело HTTP-запроса.
HEAD схож с методом GET, но выводит только заголовки HTTP-ответа, который возвращает сервер.
OPTIONS используется для получения списка методов, принимаемых веб-сервером, которые хранятся в заголовке ‘Allow’ в HTTP-ответе.
PUT предназначен для замены существующего или создания нового ресурса на веб-сервере.
TRACE используется при тестировании и отсылает полное сообщение, полученное веб-сервером, обратно клиенту, что позволяет увидеть конкретное содержимое, полученное веб-сервером.
CONNECT используется редко и совместно с прокси-сервером, который может динамически переключаться в режим туннеля.
PATCH схож с методом PUT. Отличие заключается в этом, что PATCH поддерживает частичную модификацию, в то время как метод PUT поддерживает только полную замену ресурса.
Примечание:
В большинстве приложений используются в основном GET и POST, поскольку HTML поддерживает только эти два метода. Если предполагается использование методов OPTIONS, PUT, DELETE, PATCH, TRACE или CONNECT, необходимо все тщательно продумать и оценить риски в отношении приложения или веб-сервера.
URL:
URL или Uniform Resource Locator (унифицированный указатель ресурсов) является подмножеством унифицированных идентификаторов ресурсов (Uniform Resource Identifiers; URI). Типичная структура URL выглядит так:
[Protocol]://[host]/[resource path]?[parameter1]&[parameter2]
По сути, это способ обозначения местонахождения сетевого ресурса и метод передачи данных целевому ресурсу.
Рисунок 3: Переменная HOST представляет собой сетевой адрес веб-сервера, куда клиент отсылает HTTP-запрос
Рисунок 4: Наиболее распространенные заголовки HTTP-запроса
User-Agent содержит информацию о браузере.
Accept определяет тип содержимого, который может принять клиент.
Accept-Encoding определяет тип кодировки, которую может принять клиент.
Content-Length определяет длину тела запроса в октетах. Это значение не имеет особой важности, но некоторые HTTP-методы (например, PUT) требуют этот заголовок. Если необходимо, в значение этого заголовка можно установить 0.
Referer содержит URL-источник запроса.
Cookie предназначен для отправки cookies на сервер для управления сессией.
Connection используется для того, чтобы сообщить серверу о том, что нужно закрыть соединение или оставить открытым для последующих запросов.
Authorization содержит информацию, имеющую отношение к аутентификации на конкретной платформе.
HTTP-ответы
Пример простого HTTP-ответа:
Рисунок 5: Элементарный HTTP-ответ
В примере выше обратим особое внимание на первую строчку, где указана используемая HTTP-версия и код статуса, возвращенный сервером. Код статуса – важная часть HTTP-сообщения, поскольку свидетельствует о том, как приложение обработало запрос.
Рисунок 6: Перечень кодов статуса
Код ответа «100 Continue» редко когда-либо используется. Наиболее распространенный код «200 OK», который сигнализирует о том, что запрос корректен, ресурс существует, сервер обработал запрос и вернул ресурс в теле ответа. Код 201 означает, что ресурс, запрашиваемый в запросе, был успешно создан. Этот код обычно является результатом запроса с использованием метода PUT. Коды статуса 3xx возвращается приложениями со ссылкой на ресурс, куда нужно перенаправить клиента. Ссылка находится либо в тебе ответа, либо в заголовке «location». Коды статуса 4xx отсылаются в случае, если запрашиваемого ресурса на сервере не существует или пользователь не авторизован для получения содержимого или при возникновении ошибки в запросе, отправленном серверу. Коды статуса 5xx возвращаются в случае, когда сервере возникает ошибка, и нет возможности обработать запрос.
Рисунок 7: Наиболее распространенные HTTP-заголовки ответов
Date содержит дату, когда получен запрос.
Server содержит информацию о веб-сервере (например, IIS/Apache).
X-Powered-By содержит информацию, касающуюся технологии, используемой в скриптах, и текущую версию (например, PHP или Asp.net).
Content-Length схож с аналогичным заголовком в запросе. Содержит длину тела ответа в октетах.
Set-Cookie содержит cookie, используемые клиентом при формировании запроса с целью управления сессией.
Expires содержит, время по истечению которого сервер не будет рассматривать ответ как корректный.
Cache-Control указывает клиенту, нужно ли кэшировать возвращаемые запросы.
Пример HTTP-запроса с использованием метода GET:
Рисунок 8: Пример использования метода GET
Как видно на рисунке выше, в первой строчке указан метод, путь к ресурсу с параметрами и используемая версия HTTP. Во второй строчке указан хост, которому посылается запрос. В третьей строке содержится информация о браузере клиента. В четвертной строчке указан тип данных, который может принимать клиент. В пятой строчке указан язык, используемый клиентом. В шестой – cookie, полученные с сервера для поддержания сессии. Седьмая строчка указывает, нужно ли закрывать сессию или оставить открытой. Последняя строчка нужна при использовании метода GET и является пустой.
Пример ответа на запрос с использованием метода GET:
Рисунок 9: Ответ на запрос с использованием метода GET
В ответе на запрос содержится несколько HTTP-заголовков, которые уже обсуждались ранее.
Пример использования метода POST:
Рисунок 10: Пример отправки информации методом POST
HTTP-запрос с использованием метода POST во многом схож с запросом с методом GET, который мы только что рассматривали. Основное отличие заключается в том, что параметры передаются не через URL, а через тело запроса. Этот метод более безопасен и пригоден для передачи конфиденциальной информации, поскольку передаваемые сведения нельзя получить из кэша на стороне клиента. Если планируется передавать параметры, имеющие отношение к аутентификации, следует использовать протокол HTTPS вместе с TLS с целью включения функции шифрования передаваемой информации. Заголовок Content-Length содержит длину тела запроса в октетах. И, наконец, заголовок Referer указывает серверу место возникновения запроса.
Пример HTTP-запроса с методом TRACE:
Рисунок 11: Запрос с использованием метода TRACE
Пример ответа на запрос с методом TRACE:
Рисунок 12: Ответ на запрос с методом TRACE
Как видно из рисунка выше, при использовании метода TRACE сервер возвращает в теле ответа все, что было отправлено в запросе. Эта функция может быть полезна в том случае, если клиенту нужно точно знать, что получено сервером. Метод TRACK выполняет ту же самую функцию, но используется при работе с сервером Microsoft IIS. Уязвимости, которые могут возникать при использовании метода TRACE, связаны с межсайтовой трассировкой (Cross-Site Tracing; XST). Этот класс брешей злоумышленник может использовать для кражи cookie или другой конфиденциальной информации (например, учетных записей), хранимых в заголовке Authorization при помощи межсайтового скриптинга (XSS).
Пример HTTP-запроса с методом PUT:
Рисунок 13: Создание простейшей страницы при помощи метода PUT
Метод PUT требует использования в запросе заголовка Content-Length. Значение этого заголовка особого значение не имеет и может быть установлено нулевым без каких-либо непредсказуемых последствий. Если директория, указанная в URL, уже существует на сервере, соответствующий ресурс будет полностью заменен. Если ресурса, указанного в URL, не существует, то будет создан новый ресурс (предполагается, что соответствующий метод реализован на сервере). Содержимое ресурса, который нужно создать, указывается в теле запроса. В примере выше создается простая html-страница.
Пример ответа на запрос с методом PUT:
Рисунок 14: Ответ с кодом об успешном создании страницы
В идеале от сервера должен прийти ответ с кодом статуса «201 Created», свидетельствующий о том, что ресурс создан. Кроме того, в HTTP-запрос можно было бы вставить заголовок «Expect: 100-continue», чтобы удостовериться, что сервер готов к обработке и не закроет сокет до того, как получит содержимое, которое вы указали в теле запроса. При использовании в запросе заголовка «Expect» в ответ может прийти один из двух кодов статуса: «100 Continue» или «417 Expectation Failed».
После ознакомления с вышеуказанной информации становится понятно, почему этот метод может стать причиной потенциальных проблем и привести к тому, что злоумышленник завладеет вашим сервером. В реальных условиях использование метода PUT разрешено нечасто, и для того, чтобы сервер принял содержимое тело запроса, необходимо наличие заголовка «Authorization».
Пример атаки показан на рисунке ниже. В этом примере в тело HTTP-запроса вставляется код шелла, который, в случае принятия запроса сервером, позволяет злоумышленнику выполнять команды.
Пример HTTP-запроса с методом PUT и вставкой кода шелла:
Рисунок 15: Пример использования кода шелла в теле запроса
Пример HTTP-запроса с методом DELETE:
Рисунок 15: Запрос на удаление ресурса при помощи метода DELETE
Пример ответа на запрос с методом DELETE:
Рисунок 16: Ответ на запрос об успешном удалении ресурса
После успешного удаления ресурса, указанного в URL, сервер должен вернуть код статуса 200 OK.
Пример HTTP-запроса с методом OPTIONS:
Рисунок 17: Запрос методов, доступных на сервере, при помощи метода OPTIONS
Пример ответа на запрос с методом OPTIONS:
Рисунок 18: Ответ с перечнем методов, доступных на сервере
Цель метода OPTIONS – узнать, какие методы разрешены на сервере. При помощи этого метода нельзя нанести какой-либо ущерб, а только собрать нужную информацию. Важно отметить, что содержимое заголовка «Allow» в заголовке ответа часто содержит методы, разрешенные не на сервере, а на прокси-сервере в случае, если трафик проходит через туннель.
В данной статье была представлена информация относительно использования HTTP-сообщений и методов, реализованных в протоколе HTTP/1.1. Кроме того, затрагивалась информация о возможных сценариях атак против веб-приложений при помощи этих методов. Эти сведения могут помочь вам в разработке сценариев пентестов. Надеемся, что после ознакомления с этой заметкой, вы стали лучше понимать механизмы функционирования и потоков данных протокола HTTP.