Czy wyłączenie metod HTTP w Tomcat rozróżnia duże i małe litery?

11

W pliku web.xml mojej aplikacji umieściłem następujące informacje, aby spróbować zabronić PUT, DELETE itp .:

 <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>

Ok, więc teraz:

Jeśli zrobię zapytanie metodą DELETE, otrzymam z powrotem 403.

Jeśli zrobię zapytanie metodą delete, otrzymam z powrotem 403.

ALE

Jeśli zrobię zapytanie metodą DeLeTe, dostanę OK!

Jak mogę sprawić, że nie będzie uwzględniana wielkość liter?

Edycja: Testuję to za pomocą programu 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.Textto pole tekstowe, w którym wpisuję nazwę metody. Gdy jest 403, generowany jest wyjątek, który zostaje złapany w bloku catch.

Plik cache_test.jsp zawiera:

<%
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
źródło
Jak to testujesz?
Xavier Lucas
@XavierLucas, Dodał to do pytania
developerwjk
1
Twój program testowy jest wadliwy. HttpWebRequestbędzie rozróżniana wielkość liter rozpoznać i konwertować standardowych metod HTTP do wielkich liter. Dodatkowo udokumentowano, że zezwala tylko na standardowe metody HTTP. Najlepszą opcją jest użycie surowego strumienia TCP (np. W netcat, PuTTY raw lub telnet itp.).
Bob
1
@ Bob, zrobiłem to w .NET 2.0 w Visual C # 2005 Express i nie napotkałem żadnego z tych problemów. Wysyła dokładnie to, co wpisuję. Musieli więc to zmienić w późniejszej wersji.
developerwjk
1
@Bob, Lol. Dokumentacja Microsoft jest błędna / myląca. W przypadku wersji .NET 2.0 mówią także: „Właściwość Method może być ustawiona na dowolne z czasowników protokołu HTTP 1.1: GET, HEAD, POST, PUT, DELETE, TRACE lub OPTIONS.” Ale w praktyce nie ogranicza się do tego.
developerwjk

Odpowiedzi:

13

Bez względu na nieprawidłowe zachowanie Tomcat w odniesieniu do standardu HTTP, powinieneś używać białej listy, aby zezwolić na określone metody, a nie czarnej listy.

Na przykład poniższa biała lista zablokuje wszystkie metody z wyjątkiem wielkości liter GET i 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>

(Uwaga: wymaga Tomcat 7+. Osoby używające starszych wersji będą musiały zbadać inne rozwiązania, np. Filtr serwletu).

Nr ref

Kok
źródło
Kiedy robię to z dołączonym POST, przechodzę do strony w witrynie (wystarczy kliknąć link lub zakładkę do niej) i daje mi 405.
developerwjk
Właściwie daje mi status HTTP 403 - Odmówiono dostępu do żądanego zasobu
developerwjk
Próbowałem tego w pliku web.xml serwera i zignorowałem pominięcia i po prostu wszystko zablokowałem. Wyjąłem to. Wypróbowałem to w pliku web.xml aplikacji i znowu, po prostu blokuje każdą metodę i ignoruje pominięcia.
developerwjk
Próbowałem również dokładnie tak, jak powyżej, ale wyjmowanie, <auth-constraint />a następnie po prostu pozwala na wszystko.
developerwjk
2
@developerwjk http-method-omissionzostał po raz pierwszy zdefiniowany w Servlet API 3.0, który jest implementowany przez Tomcat 7+: tomcat.apache.org/whichversion.html . Niestety oznacza to, że nie będzie to działać w Tomcat 6 i starszych (uwaga: 5 to już EOL). Możesz wypróbować inne proponowane rozwiązanie w połączonym pytaniu SO, które zaleca ustawienie dwóch oddzielnych security-constraints - nie mogłem potwierdzić, że jedno działa na 7, więc nie uwzględniłem go w tej odpowiedzi.
Bob
13

Cóż, po szybkich testach na losowych serwerach, które mają Server: Apache-Coyottepodpis nagłówka w swoich odpowiedziach HTTP, wydaje się, że masz rację, ponieważ wysyłanie get / HTTP/1.1\r\nHost: <target_IP>\r\n\r\nza pomocą prostego połączenia netcat działało za każdym razem, gdy powinien otrzymać kod HTTP 400.

Na przykład :

$ { 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.@[email protected].......
..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

Muszę powiedzieć, że jestem tu trochę zszokowany i nie zdziwiłbym się, gdyby w takim przypadku zachowanie objęło wszystkie metody HTTP / 1.1.

Powinieneś wypełnić raport o błędzie w narzędziu do śledzenia błędów i wysłać wiadomość na odpowiednią listę mailingową, ponieważ jest to jedno brzydkie naruszenie RFC 2616 (patrz poniżej) ze złymi konsekwencjami.

5.1.1 Metoda

  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
Xavier Lucas
źródło
3
Uwaga: RFC 2616 jest teraz zastąpiony przez RFC 7230-7235. RFC 7230 § 3.1.1 : „W metodzie żądania rozróżniana jest wielkość liter.” RFC 7231 § 4 : „Umownie, znormalizowane metody są zdefiniowane wielkimi literami US-ASCII.”, A następnie ta sama lista w twojej odpowiedzi.
Bob
1
Kod stanu odpowiedzi powinien w rzeczywistości wynosić 405 Metoda niedozwolona.
Lie Ryan
3
@LieRyan Nie, ponieważ oznaczałoby to, że token metody pasuje do RFC, podczas gdy serwer nie pozwala na użycie go w tym zasobie. RFC 2616 § 10.4.1: [400 Błędne żądanie] Serwer nie mógł zrozumieć żądania z powodu nieprawidłowej składni. RFC 2616 § 10.4.6 [405 Method Not Allowed] sposób określony w żądaniu-Line jest niedozwolone dla zasobu wskazanego przez URI żądania. Token nie jest w żaden sposób metodą HTTP (patrz fragment RFC 2616 § 5.1.1 powyżej)get
Xavier Lucas
@XavierLucas: użycie metody małych liter nie jest błędem składni, sprawdź sekcję 5 RFC2616 . W ABNF, używaj extension-methodskładni, tokenktóra zawiera wszystkie znaki alfanumeryczne i niektóre symbole, a nie tylko metody wyszczególnione w RFC. Niemal każda część HTTP jest rozszerzalna, pod warunkiem, że zarówno klient, jak i serwer uzgodnią, w jaki sposób należy je rozszerzyć, w tym zdefiniować własne metody małych liter. Wiersz żądania „get / HTTP / 1.1” jest poprawny pod względem składniowym, po prostu narusza RFC, ponieważ w nazwie metody powinna być rozróżniana wielkość liter.
Lie Ryan
@LieRyan extension-methodJest tutaj, aby zostawić otwarte drzwi dla następnych RFC, nie ma tutaj dodawać własnych metod poza zasięgiem RFC i udawać, że korzystasz z usług zgodnych z HTTP / 1.1. Tak więc należy zwrócić 400, ponieważ w najnowszej wersji RFC nie pojawiła się jeszcze żadna taka metoda, dlatego jest to dzisiaj nieprawidłowy token. Jeśli token był poprawny w odniesieniu do bieżącej listy metod i został wdrożony po stronie serwera, ale został niedozwolony, wówczas należy zwrócić 405. 501 powinno zostać zwrócone, jeśli metoda jest poprawna, ale nie została zaimplementowana po stronie serwera.
Xavier Lucas