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_errors
cho 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 $_SERVER
giá 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ó là đá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 On
bê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 $_SERVER
giá 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.