Запрещение методов 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());
%>
developerwjk
источник
Как вы это тестируете?
Ксавье Лукас
@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 должен быть возвращен, если метод действителен, но не реализован на стороне сервера.
Ксавье Лукас