Không cho phép các phương thức HTTP trên Tomcat có phân biệt chữ hoa chữ thường?


11

Tôi đã đặt các tệp sau trong tệp web.xml của ứng dụng của mình để cố gắng không cho phép PUT, DELETE, v.v.:

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

Được rồi, vậy bây giờ:

Nếu tôi thực hiện một yêu cầu với phương pháp DELETEtôi sẽ nhận lại 403.

Nếu tôi thực hiện một yêu cầu với phương pháp deletetôi sẽ nhận lại 403.

NHƯNG

Nếu tôi làm một yêu cầu với phương pháp DeLeTetôi nhận được OK!

Làm thế nào tôi có thể làm cho nó không cho phép những trường hợp không nhạy cảm?

Chỉnh sửa: Tôi đang thử nghiệm nó với chương trình 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.Textlà một hộp văn bản nơi tôi đang gõ tên phương thức. Khi có 403, một ngoại lệ được ném vào khối bắt.

Cache_test.jsp chứa:

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

Làm thế nào để bạn kiểm tra nó?
Xavier Lucas

@XavierLucas, Đã thêm câu hỏi đó
developerwjk

1
Chương trình kiểm tra của bạn là thiếu sót. HttpWebRequestsẽ không nhận biết và chuyển đổi các phương thức HTTP tiêu chuẩn thành chữ hoa. Ngoài ra, nó được ghi nhận là chỉ cho phép các phương thức HTTP tiêu chuẩn. Tùy chọn tốt nhất là sử dụng luồng TCP thô (ví dụ: trong netcat hoặc PuTTY raw hoặc telnet, v.v.).
Bob

1
@Bob, tôi đã làm điều đó trong .NET 2.0 trong Visual C # 2005 Express và không gặp phải bất kỳ vấn đề nào. Nó đang gửi chính xác những gì tôi gõ. Vì vậy, họ phải thay đổi điều đó trong một phiên bản sau.
nhà phát triển

1
@Bob, Lol. Tài liệu của Microsoft là sai / sai. Đối với phiên bản .NET 2.0, họ cũng nói "Thuộc tính Phương thức có thể được đặt thành bất kỳ động từ giao thức HTTP 1.1 nào: GET, HEAD, POST, PUT, DELETE, TRACE hoặc TÙY CHỌN." Nhưng nó không hạn chế điều đó trong bất kỳ cách nào trong thực tế.
nhà phát

Câu trả lời:


13

Bất kể hành vi không chính xác của Tomcat liên quan đến tiêu chuẩn HTTP, bạn nên sử dụng danh sách trắng để cho phép các phương thức cụ thể thay vì danh sách đen.

Ví dụ, danh sách trắng sau đây sẽ chặn tất cả các phương thức ngoại trừ phân biệt chữ hoa chữ thường GETHEAD.

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

(Lưu ý: yêu cầu Tomcat 7+. Những người sử dụng các phiên bản cũ hơn sẽ phải điều tra các giải pháp khác, ví dụ: bộ lọc servlet.)

Tham chiếu


Khi tôi làm điều đó với POST cũng được bao gồm, tôi đi đến một trang trên trang web (chỉ cần nhấp vào một liên kết hoặc đánh dấu vào nó) và nó mang lại cho tôi 405.
developerwjk

Trên thực tế, nó mang lại cho tôi Trạng thái HTTP 403 - Quyền truy cập vào tài nguyên được yêu cầu đã bị từ chối
developerwjk

Tôi đã thử nó trong tệp web.xml của máy chủ và nó đã bỏ qua các thiếu sót và chỉ chặn mọi thứ. Đã ra đó. Đã thử nó trong tệp web.xml của ứng dụng và một lần nữa, nó chỉ chặn mọi phương thức và bỏ qua các thiếu sót.
nhà phát triển

Cũng đã thử chính xác như trên nhưng lấy ra <auth-constraint />và sau đó nó chỉ cho phép mọi thứ.
developerwjk

2
@developerwjk http-method-omissionđược xác định lần đầu tiên trong Servlet API 3.0, được triển khai bởi Tomcat 7+: tomcat.apache.org/whichversion.html . Thật không may, điều này có nghĩa là điều này sẽ không hoạt động trong Tomcat 6 trở lên (lưu ý: 5 đã là EOL rồi). Bạn có thể thử giải pháp được đề xuất khác trong câu hỏi SO được liên kết khuyên bạn nên đặt hai security-constraints riêng biệt - Tôi không thể xác nhận rằng một hoạt động trong 7, vì vậy không bao gồm nó trong câu trả lời này.
Bob

13

Chà, sau khi kiểm tra nhanh qua một số máy chủ ngẫu nhiên giữ Server: Apache-Coyottechữ ký tiêu đề trong các phản hồi HTTP của họ, có vẻ như bạn đã đúng khi gửi get / HTTP/1.1\r\nHost: <target_IP>\r\n\r\nvới một kết nối netcat đơn giản hoạt động mỗi khi phải nhận được 400 mã HTTP.

Ví dụ :

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

Tôi phải nói rằng tôi hơi sốc ở đây và tôi sẽ không ngạc nhiên khi thấy hành vi đó được mở rộng cho tất cả các phương thức HTTP / 1.1 trong trường hợp đó.

Bạn nên điền báo cáo lỗi vào công cụ theo dõi lỗi của họ và gửi thư đến danh sách gửi thư thích hợp vì đó là một vi phạm xấu của RFC 2616 (xem bên dưới) với hậu quả xấu.

Phương pháp 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
Lưu ý: RFC 2616 hiện được thay thế bằng RFC 7230-7235. RFC 7230 § 3.1.1 : "Phương thức yêu cầu phân biệt chữ hoa chữ thường." RFC 7231 § 4 : "Theo quy ước, các phương thức được tiêu chuẩn hóa được xác định trong các chữ cái US-ASCII viết hoa.", Theo sau là cùng một danh sách trong câu trả lời của bạn.
Bob

1
Mã trạng thái phản hồi thực sự phải là Phương thức 405 Không được phép.
Lie Ryan

3
@LieRyan Không vì điều đó có nghĩa là mã thông báo phương thức phù hợp với RFC trong khi máy chủ không cho phép sử dụng nó trên tài nguyên này. RFC 2616 § 10.4.1: [400 Yêu cầu xấu] Máy chủ không thể hiểu được yêu cầu do cú pháp không đúng. RFC 2616 § 10.4.6 [405 Phương pháp không được phép] Các phương pháp quy định tại các Request-Line không được phép cho các tài nguyên được xác định bởi Yêu cầu-URI. Mã thông báo getkhông phải là một phương thức HTTP theo bất kỳ cách nào (xem đoạn trích của RFC 2616 § 5.1.1 ở trên)
Xavier Lucas

@XavierLucas: sử dụng phương pháp chữ thường không phải là lỗi cú pháp, hãy kiểm tra RFC2616 Phần 5 . Trong ABNF, extension-methodcó cú pháp tokenbao gồm tất cả các ký tự chữ và số và một số ký hiệu, không chỉ các phương thức được liệt kê cụ thể trong RFC. Hầu như mọi phần của HTTP đều có thể mở rộng, miễn là cả máy khách và máy chủ đều đồng ý cách chúng được mở rộng, bao gồm cả việc xác định các phương thức viết thường của bạn. Dòng yêu cầu "get / HTTP / 1.1" về mặt cú pháp là tốt, nó chỉ vi phạm RFC trong tên phương thức đó nên phân biệt chữ hoa chữ thường.
Lie Ryan

@LieRyan Ở extension-methodđây để mở cửa cho các RFC tiếp theo, đó không phải là ở đây để đưa các phương thức của riêng bạn ra khỏi phạm vi của RFC và giả vờ rằng bạn đang chạy các dịch vụ tuân thủ HTTP / 1.1. Vì vậy, 400 phải được trả về vì chưa có phương thức nào như vậy xuất hiện trong RFC mới nhất, do đó, ngày nay, một mã thông báo không hợp lệ. Nếu mã thông báo hợp lệ liên quan đến danh sách phương thức hiện tại và phía máy chủ được triển khai nhưng không được phép thì nên trả lại 405. Phải trả lại 501 trong trường hợp phương thức hợp lệ nhưng không được triển khai phía máy chủ.
Xavier Lucas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.