Re: Об одной малоизвестной уязвимости в веб сайтах
Gena Makhomed
gmm at csdoc.com
Mon Jun 16 20:20:57 UTC 2014
On 16.06.2014 15:00, Maxim Dounin wrote:
>> озвученные в RFC 7230 требования к клиенту:
>>
>> http://tools.ietf.org/html/rfc7230#section-5.4
>>
>> A client MUST send a Host header field in all HTTP/1.1 request
>> messages. If the target URI includes an authority component, then a
>> client MUST send a field-value for Host that is identical to that
>> authority component, excluding any userinfo subcomponent and its "@"
>> delimiter (Section 2.7.1).
>>
>> - это ведь требования к синтаксису, которые обязательны для выполнения.
>
> Нет, это не требования к синтаксису, это требования к семантике.
Запись target URI в виде valid request message - это разве не syntax?
http://tools.ietf.org/html/rfc7231#section-2
When a client constructs an HTTP/1.1 request message, it sends the
target URI in one of various forms, as defined in (Section 5.3 of
[RFC7230]). When a request is received, the server reconstructs an
effective request URI for the target resource (Section 5.5 of
[RFC7230]).
One design goal of HTTP is to separate resource identification from
request semantics, which is made possible by vesting the request
semantics in the request method (Section 4) and a few
request-modifying header fields (Section 5).
"effective request URI" - это именно что resource identification.
Они ведь разнесли "syntax" и "semantics" по двум отдельным документам:
RFC 7230: Message Syntax and Routing
RFC 7231: Semantics and Content
>> http://tools.ietf.org/html/rfc7231#section-6.5.1
>>
>> 6.5.1. 400 Bad Request
>>
>> The 400 (Bad Request) status code indicates that the server cannot or
>> will not process the request due to something that is perceived to be
>> a client error (e.g., malformed request syntax, invalid request
>> message framing, or deceptive request routing).
>>
>> Следовательно, сервер имеет право вернуть 400 статус,
>> если получит запрос с разными authority component
>> в заголовке Host и в absolute Request URI ?
>
> Сервер имеет право вернуть 400 более или менее в любой момент.
Да, но здесь явно указывается, когда сервер возвращает 400:
в случае client error, например, "malformed request syntax"
или "deceptive request routing" - эти две причины подходят.
>> Кроме того, в разделе 5.5. Effective Request URI
>> http://tools.ietf.org/html/rfc7230#section-5.5
>>
>> даже прямо говорят, что запрос может быть misdirected,
>> deliberately or accidentally, и что origin server должен
>> сам решить, обрабатывать такой запрос или нет, потому что
>> "it might indicate an attempt to bypass security filters,
>> trick the server into delivering non-public content,
>> or poison a cache."
>>
>> именно это ведь и происходит в случае запроса
>>
>> GET http://apple.com/ HTTP/1.1
>> Host: samsung.com
>>
>> Разве ответить на такой запрос 400-м статусом не будет лучше?
>
> Это зависит от многих факторов. Вот тут Валентин давеча
> напрограммировал возврат 400, если имя, указанное в SNI, не
> совпадало с именем, используемым в запросе, ибо RFC 6066 говорит:
>
> ... If the server_name is
> established in the TLS session handshake, the client SHOULD NOT
> attempt to request a different server name at the application layer.
>
> Так пришлось распрограмировать обратно - потому что Chrome
> использует "a different server name at the application layer",
> когда считает нужным/возможным.
"SHOULD NOT" - это не запрет, а только лишь рекомендация:
http://tools.ietf.org/html/rfc2119#section-4
так что формально и фактически Chrome ничего не нарушает.
В обсуждаемой выше ситуации написано совсем иначе: "MUST".
http://tools.ietf.org/html/rfc2119#section-1
и если клиент этого не сделал - он сам прислал невалидный запрос,
так что ответить 400-м статусом на такой запрос - вполне разумно.
да и в RFC 7230 об этом тоже есть (про поведение хрома):
http://tools.ietf.org/html/rfc7230#section-2.3
server MUST NOT assume that two requests on the same connection are
from the same user agent unless the connection is secured and
specific to that agent. Some non-standard HTTP extensions (e.g.,
[RFC4559]) have been known to violate this requirement, resulting in
security and interoperability problems.
> То, как ведёт себя nginx по умолчанию - вполне себе безопасно,
> и проблемы нет. Какая-либо проблема появляется тогда и только
> тогда, когда администратор начинает писать в конфиге $http_host,
> не думая о последствиях. Есть мнение, что совсем простое решение
> этой проблемы - не делать так (c) анекдот.
Когда nginx выполняет роль origin server или HTTP reverse proxy
- тогда проблем действительно нет, но когда он выполняет роль
"gateway" и communicates с backend`ом по протоколу FastCGI -
тогда получаются очень неприятные проблемы.
Причина проблем: malformed request syntax,
который не получается корректным образом передать на backend.
Что мешает в этой ситуации вернуть 400 статус? Вместо того,
чтобы отсылать на backend невалидный запрос, интерпретируя
клиентский запрос не по спецификации HTTP/1.1 а по спецификации
CGI/1.1, которая не согласуется со спецификацией протокола HTTP/1.1.
Ничего ведь не сломается и на backend не уйдет misdirected запрос.
И даже отдельной директивы никакой не надо будет создавать для этого.
Никакой легальный клиент не пострадает от этого изменения в nginx,
потому что никто кроме взломщиков не создает таких misdirected запросов,
которые не соответствуют обязательным требованиям к клиентским запросам.
--
Best regards,
Gena
Подробная информация о списке рассылки nginx-ru