Tal vez algo como:
header('Location: /' . $_GET['redirect']); //start forward slash guarantees domain cant change?
No, una barra diagonal hacia adelante no no lo protege contra open redirects .
Un atacante podría consultar el script como ...
https://yoursite.example/file.php?redirect=/malicious.example
... que da como resultado Location: //malicious.example
, que se trata como una URL relativa al protocolo que su navegador entenderá como una redirección a https://malicious.example
.
Esta notación también funciona para las URL en otros contextos, por ejemplo, Enlaces HTML:
'<a href="//malicious.example">...</a>'.
¿Existe una forma sencilla (no una lista blanca) de garantizar que la redirección no abandone el dominio?
Un enfoque alternativo simple a la respuesta de @ David es buscar una barra y un carácter alfanumérico posterior, o la secuencia inicial /./
. Ambos nunca pueden llevar a la representación de una URL absoluta.
Tenga en cuenta que en versiones anteriores de PHP también tenía que desinfectar un valor de encabezado proporcionado por el usuario para nuevas líneas / retornos de carro, ya que de lo contrario podría habilitar los ataques de inyección de encabezado.
De tu comentario de seguimiento:
¿Qué pasa si comenzó con un protocolo y un nombre de host? por ejemplo, header('Location: https://domain.com' . $_GET['redirect'])
hay una manera de evitar eso?
Esto solo es seguro si obliga a que el primer carácter proporcionado por el usuario sea una barra. De lo contrario, un ataque simple sería .malicious.example
, redirigiendo al subdominio controlado por el atacante https://domain.com.malicious.example
. Alternativamente, @malicious.example
también funciona, ya que convierte a domain.com
en el nombre de usuario para autenticar con el dominio malicious.example
.