El contestador de @ssnepenthe tiene razón al decir que el gancho que está utilizando no es el correcto en la solicitud entrante.
La información de solicitud está disponible de inmediato para PHP, por lo que puede utilizar el primer enlace disponible para verificarlos. Y si desea hacer esto en el contexto de la API de solicitud, debe usar el primer enlace de una solicitud de API REST. 'rest_pre_dispatch'
sugerido por @ssnepenthe está bien, tal vez otra opción podría ser la rest_authentication_errors
que le permitiría devolver un error en caso de que algo esté mal.
Pero Jack Johansson tiene razón al decir que los encabezados HTTP (como el encabezado de referencia utilizado en la respuesta de @ ssnepenthe) no son confiables, ya que el cliente puede cambiarlos fácilmente. Entonces sería como poner un guardia de seguridad frente a una puerta que solo pregunta "¿es seguro dejarte entrar?" a cualquiera que quiera entrar: eso no va a funcionar.
Pero la solución que propuso la respuesta de Jack Johansson (un nonce) tampoco es una solución real: el objetivo principal de nonces es cambiar con el tiempo, y un punto final API público no puede tener cosas que cambien en función del tiempo. Además, los WP nonces son confiables solo cuando hay un usuario conectado, lo que podría no ser el caso para una API pública y si un usuario está conectado, probablemente no haya razón para verificar el dominio entrante: confía en el usuario, no en el máquina de usuario.
¿Entonces lo que hay que hacer?
Bueno, incluso si los encabezados HTTP no son confiables, no toda la información disponible $_SERVER
proviene de encabezados.
Normalmente, todos los $_SERVER
valores cuyas claves comienzan con las que comienzan HTTP_
provienen de encabezados y deben tratarse como entradas inseguras del usuario .
Pero, por ejemplo, $_SERVER['REMOTE_ADDR']
contiene la dirección IP utilizada para la conexión TCP a su servidor, lo que significa que es confiable 1 .
Lo que también significa que:
- configurar correctamente el servidor para generar el
$_SERVER['REMOTE_HOST']
valor (por ejemplo, en Apache necesitará HostnameLookups On
dentro de su httpd.conf
) ese valor
- usando
gethostbyaddr
para hacer una búsqueda inversa de DNS para resolver el nombre de dominio de la IP almacenada en$_SERVER['REMOTE_ADDR']
usted podría obtener bastante fiable un nombre de host que se puede utilizar para comprobar en contra de una lista blanca (para el código, se puede adaptar el código de aswer @ de ssnepenthe donde debería reemplazar $referer = $request->get_header('referer')
con $referer = gethostbyaddr($_SERVER['REMOTE_ADDR'])
).
Pero hay un problema .
Si su servidor web está detrás de un proxy inverso (una solución bastante común, en realidad), la conexión TCP al servidor web en realidad la realiza el proxy, por $_SERVER['REMOTE_ADDR']
lo que será la IP del proxy y no la IP del cliente que envió la solicitud originalmente.
La IP de solicitud original en tales casos generalmente está disponible como $_SERVER['HTTP_X_FORWARDED_FOR']
, pero ser uno de esos $_SERVER
valores que comienzan con HTTP_
ella no es realmente confiable.
Por lo tanto, si su servidor web está detrás de un proxy inverso 2, incluso el $_SERVER['REMOTE_ADDR']
no sería útil para dicha protección y una lista blanca basada en el dominio solo podría implementarse en el nivel del proxy.
En resumen, una solución confiable para la seguridad de los puntos finales API debe implementarse utilizando algún mecanismo de autenticación real (por ejemplo, oAuth) o debe hacerse actuando directamente en la configuración del servidor y no a nivel de aplicación.
Notas
1 Bueno, en teoría, podría romperse si alguien piratea su ISP o si un atacante actúa desde dentro de su LAN, en ambos casos hay muy poco que pueda hacer para estar seguro.
2 Si no sabe si está detrás de un proxy inverso, puede enviar una solicitud desde su PC local y verificar si $_SERVER['REMOTE_ADDR']
el servidor coincide con la IP local de la PC y también si $_SERVER['HTTP_X_FORWARDED_FOR']
está presente y si coincide con la IP local de la PC.