Désactiver les méthodes HTTP sur Tomcat est-il sensible à la casse?

11

J'ai mis ce qui suit dans le web.xml de mon application pour tenter de refuser PUT, DELETE, etc.:

 <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, alors maintenant:

Si je fais une demande avec la méthode de DELETEje reçois un 403.

Si je fais une demande avec la méthode de deleteje reçois un 403.

MAIS

Si je fais une demande avec la méthode de DeLeTej'obtiens OK!

Comment puis-je faire en sorte qu'ils ne respectent pas la casse?

Edit: je le teste avec un programme 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.Textest une zone de texte où je tape le nom de la méthode. Lorsqu'il y a un 403, une exception est levée qui est interceptée dans le bloc catch.

Le cache_test.jsp contient:

<%
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
la source
Comment le testez-vous?
Xavier Lucas
@XavierLucas, Ajouté à la question
developerwjk
1
Votre programme de test est défectueux. HttpWebRequestsera insensible à la casse reconnaître et convertir des méthodes HTTP standard en majuscules. De plus, il est documenté comme n'autorisant que les méthodes HTTP standard. La meilleure option consiste à utiliser un flux TCP brut (par exemple dans netcat, ou PuTTY raw, ou telnet, etc.).
Bob
1
@Bob, je l'ai fait dans .NET 2.0 dans Visual C # 2005 Express et je n'ai rencontré aucun de ces problèmes. Il envoie exactement ce que je tape. Ils ont donc dû changer cela dans une version ultérieure.
developerwjk
1
@Bob, Lol. La documentation de Microsoft est erronée / trompeuse. Pour la version .NET 2.0, ils disent également "La propriété Method peut être définie sur n'importe lequel des verbes de protocole HTTP 1.1: GET, HEAD, POST, PUT, DELETE, TRACE ou OPTIONS." Mais cela ne se limite en aucune façon dans la pratique.
developerwjk

Réponses:

13

Indépendamment du comportement incorrect de Tomcat en ce qui concerne la norme HTTP, vous devez utiliser une liste blanche pour autoriser des méthodes spécifiques plutôt qu'une liste noire.

Par exemple, la liste blanche suivante bloquera toutes les méthodes sauf la casse GET et 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>

(Remarque: nécessite Tomcat 7+. Ceux qui utilisent des versions plus anciennes devront rechercher d'autres solutions, par exemple un filtre de servlet.)

Réf.

Bob
la source
Lorsque je fais cela avec POST également inclus, je vais sur une page du site (il suffit de cliquer sur un lien ou un signet) et cela me donne un 405.
developerwjk
En fait, cela me donne le statut HTTP 403 - L'accès à la ressource demandée a été refusé
developerwjk
Je l'ai essayé dans le web.xml du serveur, et il a ignoré les omissions et a tout bloqué. Je l'ai retiré. Je l'ai essayé dans le web.xml de l'application, et encore une fois, il bloque simplement chaque méthode et ignore les omissions.
developerwjk
Également essayé exactement comme ci-dessus mais en sortant <auth-constraint />et puis il permet tout simplement.
developerwjk
2
@developerwjk a http-method-omissionété défini pour la première fois dans Servlet API 3.0, qui est implémenté par Tomcat 7+: tomcat.apache.org/whichversion.html . Malheureusement, cela signifie que cela ne fonctionnera pas dans Tomcat 6 et versions antérieures (remarque: 5 est déjà en fin de vie). Vous pouvez essayer l'autre solution proposée dans la question SO liée qui recommande de définir deux security-constraints distincts - je n'ai pas pu confirmer que l'un fonctionne en 7, donc ne l'incluez pas dans cette réponse.
Bob
13

Eh bien, après des tests rapides sur certains serveurs aléatoires détenant la Server: Apache-Coyottesignature d'en-tête dans leurs réponses HTTP, il semble que vous avez raison, car l'envoi get / HTTP/1.1\r\nHost: <target_IP>\r\n\r\navec une simple connexion netcat a fonctionné à chaque fois alors qu'un code HTTP 400 aurait dû être reçu.

Par exemple :

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

Je dois dire que je suis un peu choqué ici et je ne serais pas surpris de voir ce comportement étendu à toutes les méthodes HTTP / 1.1 dans ce cas.

Vous devez remplir un rapport de bogue sur leur outil de suivi des bogues et envoyer un e-mail à la liste de diffusion appropriée car c'est une vilaine violation de la RFC 2616 (voir ci-dessous) avec de mauvaises conséquences.

5.1.1 Méthode

  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
la source
3
Remarque: RFC 2616 est maintenant remplacé par RFC 7230-7235. RFC 7230 § 3.1.1 : "La méthode de demande est sensible à la casse." RFC 7231 § 4 : "Par convention, les méthodes normalisées sont définies en lettres US-ASCII tout en majuscules.", Suivi de la même liste dans votre réponse.
Bob
1
Le code d'état de réponse doit en fait être la méthode 405 non autorisée.
Lie Ryan
3
@LieRyan Non, car cela signifierait que le jeton de méthode correspond au RFC tandis que le serveur ne permet pas qu'il soit utilisé sur cette ressource. RFC 2616 § 10.4.1: [400 Bad Request] La requête n'a pas pu être comprise par le serveur en raison d'une syntaxe incorrecte. RFC 2616 § 10.4.6 [Méthode 405 non autorisée] La méthode spécifiée dans la ligne de demande n'est pas autorisée pour la ressource identifiée par l'URI de demande. Le jeton getn'est en aucun cas une méthode HTTP (voir l'extrait de RFC 2616 § 5.1.1 ci-dessus)
Xavier Lucas
@XavierLucas: l'utilisation de la méthode des minuscules n'est pas une erreur de syntaxe, consultez la section 5 de la RFC2616 . Dans l'ABNF, extension-methodayez la syntaxe tokenqui inclut tous les caractères alphanumériques et certains symboles, pas seulement les méthodes spécifiquement énumérées dans le RFC. Presque toutes les parties de HTTP sont extensibles, tant que le client et le serveur conviennent de la manière dont ils doivent également être étendus, y compris la définition de vos propres méthodes en minuscules. La ligne de requête "get / HTTP / 1.1" est syntaxiquement correcte, elle viole simplement le RFC dans ce nom de méthode qui doit être sensible à la casse.
Lie Ryan
@LieRyan The extension-methodest là pour laisser la porte ouverte aux prochains RFC, ce n'est pas ici pour obtenir vos propres méthodes ajoutées hors de la portée de RFC et prétendre que vous exécutez des services conformes HTTP / 1.1. Donc, un 400 devrait être retourné car aucune méthode de ce type n'est encore apparue dans le dernier RFC, c'est donc aujourd'hui un jeton non valide. Si le jeton était valide concernant la liste de méthodes actuelle et implémenté côté serveur mais non autorisé, un 405 doit être renvoyé. Un 501 doit être retourné si la méthode est valide mais n'est pas implémentée côté serveur.
Xavier Lucas