Заборона 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, викидається виняток, який потрапляє у блок лову.

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
@Bob, я зробив це в .NET 2.0 у Visual C # 2005 Express і не зіткнувся з жодною з цих проблем. Він надсилає саме те, що я набираю. Тому вони, мабуть, змінили це в більш пізній версії.
developerwjk

1
@Bob, Лол. Документація Microsoft неправильна / оманлива. Для версії .NET 2.0 вони також кажуть: "Властивість методу можна встановити на будь-яке з дієслів протоколу 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було вперше визначено в API 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простим мережним з'єднанням працювало кожен раз, тоді як 400 HTTP-код повинен був бути отриманий.

Наприклад :

$ { 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 : "Метод запиту залежить від регістру." § 4 RFC 7231 : "За умовами, стандартизовані методи визначаються у великих літерах США-ASCII". Далі йде той самий список у вашій відповіді.
Боб

1
Код статусу відповіді насправді повинен бути 405 Метод не дозволений.
Лежати Райан

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

@XavierLucas: використання методу малих регістрів не є синтаксичною помилкою, перевірте розділ 5 RFC2616 . У 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.