Non consentire i metodi HTTP su Tomcat distingue tra maiuscole e minuscole?


11

Ho inserito quanto segue nel web.xml della mia applicazione per tentare di non consentire PUT, DELETE, ecc .:

 <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, quindi adesso:

Se faccio una richiesta con il metodo di DELETEottengo un 403 indietro.

Se faccio una richiesta con il metodo di deleteottengo un 403 indietro.

MA

Se faccio una richiesta con il metodo DeLeTeottengo OK!

Come posso fare in modo che non facciano distinzione tra maiuscole e minuscole?

Modifica: lo sto testando con un programma 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è una casella di testo in cui sto digitando il nome del metodo. Quando c'è un 403, viene generata un'eccezione che viene catturata nel blocco catch.

Cache_test.jsp contiene:

<%
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());
%>

Come lo testate?
Xavier Lucas,

@XavierLucas, aggiunto alla domanda
developerwjk,

1
Il tuo programma di test è difettoso. HttpWebRequestsi è case-sensitive riconoscere e convertire i metodi HTTP standard in maiuscolo. Inoltre, è documentato come consentito solo metodi HTTP standard. L'opzione migliore è utilizzare un flusso TCP non elaborato (ad es. In netcat o PuTTY raw o telnet, ecc.).
Bob

1
@Bob, l'ho fatto in .NET 2.0 in Visual C # 2005 Express e non ho riscontrato nessuno di questi problemi. Sta inviando esattamente quello che scrivo. Quindi devono averlo cambiato in una versione successiva.
developerwjk,

1
@Bob, Lol. La documentazione di Microsoft è errata / fuorviante. Per la versione .NET 2.0 dicono anche "La proprietà Method può essere impostata su uno qualsiasi dei verbi del protocollo HTTP 1.1: GET, HEAD, POST, PUT, DELETE, TRACE o OPTIONS". Ma non si limita a questo in alcun modo nella pratica.
developerwjk,

Risposte:


13

Indipendentemente dal comportamento errato di Tomcat rispetto allo standard HTTP, è necessario utilizzare una whitelist per consentire metodi specifici anziché una blacklist.

Ad esempio, la seguente whitelist bloccherà tutti i metodi tranne il maiuscolo / minuscolo GET e 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>

(Nota: richiede Tomcat 7+. Coloro che utilizzano versioni precedenti dovranno studiare altre soluzioni, ad esempio un filtro servlet.)

arbitro


Quando lo faccio con POST incluso, vado a una pagina del sito (basta fare clic su un link o un segnalibro) e mi dà un 405.
developerwjk,

In realtà mi dà lo stato HTTP 403 - L'accesso alla risorsa richiesta è stato negato
developerwjk,

L'ho provato nel web.xml del server e ha ignorato le omissioni e bloccato tutto. L'ho preso. L'ho provato nel web.xml dell'applicazione e, di nuovo, sta semplicemente bloccando ogni metodo e ignorando le omissioni.
developerwjk,

Ho anche provato esattamente come sopra ma eliminando <auth-constraint />e quindi consente tutto.
developerwjk,

2
@developerwjk è http-method-omissionstato definito per la prima volta in Servlet API 3.0, implementato da Tomcat 7+: tomcat.apache.org/whichversion.html . Sfortunatamente, questo significa che non funzionerà in Tomcat 6 e versioni precedenti (nota: 5 è già EOL). Puoi provare l'altra soluzione proposta nella domanda SO collegata che consiglia di impostare due security-constraints separate : non ho potuto confermare che una funziona in 7, quindi non l'ho inclusa in questa risposta.
Bob,

13

Bene, dopo un rapido test su alcuni server casuali che contengono la Server: Apache-Coyottefirma dell'intestazione nelle loro risposte HTTP, sembra che tu abbia ragione perché l'invio get / HTTP/1.1\r\nHost: <target_IP>\r\n\r\ncon una semplice connessione netcat ha funzionato ogni volta mentre un codice HTTP 400 avrebbe dovuto essere ricevuto.

Per esempio :

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

Devo dire che sono un po 'scioccato qui e non sarei sorpreso di vedere quel comportamento esteso a tutti i metodi HTTP / 1.1 in questo caso.

Dovresti compilare una segnalazione di bug sul loro strumento di tracciamento dei bug e inviare una mail alla mailing list appropriata perché questa è una brutta violazione di RFC 2616 (vedi sotto) con conseguenze negative.

5.1.1 Metodo

  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
Nota: RFC 2616 è ora sostituito da RFC 7230-7235. RFC 7230 § 3.1.1 : "Il metodo di richiesta fa distinzione tra maiuscole e minuscole". RFC 7231 § 4 : "Per convenzione, i metodi standardizzati sono definiti in lettere maiuscole US-ASCII.", Seguito dallo stesso elenco nella risposta.
Bob

1
Il codice di stato della risposta dovrebbe in realtà essere 405 Metodo non consentito.
Sdraiati Ryan il

3
@LieRyan No perché ciò significherebbe che il token del metodo si adatta all'RFC mentre il server non ne consente l'utilizzo su questa risorsa. RFC 2616 § 10.4.1: [400 Bad Request] La richiesta non è stata compresa dal server a causa di una sintassi non corretta. RFC 2616 § 10.4.6 [Metodo 405 non consentito] Il metodo specificato nella riga di richiesta non è consentito per la risorsa identificata dall'URI di richiesta. Il token getnon è in alcun modo un metodo HTTP (vedere l'estratto di RFC 2616 § 5.1.1 sopra)
Xavier Lucas,

@XavierLucas: l'uso del metodo minuscolo non è un errore di sintassi, controlla la Sezione 5 di RFC2616 . Nell'ABNF, extension-methodavere la sintassi tokenche include tutti i caratteri alfanumerici e alcuni simboli, non solo i metodi specificamente elencati nell'RFC. Quasi ogni parte di HTTP è estensibile, a patto che sia il client che il server concordino su come siano troppo estesi, compresa la definizione dei propri metodi minuscoli. La riga di richiesta "get / HTTP / 1.1" va sintatticamente bene, viola solo la RFC in quel nome di metodo dovrebbe essere case sensitive.
Sdraiati Ryan il

@LieRyan extension-methodÈ qui per lasciare la porta aperta ai prossimi RFC, non è qui per ottenere i tuoi metodi aggiunti dall'ambito di RFC e fingere che stai eseguendo servizi conformi a HTTP / 1.1. Quindi un 400 dovrebbe essere restituito perché nessun metodo simile è ancora apparso nell'ultimo RFC, quindi oggi è un token non valido. Se il token era valido per quanto riguarda l'elenco dei metodi correnti e implementato sul lato server ma non consentito, è necessario restituire un 405. Un 501 dovrebbe essere restituito nel caso in cui il metodo sia valido ma non implementato sul lato server.
Xavier Lucas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.