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