Запрещение методов HTTP на Tomcat чувствительно к регистру?


11

Я поместил следующее в web.xml моего приложения, чтобы попытаться запретить PUT, DELETE и т.д .:

 <security-constraint>
 <web-resource-collection>
  <web-resource-name>restricted methods</web-resource-name>
  <url-pattern>/*</url-pattern>
  <http-method>DELETE</http-method>
  <http-method>PUT</http-method>
  <http-method>SEARCH</http-method>
  <http-method>COPY</http-method>
  <http-method>MOVE</http-method>
  <http-method>PROPFIND</http-method>
  <http-method>PROPPATCH</http-method>
  <http-method>MKCOL</http-method>
  <http-method>LOCK</http-method>
  <http-method>UNLOCK</http-method>
  <http-method>delete</http-method>
  <http-method>put</http-method>
  <http-method>search</http-method>
  <http-method>copy</http-method>
  <http-method>move</http-method>
  <http-method>propfind</http-method>
  <http-method>proppatch</http-method>
  <http-method>mkcol</http-method>
  <http-method>lock</http-method>
  <http-method>unlock</http-method>
 </web-resource-collection>
 <auth-constraint />
 </security-constraint>

Хорошо, теперь:

Если я делаю запрос с методом DELETEя получаю 403 обратно.

Если я делаю запрос с методом deleteя получаю 403 обратно.

НО

Если я делаю запрос с методом, DeLeTeя получаю ОК!

Как я могу запретить эти нечувствительные к регистру?

Изменить: я тестирую его с помощью программы на C #:

    private void button1_Click(object sender, EventArgs e)
    {
        textBox1.Text = "making request";
        System.Threading.Thread.Sleep(400);
        WebRequest req = WebRequest.Create("http://serverurl/Application/cache_test.jsp");
        req.Method = txtMethod.Text;
        try
        {
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();

            textBox1.Text = "Status: " + resp.StatusCode;

            if (resp.StatusCode == System.Net.HttpStatusCode.OK)
            {
                WebHeaderCollection header = resp.Headers;
                using (System.IO.StreamReader reader = new System.IO.StreamReader(resp.GetResponseStream(), ASCIIEncoding.ASCII))
                {
                    //string responseText = reader.ReadToEnd();
                    textBox1.Text += "\r\n" + reader.ReadToEnd();
                }
            }
        }
        catch (Exception ex)
        {
            textBox1.Text = ex.Message;
        }
    }

txtMethod.Textтекстовое поле, в котором я набираю имя метода. Когда есть 403, генерируется исключение, которое захватывается в блоке catch.

Cache_test.jsp содержит:

<%
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma","no-cache");

out.print("Method used was: "+request.getMethod());
%>

Как вы это тестируете?
Ксавье Лукас

@XavierLucas, добавил это к вопросу
developerwjk

1
Ваша тестовая программа имеет недостатки. HttpWebRequestбудет без учета регистра распознавать и преобразовывать стандартные методы HTTP в верхний регистр. Кроме того, он задокументирован как разрешающий только стандартные методы HTTP. Наилучшим вариантом является использование необработанного потока TCP (например, в netcat или PuTTY raw, или telnet и т. Д.).
Боб

1
@ Боб, я сделал это в .NET 2.0 в Visual C # 2005 Express и не столкнулся ни с одной из этих проблем. Он посылает именно то, что я печатаю. Таким образом, они должны были изменить это в более поздней версии.
developerwjk

1
@Bob, Lol. Документация Microsoft неверна / вводит в заблуждение. Для версии .NET 2.0 они также говорят: «Свойство Method может быть установлено на любой из глаголов протокола HTTP 1.1: GET, HEAD, POST, PUT, DELETE, TRACE или OPTIONS». Но это никак не ограничивается этим на практике.
developerwjk

Ответы:


13

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

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

<security-constraint>
    <web-resource-collection>
        <web-resource-name>restricted methods</web-resource-name>
        <url-pattern>/*</url-pattern>
        <http-method-omission>GET</http-method-omission>
        <http-method-omission>HEAD</http-method-omission>
    </web-resource-collection>
    <auth-constraint />
</security-constraint>

(Примечание: требуется Tomcat 7+. Те, кто использует более старые версии, должны будут исследовать другие решения, например, фильтр сервлетов.)

ссылка


Когда я делаю это с включенным POST, я перехожу на страницу сайта (просто щелкаю ссылку или закладку на нее), и это дает мне 405.
developerwjk

На самом деле это дает мне статус HTTP 403. - Доступ к запрошенному ресурсу был запрещен
developerwjk

Я попробовал это в web.xml сервера, и он проигнорировал упущения и просто заблокировал все. Взял это. Попробовал его в приложении web.xml, и опять же, он просто блокирует каждый метод и игнорирует пропуски.
developerwjk

Также попробовал точно так же как выше, но вынимающий <auth-constraint />и тогда это только позволяет все.
developerwjk

2
@developerwjk http-method-omissionвпервые был определен в Servlet API 3.0, который реализован Tomcat 7+: tomcat.apache.org/whichversion.html . К сожалению, это означает, что это не будет работать в Tomcat 6 и старше (примечание: 5 уже EOL). Вы можете попробовать другое предложенное решение в связанном вопросе SO, который рекомендует установить два отдельных security-constraints - я не смог подтвердить, что один работает в 7, поэтому не включил его в этот ответ.
Боб

13

Что ж, после быстрого тестирования на некоторых случайных серверах, содержащих Server: Apache-Coyotteподпись заголовка в их ответах HTTP, кажется, что вы правы, так как отправка get / HTTP/1.1\r\nHost: <target_IP>\r\n\r\nс простым соединением netcat работала каждый раз, когда должен был быть получен код HTTP 400.

Например :

$ { echo -en "get / HTTP/1.1\r\nHost: <target_IP>:8080\r\n\r\n" ; } | nc <target_IP> 8080

01:14:58.095547 IP 192.168.1.3.57245 > <target_IP>.8080: Flags [P.], seq 1:42, ack 1, win 115, options [nop,nop,TS val 4294788321 ecr 0], length 41
E..]C.@.@..Y......p.....A..v.......s.......
..D.....get / HTTP/1.1
Host: <target_IP>:8080

[...]

01:14:58.447946 IP <target_IP>.8080 > 192.168.1.3.57245: Flags [.], seq 1:1409, ack 43, win 65494, options [nop,nop,TS val 7981294 ecr 4294787971], length 1408
E...f...i.....p.............A..............
.y....C.HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Transfer-Encoding: chunked
Date: Tue, 27 Jan 2015 00:15:14 GMT

Должен сказать, что я немного шокирован, и я не удивлюсь, если в таком случае это поведение распространится на все методы HTTP / 1.1.

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

5.1.1 Метод

  The Method  token indicates the method to be performed on the
  resource identified by the Request-URI. The method is case-sensitive.

      Method         = "OPTIONS"                ; Section 9.2
                     | "GET"                    ; Section 9.3
                     | "HEAD"                   ; Section 9.4
                     | "POST"                   ; Section 9.5
                     | "PUT"                    ; Section 9.6
                     | "DELETE"                 ; Section 9.7
                     | "TRACE"                  ; Section 9.8
                     | "CONNECT"                ; Section 9.9
                     | extension-method
      extension-method = token

3
Примечание: RFC 2616 теперь заменен RFC 7230-7235. RFC 7230 § 3.1.1 : «Метод запроса чувствителен к регистру». RFC 7231 § 4 : «По стандарту стандартные методы определяются заглавными буквами US-ASCII в верхнем регистре», за которым следует тот же список в вашем ответе.
Боб

1
Код статуса ответа на самом деле должен быть 405 Метод не разрешен.
Ли Райан

3
@LieRyan Нет, потому что это означает, что маркер метода соответствует RFC, в то время как сервер не позволяет использовать его на этом ресурсе. RFC 2616 § 10.4.1: [400 Bad Request] Запрос не может быть понят сервером из-за неправильного синтаксиса. RFC 2616 § 10.4.6 [405 Method Not Allowed] метод , указанный в строке запроса, не разрешен для ресурса , идентифицированного Request-URI. Токен никоим образом не является методом HTTP (см. Выдержку из RFC 2616 § 5.1.1 выше)get
Ксавье Лукас,

@XavierLucas: использование строчных букв не является синтаксической ошибкой, см. RFC2616, раздел 5 . В ABNF extension-methodесть синтаксис, tokenкоторый включает все буквенно-цифровые символы и некоторые символы, а не только методы, специально перечисленные в RFC. Почти каждая часть HTTP является расширяемой, если и клиент, и сервер соглашаются с тем, как они слишком расширяются, включая определение ваших собственных строчных методов. Строка запроса "get / HTTP / 1.1" синтаксически хороша, она просто нарушает RFC, так как имя метода должно быть чувствительным к регистру.
Ли Райан

@LieRyan extension-methodЗдесь, чтобы оставить дверь открытой для следующих RFC, это не для того, чтобы добавить свои собственные методы из области RFC и притвориться, что вы используете службы, совместимые с HTTP / 1.1. Таким образом, 400 должно быть возвращено, потому что такой метод еще не появился в последнем RFC, таким образом, сегодня это недействительный токен. Если токен действителен в отношении текущего списка методов и реализован на стороне сервера, но не разрешен, то следует вернуть 405. 501 должен быть возвращен, если метод действителен, но не реализован на стороне сервера.
Ксавье Лукас
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.