kiểm tra url yêu cầu


9

Sử dụng WP 4.8.2

Cách tốt nhất để kiểm tra URL yêu cầu khi xử lý yêu cầu với phần còn lại là gì?

Ví dụ: một trang web nhận được yêu cầu và bạn muốn kiểm tra xem nó có đến từ URL 'được phép' hay không. Và thất bại nếu URL không được phép.

Điều này không hoạt động:

function my_check_request_url( $request, $url ) {

    $bits = parse_url( $url );

    if ( $bits['host'] != 'example.com' )
       $request = false;

    return $request;

}
add_filter( 'rest_request_from_url', 'my_check_request_url', 10, 2 );

Sau khi bình luận ra điều kiện, phản hồi vẫn được gửi. Vì vậy, tôi nghĩ rằng tôi đang sử dụng móc sai.
shanebp

Bạn đã kiểm tra những gì $request$urlvars trông giống như thông qua var_dumphoặc tương tự, tôi thấy rằng việc kiểm tra đầu vào và đầu ra luôn dẫn đến một câu trả lời thích hợp.
gian xa xôi

2
url giới thiệu dễ dàng bị làm giả và không thể được sử dụng cho bất kỳ loại bảo mật nào.
Milo

Chúng tôi đang sử dụng mã thông báo và ssl. Chúng tôi cũng muốn kiểm tra url giới thiệu, bất kể nó có thể bị làm giả hay không.
shanebp

2
Đây là một API mở cho web, điều này nói về các trọng tài là xác thực và SSL chỉ là không liên quan. Có lẽ bạn cũng đang vô hiệu hóa các biện pháp bảo vệ CORS ... Trừ khi nó chỉ có sẵn cho người dùng đã đăng nhập, điều này không có bảo mật trong đó.
Đánh dấu Kaplun

Câu trả lời:


5

Bộ lọc đó chắc chắn không phải là bộ lọc bạn đang tìm kiếm. Bộ lọc đó kích hoạt trước khi trả về kết quả WP_REST_Request::from_url()dường như là một phương thức xuất xưởng chỉ được sử dụng nội bộ để xử lý các nhúng.

Một lựa chọn tốt hơn là trả về một WP_Errorthể hiện trên rest_pre_dispatchbộ lọc .

Một số hãy cẩn thận:

Như được đề cập bởi @milo, người giới thiệu không đáng tin cậy và không nên được sử dụng để kiểm tra bảo mật.

Ngoài ra, nó không được đảm bảo để được thiết lập.

Với những cách khác, đây là một ví dụ về cách bạn có thể sử dụng rest_pre_dispatchbộ lọc để khiến yêu cầu không thành công nếu đó là từ một người giới thiệu xấu:

function wpse281916_rest_check_referer( $result, $server, $request ) {
    if ( null !== $result ) {
        // Core starts with a null value.
        // If it is no longer null, another callback has claimed this request.
        // Up to you how to handle - for this example we will just return early.
        return $result;
    }

    $referer = $request->get_header( 'referer' );

    if ( ! $referer ) {
        // Referer header is not set - If referer is required, return a WP_Error instance instead.
        return $result;
    }

    $host = wp_parse_url( $referer, PHP_URL_HOST );

    if ( ! $host ) {
        // Referer is malformed - If referer is required, return a WP_Error instance instead.
        return $result;
    }

    if ( 'mysite.com' !== $host ) {
        // Referer is set to something that we don't allow.
        return new WP_Error(
            'invalid-referer',
            'Requests must contain a valid referer',
            compact( 'referer' )
        );
    }

    // Otherwise we are good - return original result and let WordPress handle as usual.
    return $result;
}
add_filter( 'rest_pre_dispatch', 'wpse281916_rest_check_referer', 10, 3 );

4

Bất cứ điều gì bạn nhận được từ khách hàng đều được coi là đầu vào của người dùng và không đáng tin cậy. Vì tiêu đề có thể dễ dàng bị thao túng và lạm dụng, đề nghị của tôi là không sử dụng phương pháp này nếu bạn đang dựa vào nó cho dữ liệu nhạy cảm.

Nếu các yêu cầu đến từ một trang, bạn có thể có một cách tiếp cận khác. Mặt khác, bất kỳ ai cũng có thể gửi yêu cầu tới API từ nơi nào và thay đổi người giới thiệu.

Giả sử bạn có một loạt các trang được lọc là "Được phép" . Bạn chỉ có thể tạo một thông báo cho các trang này và sau đó xác thực chúng trong yêu cầu của bạn.

Nếu một thông báo tồn tại và hợp lệ, thì yêu cầu được cho phép. Nếu không, chặn nó.


4
+1 ... đó là một API .... giả định bạn chỉ nhận được cuộc gọi từ trình duyệt là vô lý.
Đánh dấu Kaplun

Có, tôi nghĩ rằng nounce là một cách tiếp cận tốt hơn vì nó không tồn tại nếu ai đó trực tiếp gửi yêu cầu tới API.
Jack Johansson

4

Asss của @ssnepenthe là đúng khi nói rằng hook bạn đang sử dụng không phải là một cái gì đó đúng trong yêu cầu đến.

Thông tin yêu cầu có sẵn ngay lập tức cho PHP, vì vậy bạn có thể sử dụng hook sớm nhất có sẵn để kiểm tra chúng. Và nếu bạn muốn làm điều này trong ngữ cảnh API yêu cầu, bạn nên sử dụng móc sớm nhất của yêu cầu API REST. 'rest_pre_dispatch'được đề xuất bởi @ssnepenthe là tốt, có thể một tùy chọn khác có thể rest_authentication_errorscho phép bạn trả lại lỗi trong trường hợp có gì đó không đúng.

Nhưng Jack Johansson đã đúng khi nói rằng các tiêu đề HTTP (như tiêu đề người giới thiệu được sử dụng trong @ ssnepenthe's aswer) không đáng tin cậy, vì chúng rất dễ bị khách hàng thay đổi. Vì vậy, nó sẽ giống như đặt một nhân viên bảo vệ trước một cánh cửa, người chỉ hỏi "có an toàn để cho bạn vào không?" cho bất cứ ai muốn đi vào: điều đó sẽ không làm việc.

Nhưng giải pháp đề xuất câu trả lời của Jack Johansson (một người không phải) cũng không phải là một giải pháp thực sự: toàn bộ quan điểm của các lực lượng là thay đổi theo thời gian và điểm cuối API công khai không thể có những thứ thay đổi theo thời gian. Hơn nữa, WP nonces chỉ đáng tin cậy khi có người dùng đăng nhập, có thể không phải là trường hợp của API công khai và nếu người dùng đã đăng nhập, có lẽ không có lý do gì để kiểm tra tên miền đến: bạn tin tưởng người dùng, không phải máy người dùng.

Vậy lam gi?

Chà, ngay cả khi các tiêu đề HTTP không đáng tin cậy, không phải tất cả thông tin có sẵn $_SERVERđều đến từ các tiêu đề.

Thông thường, tất cả các $_SERVERgiá trị có khóa bắt đầu bắt đầu HTTP_đều xuất phát từ các tiêu đề và phải được coi là đầu vào của người dùng không an toàn .

Nhưng, ví dụ, $_SERVER['REMOTE_ADDR']có chứa địa chỉ IP được sử dụng cho kết nối TCP đến máy chủ của bạn, có nghĩa là nó đáng tin cậy 1 .

Điều đó cũng có nghĩa là:

  • cấu hình đúng máy chủ để tạo $_SERVER['REMOTE_HOST']giá trị (ví dụ: trong Apache bạn sẽ cần HostnameLookups Onbên trong httpd.conf) giá trị đó
  • sử dụng gethostbyaddrđể thực hiện tra cứu DNS ngược để phân giải tên miền của IP được lưu trữ trong$_SERVER['REMOTE_ADDR']

bạn có thể có được khá đáng tin cậy một tên máy chủ mà bạn có thể sử dụng để kiểm tra đối với một danh sách trắng (đối với mã này, bạn có thể sửa lại mã từ aswer @ ssnepenthe của nơi bạn sẽ thay thế $referer = $request->get_header('referer')với $referer = gethostbyaddr($_SERVER['REMOTE_ADDR'])).

Nhưng có một vấn đề .

Nếu máy chủ web của bạn đứng sau một proxy ngược (thực tế là giải pháp khá phổ biến), kết nối TCP đến máy chủ web thực sự được tạo bởi proxy, do đó $_SERVER['REMOTE_ADDR']sẽ là IP của proxy chứ không phải IP của máy khách đã gửi yêu cầu ban đầu.

IP yêu cầu ban đầu trong các trường hợp như vậy thường có sẵn như $_SERVER['HTTP_X_FORWARDED_FOR'], nhưng là một trong những $_SERVERgiá trị bắt đầu với HTTP_nó không thực sự đáng tin cậy.

Vì vậy, nếu máy chủ web của bạn đứng sau proxy ngược 2, thậm chí điều $_SERVER['REMOTE_ADDR']đó sẽ không hữu ích cho người bảo vệ đó và danh sách trắng dựa trên tên miền chỉ có thể được triển khai ở cấp proxy.

Nói tóm lại, một giải pháp đáng tin cậy cho endpoint API đề bảo mật cần được thực hiện một trong hai sử dụng một số thực cơ chế xác thực (ví dụ OAuth) hoặc nên được thực hiện hành động trực tiếp vào cấu hình máy chủ và không phải ở mức ứng dụng.


Ghi chú

1 Về lý thuyết, nó có thể bị phá vỡ nếu ai đó hack ISP của bạn hoặc nếu kẻ tấn công hành động từ bên trong mạng LAN của bạn, trong cả hai trường hợp có rất ít điều bạn có thể làm để an toàn.

2 Nếu bạn không biết liệu mình có đứng sau proxy ngược hay không, bạn có thể gửi yêu cầu từ PC cục bộ của mình và kiểm tra xem $_SERVER['REMOTE_ADDR']trên máy chủ có khớp với IP PC cục bộ hay không $_SERVER['HTTP_X_FORWARDED_FOR']và có phù hợp với IP PC cục bộ không.


OP đang cố gắng để có được người giới thiệu, vì vậy tôi cho rằng anh ta muốn làm điều đó trên một trang, không trực tiếp ping API.
Jack Johansson

@JackJohansson thực sự là OP không bao giờ đề cập đến người giới thiệu :) Họ nói rằng họ muốn "kiểm tra xem nó có xuất phát từ URL 'được phép" hay không , có vẻ như họ đang tìm kiếm điểm cuối API trong danh sách cho các miền speficic và đoạn mã trong OP cũng giống như vậy ý tưởng với tôi
gmazzap
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.